通过http实现RPC命令的调用 实现添加块
& v, q, o: ~# x3 J& J/ C: ^+ ^
查询当前所有块的信息! X$ X) ^/ ]& u8 ~4 a( z
这里只做了两个命令 分别是get和write
源代码如下
基础功能的实现
; a& T# I! L, o$ A
package core0 A% Y; {5 |& Y
import (
"crypto/sha256"
"encoding/hex"
"time") e: t, w' K" s: B( n! o
)& r' _1 e& {7 S) g4 ~. _# U9 N( L
//定义区块
type Block struct {
Index int64 //区块编号. ?8 Q9 [8 b8 S {9 C$ w
- Timestamp int64 //区块时间戳
- PrevBlockHash string //上一个区块的hash值6 r, j9 B& Y( N% Y
- Hash string //当前区块哈希值7 h+ O" C' M, z4 o/ B3 v9 R9 R
- Data string //区块数据
- }" |& z/ j a: L" f3 L. K# ~
- //计算Hash
- func calculateHash(b *Block) string {
- blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash
- hashInBytes := sha256.Sum256([]byte(blockData)), y/ T) P9 T; B: k0 f
- return hex.EncodeToString(hashInBytes[:])
- }
! |; T( R; |* s5 u6 |
//生成新的区块% ~! f0 x! y: \. ?/ G4 W
func GenerateNewBlock(preBlock *Block, data string) *Block {& u+ w e8 Q) Z
newBlock := &Block{}. x" |9 o1 Y+ n% c4 r: {) n" }3 K, v
newBlock.Index = preBlock.Index + 1& a+ F' H. W( v$ t6 T9 Q
newBlock.PrevBlockHash = preBlock.Hash
newBlock.Timestamp = time.Now().Unix() E+ Q+ J/ P6 o! P- l( f3 L
newBlock.Hash = calculateHash(newBlock)
newBlock.Data = data
return newBlock2 y9 F% R: A C2 \
}
5 T' T& _8 P9 _$ D1 a6 g
//生成创始区块+ e, `; _) n7 e2 Q" p8 E
func GenerateGenesisBlock() *Block {7 N( u, j) k4 d, j$ T' v5 }
preBlock := &Block{}; A- P0 b2 W: c0 b& C$ v x; z
preBlock.Index = -1
preBlock.Hash = ""
return GenerateNewBlock(preBlock, "Genesis Block")
}
将基础功能实现的块进行链接 实现blockchain; V3 g5 W" S7 b1 F
package core9 E. p! ]" x. h1 I
P/ \7 X. Y# J9 F% o, V
import (
"fmt"# d! F6 d* b; r4 \4 [
"log"
)- O$ k. o5 T* m7 G/ ]5 @
//定义区块链
type BlockChain struct {% T5 |% U, a; f/ V, ~
Blocks []*Block
} G8 a+ \9 `" i( A0 ?; M: c* F
' x- r1 ]5 V6 @
//创建一个区块链% ~3 s# ?+ y) `/ A8 |
func NewBlockChain() *BlockChain {! |/ h; i$ `5 k
genesisBlock := GenerateGenesisBlock(), l3 R/ N% [ N
blockChain := &BlockChain{}
blockChain.AppendBlock(genesisBlock)
return blockChain
}
//记录区块数据* W) Z4 o) R1 F, m+ W6 K8 j
func (bc *BlockChain) SendData(data string) {# x9 F1 d! {0 w0 `
preBlock := bc.Blocks[len(bc.Blocks)-1]
newBlock := GenerateNewBlock(preBlock, data)! X* p4 u3 J4 y. W
bc.AppendBlock(newBlock)
}
//往区块链添加区块1 i- f, _2 o% W1 ]8 Z5 Z7 N
func (bc *BlockChain) AppendBlock(newBlock *Block) {5 y" N; F$ o/ R! `4 g
if len(bc.Blocks) == 0 {
bc.Blocks = append(bc.Blocks, newBlock)! X$ k5 h7 V9 v/ U6 g& k
return
} V) C5 I4 L! W4 L( t- e& F2 B
if isValid(newBlock, bc.Blocks[len(bc.Blocks)-1]) {& ~" B; k5 Y$ }
bc.Blocks = append(bc.Blocks, newBlock)
} else {
log.Fatal("invalid block")1 f; S0 K: h) E g) m
}
return) R; H( l- C5 J3 s
} ^3 C+ y7 L ?. s; r- X: o# q
+ F# L1 ^& \9 M# D. ~% x, K
//输出区块链信息3 o* p, x2 ~+ F
func (bc *BlockChain) Print() {
for _, block := range bc.Blocks {/ s7 I1 ~4 F5 a3 t V9 o9 [) p
fmt.Printf("Index : %d\n", block.Index): _8 R% s: t0 P3 U
fmt.Printf("Prev.Hash : %s\n", block.PrevBlockHash) n* J) ?3 a6 k( L( j
fmt.Printf("Curr.Hash : %s\n", block.Hash)
fmt.Printf("Curr.Data : %s\n", block.Data)
fmt.Printf("Curr.Timestamp : %d\n", block.Timestamp): O K6 U/ @: }2 O
fmt.Println("==========================================")
}
} Q3 {* `4 L1 [' o* B
//验证区块
func isValid(newBlock *Block, oldBlock *Block) bool {! c2 ]$ ^& ^- F
if newBlock.Index-1 != oldBlock.Index {1 g9 Q% y- S9 }6 l" ?
return false
}
if newBlock.PrevBlockHash != oldBlock.Hash {
return false5 P: [- C/ [0 I5 F, d' M
}$ ?. d; f. `% T) n" K) }+ E
if calculateHash(newBlock) != newBlock.Hash {- S9 X' n Y; u. G- r9 T
return false
}+ h( u3 a# ?) N( N
return true
}4 A4 V% @ u" V$ i4 u7 ?
实现RPC接口的交互" n. B9 c& e: i! `, Z! O
- package main
-
- import (
- "encoding/json", `* y! E& `9 P1 a1 a/ w, U
- "BlockChain/core"
- "io"# w! P8 ^ `/ G! o ~! ~' O9 r, r/ P% i
- "net/http"
- )3 B* D* ~3 {7 L# w
-
- var blockChain *core.BlockChain
- . e: @2 j, k" S1 K9 S: H. k8 i7 R1 h
- func run() {
- http.HandleFunc("/block_chain/get", blockChainGetHandle)/ b0 l) c8 z! m+ U
- http.HandleFunc("/block_chain/write", blockChainWriteHandle)/ P9 p/ V+ c( v1 a
- http.ListenAndServe(":8332", nil)4 l: L) u7 q: B1 d( E9 @
- }0 G4 a: Q& J" }7 o
- ; E: n! l3 _7 Z; O0 N8 X% e1 ~: n, K% U
- func blockChainGetHandle(w http.ResponseWriter, r *http.Request) {$ w; U( s) s. P l) i. F1 X; {9 s; `
- bytes, err := json.Marshal(blockChain). I4 o$ N. o) a$ b+ X
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)/ Z6 [/ m' o. K8 ~, \7 E
- return5 J7 Q) I, n, D- r
- }% D' E. M+ i$ D- M& }+ y( O
- io.WriteString(w, string(bytes))
- }
- % D$ ?# B9 n, b3 }
- func blockChainWriteHandle(w http.ResponseWriter, r *http.Request) {7 o# y* g. w# d1 B! g5 W+ J9 A
- blockData := r.URL.Query().Get("data")' I" r, n1 n4 E
- blockChain.SendData(blockData)
- blockChainGetHandle(w, r)
- }
- # w s- A# K. f' Q; Z% \
- func main() {! r$ D. I4 ]7 E3 J; l
- blockChain = core.NewBlockChain()# o' q Q, d5 A ?; \* q3 p
- run()* N! J" s, L9 t) z
- }
通过两部分代码实现简易区块链的RPC调用