6 W# E" k( |8 l, F
通过http实现RPC命令的调用 实现添加块# [9 j' H1 K. K+ {
7 h1 v8 _! K3 P5 N0 f1 x
查询当前所有块的信息
+ t3 Z( s" T( r3 K7 ]
这里只做了两个命令 分别是get和write) ~! l. ?+ L Q2 X( V6 X+ |: v
源代码如下1 T! s; B9 G; p4 c* z+ W
基础功能的实现
% S* t7 F' P) V& f8 a7 [
package core/ S9 H4 q1 U# {' C
import (
"crypto/sha256"* \* Q2 q. J" F5 p( a
"encoding/hex": } O2 x3 ]& _ t1 N
"time"
)
//定义区块
type Block struct {% z) Y0 ~8 D0 M8 s
Index int64 //区块编号. A/ c B- e+ m' B' }/ q
- Timestamp int64 //区块时间戳' L( G3 y6 u+ \# }2 l2 W' s/ j; I5 j( ?
- PrevBlockHash string //上一个区块的hash值
- Hash string //当前区块哈希值
- Data string //区块数据& v; c4 g0 Y, V1 I1 Q; |
- }
- //计算Hash" `1 ?0 a7 P( L' J; J
- func calculateHash(b *Block) string {1 J9 n4 _0 s7 H* | c' m8 v4 l7 G% t
- blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash
- hashInBytes := sha256.Sum256([]byte(blockData))
- return hex.EncodeToString(hashInBytes[:])& \- W$ @) T( e
- }
//生成新的区块! ?; o4 T0 H# j
func GenerateNewBlock(preBlock *Block, data string) *Block {
newBlock := &Block{}- U$ q M+ ?# k
newBlock.Index = preBlock.Index + 17 j4 y. U. Z5 S4 d% _8 N# Q
newBlock.PrevBlockHash = preBlock.Hash
newBlock.Timestamp = time.Now().Unix()0 s& f( l0 U5 d( w
newBlock.Hash = calculateHash(newBlock)
newBlock.Data = data5 C' L% u6 V5 L! | X
return newBlock) G: G& O) \2 ^8 d6 X
}
9 @& j8 N( |! W- I3 U! a) I# N
//生成创始区块$ f5 G% Q0 H2 i7 `( m7 u
func GenerateGenesisBlock() *Block {
preBlock := &Block{}
preBlock.Index = -1
preBlock.Hash = ""9 a$ d) `' y" o6 ?5 k3 h
return GenerateNewBlock(preBlock, "Genesis Block")
}; K/ Z8 M1 S/ W
将基础功能实现的块进行链接 实现blockchain0 ?3 X5 Z& L( n, B$ o2 o
package core+ W5 |+ E" e3 G+ d, m
import (3 n$ w7 V+ M2 N- W
"fmt"
"log"
)+ o: c( g$ I& {
//定义区块链
type BlockChain struct {; `9 z9 s6 W0 t3 [- o
Blocks []*Block
}& I6 P( N0 E4 F
//创建一个区块链
func NewBlockChain() *BlockChain {
genesisBlock := GenerateGenesisBlock()
blockChain := &BlockChain{}6 `0 m* P+ ~6 C& S
blockChain.AppendBlock(genesisBlock)
return blockChain. M' D4 {! a4 M9 W: w" b2 n/ e
}0 K7 z! B. x4 `' B( C# O
//记录区块数据
func (bc *BlockChain) SendData(data string) {5 V& _1 f1 w; v$ L% ?% a. J
preBlock := bc.Blocks[len(bc.Blocks)-1]
newBlock := GenerateNewBlock(preBlock, data)
bc.AppendBlock(newBlock)+ h% e6 o* I; L" u, t
}
/ Q& r0 H" M+ i9 w! v
//往区块链添加区块* Z( ~3 d) W1 g- G
func (bc *BlockChain) AppendBlock(newBlock *Block) {% w0 K5 P" m- G
if len(bc.Blocks) == 0 {
bc.Blocks = append(bc.Blocks, newBlock)# n$ s! y, Y' V# Y
return) w) q! F% D, K" |7 p8 w) o4 z, f
}
if isValid(newBlock, bc.Blocks[len(bc.Blocks)-1]) {
bc.Blocks = append(bc.Blocks, newBlock)( O2 P1 S1 q3 a. O0 R1 [2 U) o
} else {
log.Fatal("invalid block")
}
return2 Z8 c8 X6 d5 C0 i" Y0 ^$ ^& z
}
, O! Z! K" j' x! ]) _
//输出区块链信息
func (bc *BlockChain) Print() {
for _, block := range bc.Blocks {/ a+ b: p w& c5 S5 K& y8 S; V, R9 S
fmt.Printf("Index : %d\n", block.Index)
fmt.Printf("Prev.Hash : %s\n", block.PrevBlockHash)
fmt.Printf("Curr.Hash : %s\n", block.Hash)
fmt.Printf("Curr.Data : %s\n", block.Data)1 _. U5 r% F; p. |- C8 w, f* S; u
fmt.Printf("Curr.Timestamp : %d\n", block.Timestamp)
fmt.Println("==========================================")
}
}7 a* s, r0 o2 O
//验证区块) `# ~( @* B. N% ~" \* ?: @, ?& @
func isValid(newBlock *Block, oldBlock *Block) bool {
if newBlock.Index-1 != oldBlock.Index {
return false
}
if newBlock.PrevBlockHash != oldBlock.Hash {
return false
}
if calculateHash(newBlock) != newBlock.Hash {. y$ h& E/ S1 |
return false5 J6 S0 p/ L' X3 j- u
}3 J% X0 _/ b$ I, ]# H
return true7 W6 i9 b7 @7 ~( M l
}
实现RPC接口的交互& K; Z m. H" U9 g) O4 M
- package main6 c* H6 g+ ?- @ ]$ G
-
- import (, v: \& x! r6 I/ X0 @
- "encoding/json"
- "BlockChain/core"
- "io"7 M3 h! _$ H0 y$ [
- "net/http"1 K* P% H$ q2 k- b% u% Z
- ) b9 K6 X# y; E2 h$ A4 j+ Q5 d+ d0 F
- 1 O' d# u/ v3 z( U
- var blockChain *core.BlockChain( ^" k, k, ?) Q7 g, _. s5 h) V
- 1 T/ n. q0 l e5 Y2 l: J. g" D
- func run() {
- http.HandleFunc("/block_chain/get", blockChainGetHandle)7 a4 _6 [) s) A0 I0 X% ]7 x( Q) r+ C
- http.HandleFunc("/block_chain/write", blockChainWriteHandle)" j0 o/ [% g3 b; j* E! p! w
- http.ListenAndServe(":8332", nil)/ h& V; a. F7 W' \1 g9 c
- }! o3 e9 z5 P, G N5 ~1 _
- 0 G4 i4 \& |) r! e* N- h& K
- func blockChainGetHandle(w http.ResponseWriter, r *http.Request) {: x/ ?1 V* j2 m) a! D7 @
- bytes, err := json.Marshal(blockChain)2 t* d9 a% T T( Z( B
- if err != nil {" P( N6 b, Q6 o& k
- http.Error(w, err.Error(), http.StatusInternalServerError)4 U5 Y# r& B+ H; g( I
- return4 L" w) L* F2 ]( x8 ^+ a3 F9 r
- }& @# \' ?0 f6 {# H$ h3 n
- io.WriteString(w, string(bytes))
- }
- ; R1 Y4 _* ^8 w7 O* N% e5 a
- func blockChainWriteHandle(w http.ResponseWriter, r *http.Request) {
- blockData := r.URL.Query().Get("data")
- blockChain.SendData(blockData)) l6 B( G% A& a5 _) Q
- blockChainGetHandle(w, r)" f4 D/ x8 q X; X
- }
- 9 R! D9 c# V$ k# |7 Z& v
- func main() {
- blockChain = core.NewBlockChain()' x7 i+ V7 r5 e3 R+ h
- run()( A+ t3 J, g% g: M* ~
- }
通过两部分代码实现简易区块链的RPC调用