2 Z+ K5 q6 L4 e* s/ d
通过http实现RPC命令的调用 实现添加块
: h% H* [, `) m) R1 o
查询当前所有块的信息
这里只做了两个命令 分别是get和write
源代码如下
基础功能的实现
package core- N9 f9 [% c/ v0 [ `1 c$ F) J
import (3 i& e1 y5 l5 W2 K9 V0 E3 L9 }3 ~
"crypto/sha256"
"encoding/hex"
"time"
)
//定义区块! A" u' ^7 J$ A/ @: G
type Block struct {1 }$ g3 s0 K. I
Index int64 //区块编号
- Timestamp int64 //区块时间戳
- PrevBlockHash string //上一个区块的hash值 H0 \2 p9 H& Q4 D$ p U3 _
- Hash string //当前区块哈希值
- Data string //区块数据
- }
- //计算Hash
- func calculateHash(b *Block) string {+ z1 m. M j. Q, y% \, }
- blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash, D2 W% N: y: W0 H
- hashInBytes := sha256.Sum256([]byte(blockData))
- return hex.EncodeToString(hashInBytes[:])
- }
( j- Z/ B* ]2 d* f# i
//生成新的区块9 a# |0 n+ V( t( Q$ _/ g
func GenerateNewBlock(preBlock *Block, data string) *Block {
newBlock := &Block{}
newBlock.Index = preBlock.Index + 1
newBlock.PrevBlockHash = preBlock.Hash
newBlock.Timestamp = time.Now().Unix()6 u/ i8 o- `$ K+ M w7 ~ g
newBlock.Hash = calculateHash(newBlock)% m- e1 T4 p+ c8 v, s& A+ e
newBlock.Data = data5 c) [. Y4 j6 m
return newBlock
}' {6 b$ g' x; ]4 t7 _/ p
//生成创始区块. h6 e4 N! g! p! H/ o" k3 H
func GenerateGenesisBlock() *Block {
preBlock := &Block{} z8 K8 L C9 |! @, O
preBlock.Index = -1
preBlock.Hash = ""& B2 R, @, q6 J
return GenerateNewBlock(preBlock, "Genesis Block")
}
将基础功能实现的块进行链接 实现blockchain! F) B7 X* g$ |8 l
package core$ @, Z# ?" |& v3 g- t7 r
import (9 f4 i: V( J& k1 r% r8 p, P: y
"fmt"& o1 g. p* }" G8 [
"log", U- b0 Z# W* @- q4 @% L
)5 w: z T* J" c; Z* @
0 F5 ~6 v' T/ ?
//定义区块链
type BlockChain struct {" B& v* C% W$ E6 ~; ?. ^8 p. K6 e
Blocks []*Block
}! D/ R' F) J1 P
( X( [+ D: ?1 W, Y1 U# e7 ~" `4 {
//创建一个区块链
func NewBlockChain() *BlockChain { v/ Y4 _* D1 I' y- v$ V
genesisBlock := GenerateGenesisBlock()% X$ f Z# K4 Z1 l$ q2 ~
blockChain := &BlockChain{}$ B. w$ D# ?- K* g
blockChain.AppendBlock(genesisBlock)
return blockChain4 V1 W6 F! [3 w4 Z; O i
}
s- k* @( Q0 q( \4 N0 e, h+ N6 p
//记录区块数据1 j( u, R5 z- h& c, V1 A
func (bc *BlockChain) SendData(data string) {+ s2 s2 G w% {* K. S% t5 |
preBlock := bc.Blocks[len(bc.Blocks)-1]
newBlock := GenerateNewBlock(preBlock, data)- g" I. G K% Y0 x2 d' }+ s
bc.AppendBlock(newBlock)
}
4 Y* I4 O/ ]7 H/ s Y9 u) m! ~
//往区块链添加区块
func (bc *BlockChain) AppendBlock(newBlock *Block) {
if len(bc.Blocks) == 0 {( ^% @4 k& g, K9 k# s# P1 D' D# O
bc.Blocks = append(bc.Blocks, newBlock)
return$ K3 t8 d% l3 ~; s% Y$ g
}" ~0 O+ [/ x9 @$ U' _
if isValid(newBlock, bc.Blocks[len(bc.Blocks)-1]) {( A: U( f& ^3 i7 q
bc.Blocks = append(bc.Blocks, newBlock)& u1 M* Z' |, Y0 u7 N+ U
} else {
log.Fatal("invalid block") l( x8 r% r- F& y7 O
}( Q) ]) n) T/ K2 ~5 t
return( j( b: ^8 H: G7 {
}
//输出区块链信息3 Y: p5 A+ C5 P# V+ U. k6 q3 @ q
func (bc *BlockChain) Print() {
for _, block := range bc.Blocks {
fmt.Printf("Index : %d\n", block.Index)' _/ E7 m+ T( j
fmt.Printf("Prev.Hash : %s\n", block.PrevBlockHash)
fmt.Printf("Curr.Hash : %s\n", block.Hash)- [: b9 h" r, u2 w3 p4 D1 p* s
fmt.Printf("Curr.Data : %s\n", block.Data): M: O! D# W4 p, a& ~: e$ e3 L. v
fmt.Printf("Curr.Timestamp : %d\n", block.Timestamp)
fmt.Println("==========================================")
}
}; i! E. F7 ~. k3 k' L4 L+ l
( g% k# M; l% T+ C
//验证区块
func isValid(newBlock *Block, oldBlock *Block) bool {- H( w: X" y/ C3 F, ]% U. X- r
if newBlock.Index-1 != oldBlock.Index {
return false7 c. t4 `' E- b7 v0 ^3 V0 X
}7 D/ M t! u: L: j
if newBlock.PrevBlockHash != oldBlock.Hash {
return false
}. _# q. d* h$ b* j5 H; \
if calculateHash(newBlock) != newBlock.Hash {
return false
}
return true
}
实现RPC接口的交互
- package main
-
- import (
- "encoding/json"9 Z" a- d1 d9 j; v8 I7 B* H
- "BlockChain/core"
- "io"
- "net/http"( O% E* i' M E$ u1 y+ C3 R
- )
- 2 Q6 q/ {% L! H- d/ h( r
- var blockChain *core.BlockChain
-
- func run() {2 p7 x3 w$ l6 f+ {
- http.HandleFunc("/block_chain/get", blockChainGetHandle)! ?; o0 }1 {9 y- t) F7 P" @# r4 h, P
- http.HandleFunc("/block_chain/write", blockChainWriteHandle), Y* R" m1 G/ i3 u( I
- http.ListenAndServe(":8332", nil)
- }
-
- func blockChainGetHandle(w http.ResponseWriter, r *http.Request) {/ G* L* ^' n, T+ \/ i! N, v
- bytes, err := json.Marshal(blockChain)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- io.WriteString(w, string(bytes))
- }5 e3 C- y( [3 b, @: A
- * S1 O$ d1 e) n) S
- func blockChainWriteHandle(w http.ResponseWriter, r *http.Request) {" C0 m- ]. ]# t/ g( A) P
- blockData := r.URL.Query().Get("data")
- blockChain.SendData(blockData)
- blockChainGetHandle(w, r)0 h9 U6 j3 p5 M9 E$ m' b
- }
-
- func main() {
- blockChain = core.NewBlockChain() @4 F4 q2 [! y6 U& N" J: O
- run()
- }
通过两部分代码实现简易区块链的RPC调用