通过http实现RPC命令的调用 实现添加块
查询当前所有块的信息
这里只做了两个命令 分别是get和write1 ^. n9 p& c( q" H3 H9 ]6 Z6 D6 L; c
源代码如下4 |1 l8 T1 e. f4 K' k. m
基础功能的实现+ W& n% ?+ o' q& o
package core1 y4 C' c# Z3 T& ^" J
import ( S1 F/ O4 w* |) O6 z
"crypto/sha256"
"encoding/hex"! d1 R. [$ o" m) y5 l' Y
"time"0 q$ e) e9 X5 u" h) Z& T& z# c
)! A" D1 k# F f0 L0 X
//定义区块6 n0 D- p7 J/ U6 }" s% ?
type Block struct {" E. F" O5 L& b4 t, |
Index int64 //区块编号2 M& i. `4 a! |4 W7 Z/ H+ S
- Timestamp int64 //区块时间戳
- PrevBlockHash string //上一个区块的hash值8 ~7 X1 @8 ] r! c( u2 X2 p: b
- Hash string //当前区块哈希值( Z2 K, u0 d8 O* }( N) }
- Data string //区块数据
- }3 u8 w+ ]5 ]. O3 _6 \
- //计算Hash
- func calculateHash(b *Block) string {
- blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash/ O0 A1 X* S$ B l! H* e! T- Q0 I8 g
- hashInBytes := sha256.Sum256([]byte(blockData))
- return hex.EncodeToString(hashInBytes[:])- G. j( j6 i) ~# Q3 d+ ]; E
- }
//生成新的区块
func GenerateNewBlock(preBlock *Block, data string) *Block {7 g( Y3 b5 M" ]4 `& f
newBlock := &Block{}
newBlock.Index = preBlock.Index + 1
newBlock.PrevBlockHash = preBlock.Hash& \' f+ \- B6 i$ t- k1 H! _
newBlock.Timestamp = time.Now().Unix()
newBlock.Hash = calculateHash(newBlock)
newBlock.Data = data
return newBlock
}& a4 J. x; F. w7 F5 @( k& z
$ ]& l# [ t: {! W2 H8 O( `' N
//生成创始区块. @+ k2 \* t7 J3 _6 v) R4 a
func GenerateGenesisBlock() *Block {
preBlock := &Block{}
preBlock.Index = -1
preBlock.Hash = ""
return GenerateNewBlock(preBlock, "Genesis Block")
}: q; L+ L4 j. X$ S3 W7 S! L
将基础功能实现的块进行链接 实现blockchain
package core$ g- M5 J5 @. e |5 d
import (
"fmt", p3 F# g) X2 o+ @& x
"log"
)
//定义区块链
type BlockChain struct {
Blocks []*Block5 F1 {8 u1 V4 [3 k+ Z% U
}; K( i0 O/ N# v3 c7 G4 P
* ?2 l" ?2 q5 g v$ a- @
//创建一个区块链" x2 h! l! i5 J. f+ J N4 z
func NewBlockChain() *BlockChain {# L; z+ Z8 T2 b: I& M' {
genesisBlock := GenerateGenesisBlock()/ S/ M+ {- g+ g( p
blockChain := &BlockChain{}- B# l! U* K2 R' _3 e
blockChain.AppendBlock(genesisBlock)
return blockChain
}; L- p A% [# e- G8 o4 L
//记录区块数据
func (bc *BlockChain) SendData(data string) {
preBlock := bc.Blocks[len(bc.Blocks)-1]
newBlock := GenerateNewBlock(preBlock, data)! D& B, P8 Y( H9 h+ Q
bc.AppendBlock(newBlock)
}# `" x' u" f! P1 p" v( e9 X
- I& P7 ?1 {6 _( E; E3 K
//往区块链添加区块
func (bc *BlockChain) AppendBlock(newBlock *Block) {; P# h0 `! V! J0 I) _ s
if len(bc.Blocks) == 0 {
bc.Blocks = append(bc.Blocks, newBlock)
return
}
if isValid(newBlock, bc.Blocks[len(bc.Blocks)-1]) {7 r: B' F/ M' g0 Z& ~
bc.Blocks = append(bc.Blocks, newBlock)6 p4 J4 ^( Q% t( H; k8 e# N
} else {
log.Fatal("invalid block")
}
return) I- p9 Q3 V$ J+ i9 Y' G, @
}2 a" a \9 F+ a- G0 d2 |7 @
//输出区块链信息# a! d( \- T$ ^: H g7 \( T% X
func (bc *BlockChain) Print() {" N8 \1 B7 Z! D
for _, block := range bc.Blocks {
fmt.Printf("Index : %d\n", block.Index)# J6 M$ s, A9 f. q0 n9 d
fmt.Printf("Prev.Hash : %s\n", block.PrevBlockHash)3 b6 g) q1 l3 R
fmt.Printf("Curr.Hash : %s\n", block.Hash)! z/ i3 n S1 P. Y+ C8 v n: _) L
fmt.Printf("Curr.Data : %s\n", block.Data)3 B4 g, V' z- ^. Z5 @+ C
fmt.Printf("Curr.Timestamp : %d\n", block.Timestamp)+ K7 y' Y# {# N) G6 V3 G' f
fmt.Println("=========================================="); w6 g, v9 ?$ b/ w
}
}
4 u$ T- D' _" _! G/ x% V6 }
//验证区块
func isValid(newBlock *Block, oldBlock *Block) bool {
if newBlock.Index-1 != oldBlock.Index {
return false
}
if newBlock.PrevBlockHash != oldBlock.Hash {! _* l+ B9 h3 W" e* O
return false$ q) d( f4 K; O: j6 ?
}/ Z+ a3 o7 I/ k* H% \; t5 o
if calculateHash(newBlock) != newBlock.Hash {
return false! i' c. h7 l. [0 a+ {- O
}
return true
}
实现RPC接口的交互
- package main7 C5 m- u, w' Q4 [
- 0 q+ m. r# f. p
- import (
- "encoding/json"
- "BlockChain/core"* p& p. Y0 L( r& m" b
- "io", ~) e- W, x; l7 Q
- "net/http"
- )2 N! G- [! Y5 ?
- # t. P, H2 m+ h+ Y3 e
- var blockChain *core.BlockChain
-
- func run() {
- http.HandleFunc("/block_chain/get", blockChainGetHandle)4 h& c- N* I4 y. \
- http.HandleFunc("/block_chain/write", blockChainWriteHandle)
- http.ListenAndServe(":8332", nil)4 _" M+ `" b! S4 I
- }: q& `0 i! y0 N8 c A
-
- func blockChainGetHandle(w http.ResponseWriter, r *http.Request) {$ w" A6 R- _4 o
- bytes, err := json.Marshal(blockChain)& p8 P3 f% m [& g! d
- if err != nil {7 I* R* d* u4 z3 j
- http.Error(w, err.Error(), http.StatusInternalServerError)" o- _0 s: c) f
- return5 p2 M( H* a3 d5 V0 }3 |' A
- }* w0 `, u9 ]9 ~
- io.WriteString(w, string(bytes))
- }5 E) L, D, @. m- ?+ _6 |, K$ ?
- / Z+ a' u/ {; g5 w' t
- func blockChainWriteHandle(w http.ResponseWriter, r *http.Request) {
- blockData := r.URL.Query().Get("data")& Q' P1 o9 H: F# d- I& q* k
- blockChain.SendData(blockData), l, V" ]- S0 D. L1 y
- blockChainGetHandle(w, r)0 C# i3 ], s7 d% R" S
- }
-
- func main() {7 m( f* E* G- m5 l$ ~5 \7 H
- blockChain = core.NewBlockChain()- {6 h% N( X; |: a+ C4 E
- run()
- }
通过两部分代码实现简易区块链的RPC调用