通过http实现RPC命令的调用 实现添加块
查询当前所有块的信息
这里只做了两个命令 分别是get和write
源代码如下2 l4 r/ D6 |, ]3 d1 ?9 i
基础功能的实现
package core
import (. z5 i0 s7 J& F) X r, x+ i
"crypto/sha256"
"encoding/hex"5 H' H8 l, e W6 }% v
"time"2 v% M8 u/ |& E# e7 o0 ~7 o3 k
)
//定义区块
type Block struct {0 I7 a% ^+ I. O1 J
Index int64 //区块编号
- Timestamp int64 //区块时间戳
- PrevBlockHash string //上一个区块的hash值
- Hash string //当前区块哈希值. g1 V8 o: ^$ H+ \
- Data string //区块数据
- }/ k! L, {# F& o" t
- //计算Hash: |) q* d" h$ |$ `+ A$ L0 _ h `
- func calculateHash(b *Block) string {
- blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash& j. d" b' \4 F( c5 L5 M% N
- hashInBytes := sha256.Sum256([]byte(blockData))
- return hex.EncodeToString(hashInBytes[:])
- }
/ T; r) t/ n3 J% q4 f$ {$ w# z
//生成新的区块
func GenerateNewBlock(preBlock *Block, data string) *Block {4 ]1 \; e9 Y9 l' b& u$ g
newBlock := &Block{}
newBlock.Index = preBlock.Index + 1
newBlock.PrevBlockHash = preBlock.Hash
newBlock.Timestamp = time.Now().Unix()
newBlock.Hash = calculateHash(newBlock)" A7 E) `: D3 I5 r0 N! v8 U
newBlock.Data = data
return newBlock3 e; T2 Z9 {. v7 Z* u& l8 }
}
//生成创始区块9 B9 q8 H" _1 F( n5 A
func GenerateGenesisBlock() *Block {- z, a2 A! n- r3 J2 R. V# X x
preBlock := &Block{}5 u w8 U8 ^, L
preBlock.Index = -1% T! v3 ^8 [: l; y& u
preBlock.Hash = ""$ q \( I+ S# L7 O& }
return GenerateNewBlock(preBlock, "Genesis Block")
}
将基础功能实现的块进行链接 实现blockchain, L6 ^3 p* M9 U* V" w0 l# s
package core
import (/ Y/ J' _- `) L
"fmt"2 ^1 B6 }2 \9 C% X/ y) s& P
"log"0 t' R3 N9 a& K( v# Z
)
, O7 i' S- ~3 Z! m
//定义区块链 t3 t- u, n/ s# p6 L% t7 Y
type BlockChain struct {
Blocks []*Block: I, c; e/ N( H8 i/ `* T2 T/ R# W
}
//创建一个区块链2 x: L% A6 |& z: |- d5 f
func NewBlockChain() *BlockChain {( o4 Z: ^2 Y6 ]+ `3 h7 i
genesisBlock := GenerateGenesisBlock()) F7 [ O$ P0 X* y' [
blockChain := &BlockChain{}: v6 t& x6 C# \) `, c0 ^
blockChain.AppendBlock(genesisBlock)
return blockChain
}
//记录区块数据$ q- {; p8 y/ K
func (bc *BlockChain) SendData(data string) {
preBlock := bc.Blocks[len(bc.Blocks)-1]
newBlock := GenerateNewBlock(preBlock, data)2 A: |8 J+ g2 C% x3 ]$ F$ |
bc.AppendBlock(newBlock)
}& Y7 s' W- m9 y s" `1 }
//往区块链添加区块$ I. u; {* G9 }* e
func (bc *BlockChain) AppendBlock(newBlock *Block) {2 Z. ]( B4 K/ ]
if len(bc.Blocks) == 0 {
bc.Blocks = append(bc.Blocks, newBlock)6 k+ O2 z/ y. T, g. N: C
return+ N6 _. s5 y. U3 J
}
if isValid(newBlock, bc.Blocks[len(bc.Blocks)-1]) {5 i" x6 s8 |& g% T% E
bc.Blocks = append(bc.Blocks, newBlock)
} else {
log.Fatal("invalid block")
}! t0 e' c+ T; b s) O9 Y6 P
return
}( m' q0 W8 |. y4 n
0 Z" ~/ n. Z2 m" d9 c) f
//输出区块链信息
func (bc *BlockChain) Print() {
for _, block := range bc.Blocks {4 I$ {* |/ E& x" A
fmt.Printf("Index : %d\n", block.Index)6 f; @0 L2 p' C8 u1 X3 j2 X$ U
fmt.Printf("Prev.Hash : %s\n", block.PrevBlockHash)9 H7 X4 y! p/ n O& i" R0 _
fmt.Printf("Curr.Hash : %s\n", block.Hash); J \' X2 A4 L0 C, A) r, b
fmt.Printf("Curr.Data : %s\n", block.Data)
fmt.Printf("Curr.Timestamp : %d\n", block.Timestamp)
fmt.Println("==========================================")) y8 C" y3 O' I
} i, J5 t: G' W6 M" @
}
( @9 `$ E3 h) n' ^! P! S
//验证区块! |* _( c3 v4 {2 T
func isValid(newBlock *Block, oldBlock *Block) bool { R5 K& [: m# C! Y7 U$ v4 U6 c
if newBlock.Index-1 != oldBlock.Index {
return false
}
if newBlock.PrevBlockHash != oldBlock.Hash {
return false
}: k* L) i+ h* N) N, F- @5 G5 f
if calculateHash(newBlock) != newBlock.Hash {
return false, F+ g: U5 w: p! d% m/ H; H
}
return true
}
实现RPC接口的交互
- package main$ C1 m# n! E8 j+ c3 W
- ! L$ X! J: P, I
- import (
- "encoding/json"
- "BlockChain/core"
- "io"9 I, c2 z' P9 t
- "net/http"
- )
- 9 b9 _- P) t) ~5 m+ l+ N
- var blockChain *core.BlockChain
-
- func run() {) {9 }) T5 \9 E, R( x6 ~2 c8 W
- http.HandleFunc("/block_chain/get", blockChainGetHandle)
- http.HandleFunc("/block_chain/write", blockChainWriteHandle)
- http.ListenAndServe(":8332", nil)
- }
- ! U, g1 z6 g) g
- func blockChainGetHandle(w http.ResponseWriter, r *http.Request) {
- bytes, err := json.Marshal(blockChain)
- if err != nil {, B! \5 Y- c; |
- http.Error(w, err.Error(), http.StatusInternalServerError)0 `# q" |" Q! P! \) z/ t& y& C f) t
- return6 c. V( R! i2 n E) s
- }5 R) i$ j+ t' l3 w* N
- io.WriteString(w, string(bytes))
- }2 e4 n* j& X9 _( p
- ( T( R( y5 M2 S
- func blockChainWriteHandle(w http.ResponseWriter, r *http.Request) {+ Z h4 H8 }9 O2 P l
- blockData := r.URL.Query().Get("data")6 t: ?5 P0 B, I2 r! H+ q
- blockChain.SendData(blockData)8 k( [5 }0 r% |' O4 h5 K7 `+ x4 t4 q
- blockChainGetHandle(w, r)
- }
-
- func main() {4 k2 d0 y5 L2 N1 ^
- blockChain = core.NewBlockChain()
- run() @( G2 c$ K2 G4 j' N9 W- n6 [6 \+ b
- }
通过两部分代码实现简易区块链的RPC调用