; k) g1 |0 g9 e. V) r( L3 j" s
通过http实现RPC命令的调用 实现添加块
查询当前所有块的信息
这里只做了两个命令 分别是get和write4 x: ?& @, D1 N- O/ s1 o( f
源代码如下6 j2 o7 ]) V% F0 z; f! \: O7 e
基础功能的实现
4 l3 ^- u6 b. g% W9 s: E+ n8 t
package core3 } w7 d3 ^$ B; Z. S/ D( m
import (' l; Q3 J$ K- j& H/ ^
"crypto/sha256"0 n" `6 g a+ ?$ x8 v) K2 c
"encoding/hex"4 E; \$ [. Q, g" H5 J1 O9 i
"time"5 |; S1 \7 ` i( e
)
//定义区块5 R/ E- @) ^% r) o& I
type Block struct {
Index int64 //区块编号 T4 J. b; Y& q7 d. z
- Timestamp int64 //区块时间戳
- PrevBlockHash string //上一个区块的hash值
- Hash string //当前区块哈希值
- Data string //区块数据
- }8 r& N: m9 c y3 N
- //计算Hash; ?" ?6 Q' X5 I+ Z6 U8 P/ d0 M
- func calculateHash(b *Block) string {
- blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash
- hashInBytes := sha256.Sum256([]byte(blockData))) y' i; ^0 e0 S1 F) M
- return hex.EncodeToString(hashInBytes[:])$ a# s! v% v7 Q' C4 B4 W/ C
- }
//生成新的区块; h% ^4 E+ g7 b- R3 }- O0 m
func GenerateNewBlock(preBlock *Block, data string) *Block {. a8 Z" o" j P& E2 w h
newBlock := &Block{}8 m o5 p9 z6 ?# A8 I% |1 e
newBlock.Index = preBlock.Index + 1
newBlock.PrevBlockHash = preBlock.Hash8 K) {) E& ?( P$ B/ w$ m* T
newBlock.Timestamp = time.Now().Unix()
newBlock.Hash = calculateHash(newBlock)
newBlock.Data = data
return newBlock
}
//生成创始区块
func GenerateGenesisBlock() *Block {
preBlock := &Block{}1 x; S6 v# z+ a% T2 b
preBlock.Index = -12 M( x1 Y+ H+ E8 t0 i" D" d$ v
preBlock.Hash = ""
return GenerateNewBlock(preBlock, "Genesis Block") ]/ M: q4 d2 ?! K. L" Y4 \; M
}0 R. N/ b. G/ R( V/ B& a
将基础功能实现的块进行链接 实现blockchain6 |" R( b4 [4 q J0 |" C2 q
package core
import () \5 y$ ^2 o5 G' b) @8 v" X; ~
"fmt"
"log"
)+ L$ Z, ?* e- Q0 Q' t0 j
//定义区块链
type BlockChain struct {3 o9 o5 E8 }9 A" L
Blocks []*Block0 P/ x- B1 m1 m- r5 w
}; E' k: y! f/ _3 G4 Y: V* j
//创建一个区块链1 p: M7 ^' Z% o- |5 g/ J
func NewBlockChain() *BlockChain {
genesisBlock := GenerateGenesisBlock()
blockChain := &BlockChain{}: e8 q( d, ^3 j! `' }' l4 {
blockChain.AppendBlock(genesisBlock)
return blockChain
}
//记录区块数据, J7 E% n' f5 s4 M# b
func (bc *BlockChain) SendData(data string) {# x6 j; m; K) z" {) j( i9 O+ ?
preBlock := bc.Blocks[len(bc.Blocks)-1]- `3 L% s6 P- n7 S
newBlock := GenerateNewBlock(preBlock, data)
bc.AppendBlock(newBlock)2 S2 D* A2 v$ {1 D4 B4 y) D
}) ]5 h7 y/ l" X! w, [' W$ O. z
, G6 Y5 O- m, D* P( W* o
//往区块链添加区块! t9 l" ~0 l Z) @% Z1 q+ V8 t2 C/ t; J4 c
func (bc *BlockChain) AppendBlock(newBlock *Block) {% p1 O+ `6 J8 k7 _$ V% c- Y M* F7 {
if len(bc.Blocks) == 0 {
bc.Blocks = append(bc.Blocks, newBlock)3 l% A& g) ? K
return
}
if isValid(newBlock, bc.Blocks[len(bc.Blocks)-1]) {; ~7 c; w4 z/ V8 ^
bc.Blocks = append(bc.Blocks, newBlock)
} else {
log.Fatal("invalid block")( x* S; C3 M& F+ y& x: k& v
}
return; [6 B) |+ x% a1 j; F
}
//输出区块链信息
func (bc *BlockChain) Print() {
for _, block := range bc.Blocks {
fmt.Printf("Index : %d\n", block.Index)$ k/ h, S9 f, m4 \) b- p" P
fmt.Printf("Prev.Hash : %s\n", block.PrevBlockHash)
fmt.Printf("Curr.Hash : %s\n", block.Hash)
fmt.Printf("Curr.Data : %s\n", block.Data)* A5 Q6 C" t! _; x" E
fmt.Printf("Curr.Timestamp : %d\n", block.Timestamp)
fmt.Println("==========================================")
}8 a9 A, [: E" h
}2 B7 k9 z' P Q; R& a+ z7 L3 j. N
//验证区块
func isValid(newBlock *Block, oldBlock *Block) bool {
if newBlock.Index-1 != oldBlock.Index {: T6 h. H$ p; L( I! P' v1 M3 a9 }% f
return false
}+ y) i0 f5 e7 k
if newBlock.PrevBlockHash != oldBlock.Hash {
return false
}2 n, E: V/ C1 j
if calculateHash(newBlock) != newBlock.Hash {
return false% {( h7 e x- p5 a& N
}
return true# \( v$ E4 j# i# q$ W
}
实现RPC接口的交互% m: @" Q% w$ L6 e' P' e3 W
- package main
-
- import (
- "encoding/json"
- "BlockChain/core" w! \) c- ]% K4 K0 g& a2 V
- "io"
- "net/http"
- )
- ! O2 V4 M# a" \3 Z
- var blockChain *core.BlockChain. p( }' ?2 }; _& e/ E
- " U! \+ p+ Y2 M% E a8 \
- func run() {
- http.HandleFunc("/block_chain/get", blockChainGetHandle)4 [4 m |# s" V$ j
- http.HandleFunc("/block_chain/write", blockChainWriteHandle)
- http.ListenAndServe(":8332", nil), T8 j8 v. z- `, _
- }" o( c3 V* T+ J* v8 Q( U9 L
- 2 d @# L5 u, d: X; d
- func blockChainGetHandle(w http.ResponseWriter, r *http.Request) {1 N& x* o# d7 n" P% z( f# @7 [
- bytes, err := json.Marshal(blockChain)
- if err != nil { O& y0 J1 A. W+ U
- http.Error(w, err.Error(), http.StatusInternalServerError)/ m2 N$ Q2 Q0 m( y
- return
- }3 Y/ `+ H, M" L( A4 P
- io.WriteString(w, string(bytes))/ _0 P1 P$ w- n5 P" T. a# P
- }
-
- func blockChainWriteHandle(w http.ResponseWriter, r *http.Request) {" W8 x3 I( J; Q9 n- ~, ?) P! p
- blockData := r.URL.Query().Get("data")# L1 u1 Z# H: i, M2 x8 O
- blockChain.SendData(blockData)
- blockChainGetHandle(w, r)" @# W0 I3 {: l w6 k$ g6 S- P
- }4 C$ G. p) Z2 ^. I
-
- func main() {; n/ a5 E7 r) A1 f/ k
- blockChain = core.NewBlockChain()
- run()
- }
通过两部分代码实现简易区块链的RPC调用