通过http实现RPC命令的调用 实现添加块2 k" G! _" B6 p" k6 U. n
查询当前所有块的信息1 |8 p' K( c* x9 f
这里只做了两个命令 分别是get和write7 i3 _' { g" e7 ]; {
源代码如下( j, k& \ T) v) X0 q
基础功能的实现
package core
import (
"crypto/sha256"( W* {! G2 o' z* A* a0 j
"encoding/hex"
"time"
)8 m+ v% h, X' `# m* R& R
//定义区块
type Block struct {8 m5 O- `: u0 i" \1 k$ A" {' }
Index int64 //区块编号9 }: \& n4 M3 y+ h4 J$ ]% H
- Timestamp int64 //区块时间戳
- PrevBlockHash string //上一个区块的hash值
- Hash string //当前区块哈希值* g! F, f* k3 L' T3 S* F# i' X
- Data string //区块数据- O3 B! _- @% w! J, C5 J
- }
- //计算Hash
- func calculateHash(b *Block) string {
- blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash
- hashInBytes := sha256.Sum256([]byte(blockData))5 M* ~% J1 T8 s+ Z& w( W7 n% w
- return hex.EncodeToString(hashInBytes[:])
- }
5 U( |( k. p, Y8 {* J
//生成新的区块
func GenerateNewBlock(preBlock *Block, data string) *Block {
newBlock := &Block{}
newBlock.Index = preBlock.Index + 1* I; r! i' z9 Q" w3 s6 \' G
newBlock.PrevBlockHash = preBlock.Hash) u5 q$ ]1 h) f: h# Y0 F; M, m
newBlock.Timestamp = time.Now().Unix()/ Q& G7 \$ ^2 M1 j8 F; z4 P
newBlock.Hash = calculateHash(newBlock)6 _! B2 C8 @% Q) \7 H4 k4 R
newBlock.Data = data1 v9 ]3 [7 z0 }
return newBlock
}
//生成创始区块
func GenerateGenesisBlock() *Block {" ]. }3 c$ p C* q! o/ @
preBlock := &Block{}
preBlock.Index = -1
preBlock.Hash = ""
return GenerateNewBlock(preBlock, "Genesis Block")
}
将基础功能实现的块进行链接 实现blockchain
package core
import (
"fmt"
"log"
)& z) q: |6 ]$ d E% P4 T7 f
//定义区块链
type BlockChain struct {
Blocks []*Block1 t' W0 T' {* Q# k3 }0 @
}6 f- l0 w8 b; S5 N8 y7 m2 c9 c) ?
//创建一个区块链, q- K$ D6 }, t- ^7 `
func NewBlockChain() *BlockChain {# f6 h! i: |2 \
genesisBlock := GenerateGenesisBlock()* _0 K$ l& ]8 H) i
blockChain := &BlockChain{}
blockChain.AppendBlock(genesisBlock)
return blockChain3 `3 G% W Y n" u$ Q
}1 M8 k) O$ X+ m. ~; D2 q: M. Z; A
8 ^" N- B4 \7 o: z j0 C1 v
//记录区块数据* l: n0 h& y% d3 i
func (bc *BlockChain) SendData(data string) {
preBlock := bc.Blocks[len(bc.Blocks)-1], d: |) h* l8 l) H0 r E7 ?
newBlock := GenerateNewBlock(preBlock, data)
bc.AppendBlock(newBlock)
}/ O2 w1 ~5 M2 q2 b6 c: V
//往区块链添加区块
func (bc *BlockChain) AppendBlock(newBlock *Block) {( {9 M6 U# _4 B# g! O! q7 X0 S3 @
if len(bc.Blocks) == 0 {
bc.Blocks = append(bc.Blocks, newBlock)
return
}6 g# l, k- T+ o: I6 n/ m: n8 Y
if isValid(newBlock, bc.Blocks[len(bc.Blocks)-1]) {6 Z7 f9 B1 n. F1 p, {9 \$ b3 S
bc.Blocks = append(bc.Blocks, newBlock)
} else {
log.Fatal("invalid block")
}
return
}6 y) `0 F( p( J0 m( K4 B% Q) G2 K
//输出区块链信息
func (bc *BlockChain) Print() {
for _, block := range bc.Blocks {
fmt.Printf("Index : %d\n", block.Index). [0 w4 q9 ?, t1 a7 m
fmt.Printf("Prev.Hash : %s\n", block.PrevBlockHash)5 [2 R+ s V/ F6 V1 B
fmt.Printf("Curr.Hash : %s\n", block.Hash)
fmt.Printf("Curr.Data : %s\n", block.Data)7 I0 l6 d4 v5 b
fmt.Printf("Curr.Timestamp : %d\n", block.Timestamp)
fmt.Println("==========================================")- M2 Z9 o: x D# }; W0 u
}& ]& _: Z$ l1 m. r5 V
}6 _& L; Q' ]2 F" K0 m
//验证区块) J6 U7 ]9 P! ~: {/ M1 G7 r
func isValid(newBlock *Block, oldBlock *Block) bool {
if newBlock.Index-1 != oldBlock.Index {( O; a9 V1 {2 V
return false6 G" z3 ?, k' ]" W- @* Q1 [" ~
}
if newBlock.PrevBlockHash != oldBlock.Hash {
return false
}. H Q O0 f2 H5 e
if calculateHash(newBlock) != newBlock.Hash {5 i; Z' G8 k$ n A1 f* b; k
return false
}
return true; o# t/ v+ @$ k" n% o* {
}6 i, r$ q0 E6 P$ A' b% P' E
实现RPC接口的交互
- package main2 a7 q# o2 l/ ]* ~% r4 @& T
-
- import (5 S5 J- ]7 W# z; p' B2 b
- "encoding/json"
- "BlockChain/core"& o) C7 j. q6 R
- "io", `9 u& Y r2 |. N; n
- "net/http"
- )+ q5 y- t( R$ m& f% {8 _1 J
- % E2 P( `/ A: [$ @: Y+ S
- var blockChain *core.BlockChain' B! o) O% W# Z
- ! M& o) X! s* I! Y
- func run() { e* t7 ^& S: C/ M
- http.HandleFunc("/block_chain/get", blockChainGetHandle)
- http.HandleFunc("/block_chain/write", blockChainWriteHandle)1 `1 ?2 X8 v$ |/ Y- k
- http.ListenAndServe(":8332", nil)
- }8 G) e3 V! A" m
- 1 t% @# |6 p% M8 _8 l! ]2 \6 _
- func blockChainGetHandle(w http.ResponseWriter, r *http.Request) {
- bytes, err := json.Marshal(blockChain)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }9 K9 ^, { n% _) D# ~
- io.WriteString(w, string(bytes)); H) n/ Z3 z) a9 ~3 R4 C: b4 M+ J
- }3 n+ l( |% B% s! s3 B
- - y K$ W8 J3 N" d
- func blockChainWriteHandle(w http.ResponseWriter, r *http.Request) {
- blockData := r.URL.Query().Get("data")
- blockChain.SendData(blockData)- e3 q8 }4 {: S- q
- blockChainGetHandle(w, r): z7 G4 i/ \/ D) @9 L) d# b
- }
-
- func main() {
- blockChain = core.NewBlockChain()0 f% ]& I- n( v
- run()0 e+ b/ i# D7 o/ ^
- }
通过两部分代码实现简易区块链的RPC调用