通过http实现RPC命令的调用 实现添加块
) J3 V# m" W+ v- j" S2 G
查询当前所有块的信息3 \+ p# q+ G, U: ^+ X5 M3 ]( \
- k+ W; R) [6 o' L, n9 s4 U+ u7 ~
这里只做了两个命令 分别是get和write
源代码如下2 C. A6 e. d) x4 k% H# Y' \
基础功能的实现
package core* {. \% k. a4 K8 N* m4 [( d( ?1 W7 c
import (
"crypto/sha256"
"encoding/hex"
"time"
)% a, h$ I5 f1 v$ T F
//定义区块% |9 l2 _, B* G3 X/ t
type Block struct {
Index int64 //区块编号' T( A2 l c" q
- Timestamp int64 //区块时间戳# }+ G0 F4 f- N/ A
- PrevBlockHash string //上一个区块的hash值
- Hash string //当前区块哈希值9 E# I7 f+ Q3 w' y7 m
- Data string //区块数据
- }5 I6 {" b S' U9 R# ~9 W
- //计算Hash) m+ M' k6 Y' _4 C5 @ U6 O
- func calculateHash(b *Block) string {& g0 S, s8 a' g3 U0 m: B0 Y
- blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash
- hashInBytes := sha256.Sum256([]byte(blockData))# p9 y, ], V' D* p4 ^
- return hex.EncodeToString(hashInBytes[:])
- }
//生成新的区块
func GenerateNewBlock(preBlock *Block, data string) *Block {
newBlock := &Block{}& b7 g, R1 x" {0 X4 e
newBlock.Index = preBlock.Index + 1) e1 x4 H/ L. c0 f" ~% a, i* D
newBlock.PrevBlockHash = preBlock.Hash
newBlock.Timestamp = time.Now().Unix()0 A* i' r, s! H7 z7 K' N
newBlock.Hash = calculateHash(newBlock)
newBlock.Data = data
return newBlock
}
# i) p, v" w3 X# \
//生成创始区块1 d; [- k- I h0 t: H
func GenerateGenesisBlock() *Block {
preBlock := &Block{}
preBlock.Index = -1) b2 {) ?5 }$ ]' ?
preBlock.Hash = ""
return GenerateNewBlock(preBlock, "Genesis Block")0 E! f" K3 ?) x3 @. V8 j
}) Y0 [) F7 x7 ]6 j% x
将基础功能实现的块进行链接 实现blockchain
package core9 v* E( t9 V2 u7 V3 N: k' [
import (
"fmt"
"log"+ s. n3 N3 M( Y9 i! m
)
//定义区块链8 K, J+ t8 b5 `) E; C, I
type BlockChain struct {3 ]5 ] B3 b2 ]3 W; `, z
Blocks []*Block
}
//创建一个区块链
func NewBlockChain() *BlockChain {0 L, \0 {3 I% ~" @9 f0 c( g
genesisBlock := GenerateGenesisBlock()
blockChain := &BlockChain{}. i5 o' f6 u+ _% Z S: | A
blockChain.AppendBlock(genesisBlock)
return blockChain
}# q6 p, O* @# R+ g; h$ }: {- I
//记录区块数据
func (bc *BlockChain) SendData(data string) {
preBlock := bc.Blocks[len(bc.Blocks)-1]
newBlock := GenerateNewBlock(preBlock, data)7 B; t' I+ I' _3 k+ Z; F" U7 a9 t
bc.AppendBlock(newBlock)/ B4 F/ \# l( R4 ?0 f; N
}2 _: }1 L( E- p
//往区块链添加区块
func (bc *BlockChain) AppendBlock(newBlock *Block) {
if len(bc.Blocks) == 0 {
bc.Blocks = append(bc.Blocks, newBlock)2 z0 s: g6 y% m5 `3 a
return
}
if isValid(newBlock, bc.Blocks[len(bc.Blocks)-1]) {( P4 m3 s- B: m+ c
bc.Blocks = append(bc.Blocks, newBlock)
} else {. V* J% j, ~5 t) n" k( }0 N
log.Fatal("invalid block")
}1 D, ] Q( d- J. L
return
}
2 c' u6 q% M8 L- E
//输出区块链信息
func (bc *BlockChain) Print() {
for _, block := range bc.Blocks {0 S) h( t, L: I4 a( @, k7 Q* O5 H
fmt.Printf("Index : %d\n", block.Index)/ A* ~- e5 Q% u$ W* |
fmt.Printf("Prev.Hash : %s\n", block.PrevBlockHash)/ _2 k" ?/ A: T T
fmt.Printf("Curr.Hash : %s\n", block.Hash)
fmt.Printf("Curr.Data : %s\n", block.Data) w: P2 q2 @2 _" v* r
fmt.Printf("Curr.Timestamp : %d\n", block.Timestamp) J4 @# n, Z+ _/ ^, ]' Q. E
fmt.Println("==========================================")
}
}! B. V1 a8 }/ l( l4 o
0 _& N" f7 G4 ?! j3 R/ n; F4 V$ ]
//验证区块
func isValid(newBlock *Block, oldBlock *Block) bool {
if newBlock.Index-1 != oldBlock.Index {
return false
}
if newBlock.PrevBlockHash != oldBlock.Hash {
return false
}% B; S% y( G5 l d
if calculateHash(newBlock) != newBlock.Hash {5 d! M' Q" D# T; q8 {4 ]5 o
return false" Z3 E `; L4 i
}
return true
}
实现RPC接口的交互; F0 v* m3 |7 d4 g) D
- package main% T8 H0 ^$ j2 ~+ l0 E- t1 M
- % K0 G- ^- O- F& ?7 S- M8 {
- import (
- "encoding/json"
- "BlockChain/core"
- "io"* K. z$ g; ]6 \
- "net/http"
- )
- 6 I' N3 ]& k2 E7 {- T9 I: F% C
- var blockChain *core.BlockChain5 u" C2 S% f# b' [; Z
-
- func run() {0 l! g; t' @; D/ c- {- q' Z
- http.HandleFunc("/block_chain/get", blockChainGetHandle)
- http.HandleFunc("/block_chain/write", blockChainWriteHandle)
- http.ListenAndServe(":8332", nil)
- }
- & a) T2 r. {3 y) b% {) N
- func blockChainGetHandle(w http.ResponseWriter, r *http.Request) {
- bytes, err := json.Marshal(blockChain)
- if err != nil {+ Q# v8 x" ~. x: n, [
- http.Error(w, err.Error(), http.StatusInternalServerError): p6 w+ O) N T1 }& n N: S2 C, M
- return! A4 Y) ]1 C4 s2 q
- }) b* H2 d0 m' [- A' J4 m5 r2 S U
- io.WriteString(w, string(bytes))% F( s4 q$ V. q. L' \
- }% C) E, y& W0 y' q+ [7 ~
-
- func blockChainWriteHandle(w http.ResponseWriter, r *http.Request) { e9 {" s2 p& E
- blockData := r.URL.Query().Get("data")* `$ l4 r7 l5 }; O2 @0 j
- blockChain.SendData(blockData)
- blockChainGetHandle(w, r)
- }) Q' L* u" ]" i6 w
- + R4 L, T0 D. F4 ]" r% ^# R2 q9 V
- func main() {) d8 F3 |* J1 X! v& D4 I4 h
- blockChain = core.NewBlockChain()) X2 X# }# u4 e' {
- run()9 F5 q5 k6 Z8 c. u
- }
通过两部分代码实现简易区块链的RPC调用