& F5 }( P: v8 e% ^, ^; Z
通过http实现RPC命令的调用 实现添加块
查询当前所有块的信息
这里只做了两个命令 分别是get和write
源代码如下3 W& t6 P! |5 x8 T
基础功能的实现
package core# j8 q. H7 g1 {( `0 S
import (
"crypto/sha256". N8 g: e9 y1 [3 w+ T- H6 Z% G
"encoding/hex"
"time"
)
//定义区块 @+ u! ?; u0 J0 X. Q& x6 a, F5 i
type Block struct {
Index int64 //区块编号+ m( Y/ V: N! R* ]/ P, S7 D1 ^
- Timestamp int64 //区块时间戳2 b1 J% z# r$ t7 l. R' e+ h* Y" r
- PrevBlockHash string //上一个区块的hash值$ R) J& |: m4 t5 ?
- Hash string //当前区块哈希值3 Y8 d( p3 t) S: C6 [; K! \
- Data string //区块数据
- } A$ b, |$ `6 T# c
- //计算Hash( T" x# h+ t& t5 D" m5 o: L
- func calculateHash(b *Block) string {/ k' S b1 X% h- L) N
- blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash
- hashInBytes := sha256.Sum256([]byte(blockData)). \8 z, V8 f0 B: [- ~6 w& G0 u3 h U+ G
- return hex.EncodeToString(hashInBytes[:])
- }
//生成新的区块( j# C) ]) K4 [
func GenerateNewBlock(preBlock *Block, data string) *Block {* P/ x# a1 D2 k: Q- l+ Q, v4 N, z
newBlock := &Block{}/ ~ e; ~& O) T* t' R, a
newBlock.Index = preBlock.Index + 1
newBlock.PrevBlockHash = preBlock.Hash# P! q2 ^1 a2 E! J
newBlock.Timestamp = time.Now().Unix()
newBlock.Hash = calculateHash(newBlock)
newBlock.Data = data
return newBlock, J' F- Z0 g* M( V' e: ]* u& {
}
//生成创始区块
func GenerateGenesisBlock() *Block {
preBlock := &Block{}
preBlock.Index = -1. L$ _5 ^ M2 b' m
preBlock.Hash = ""
return GenerateNewBlock(preBlock, "Genesis Block")( v5 W& H! H- b9 S
}" T$ z6 Y& x) c* R( X8 K& f
将基础功能实现的块进行链接 实现blockchain N, b" y# D1 d6 ~6 u: S; w
package core! x! b4 p" N; c k# o
import (& D7 ?6 l6 ]+ G7 }, L% B% }' h
"fmt"( ^5 @1 B O' X- f% s
"log"/ ?) b% a7 J8 t, @/ L b* y
)
. o5 @! p+ p; H
//定义区块链
type BlockChain struct {, A- B5 j9 A* A# \
Blocks []*Block
}! L9 b3 T2 X8 t3 R
//创建一个区块链
func NewBlockChain() *BlockChain {
genesisBlock := GenerateGenesisBlock()
blockChain := &BlockChain{}
blockChain.AppendBlock(genesisBlock)
return blockChain9 a* k9 r8 G$ H' G! F
}: f$ s5 L( z& F8 T! n
9 q) h3 [( ?( f9 G9 D
//记录区块数据
func (bc *BlockChain) SendData(data string) {
preBlock := bc.Blocks[len(bc.Blocks)-1]. f$ ]. @7 }% c# n' x* M
newBlock := GenerateNewBlock(preBlock, data)
bc.AppendBlock(newBlock)8 Y4 N2 b2 U, Z8 L
}
' M$ k" M1 n0 j- Q5 o3 m. ]! P
//往区块链添加区块
func (bc *BlockChain) AppendBlock(newBlock *Block) {0 q1 L; g; ^; s1 i3 \$ a* [! c
if len(bc.Blocks) == 0 {# l% G, j6 `& Z8 B- u& E! I
bc.Blocks = append(bc.Blocks, newBlock)) S- {9 c0 ~7 c9 X5 h; U+ k+ F
return9 v8 H5 q, j4 F
}
if isValid(newBlock, bc.Blocks[len(bc.Blocks)-1]) {
bc.Blocks = append(bc.Blocks, newBlock)" M1 `( \$ O( a: `/ ]* a
} else {
log.Fatal("invalid block")
}
return7 l4 X4 w" L% N7 C
}# { ]) `8 | }$ t" n
8 I+ D6 n3 i6 {% p4 V$ `6 d; U2 \0 t
//输出区块链信息
func (bc *BlockChain) Print() {& o2 j- a+ t* {
for _, block := range bc.Blocks {
fmt.Printf("Index : %d\n", block.Index)% G) H3 }+ _/ \
fmt.Printf("Prev.Hash : %s\n", block.PrevBlockHash): r7 r+ }: D0 v) p! N* K0 D4 H
fmt.Printf("Curr.Hash : %s\n", block.Hash)
fmt.Printf("Curr.Data : %s\n", block.Data)
fmt.Printf("Curr.Timestamp : %d\n", block.Timestamp)9 u0 L( q# q: Y- F' ^& g) k
fmt.Println("==========================================")& J" q' R- k% a0 a
}
}
//验证区块3 o% A1 C0 O% F+ F' q$ o) \
func isValid(newBlock *Block, oldBlock *Block) bool {
if newBlock.Index-1 != oldBlock.Index {& b4 O% d* Z# ~- Q
return false" V# u1 _2 Q2 n: ?' s) Z) ~
}: z3 \# k- k5 S) R5 S
if newBlock.PrevBlockHash != oldBlock.Hash {/ c* `+ M8 Y; ^' ^
return false( A7 ]6 |8 I9 ~' P
}* W% L% L* q& b7 \8 X3 |. Z: \
if calculateHash(newBlock) != newBlock.Hash {, f4 a# b/ ~! {: r; B3 p! ~7 _
return false0 Z1 |& M e; b+ C
}
return true" C: r# g9 \9 ]& o% y& D, v
}. B+ T4 H% W: X8 l3 H8 F
实现RPC接口的交互! g# O* A: i) r4 p
- package main
- & Y6 p6 W6 f5 M/ J! {& ~6 v# T
- import ( j: i: [3 u5 u) ?+ O! d/ F: T
- "encoding/json"
- "BlockChain/core"
- "io"
- "net/http"8 @0 ?0 B4 X! ~ n9 d
- )! ]! g5 J1 `+ b2 `/ M
-
- var blockChain *core.BlockChain3 D2 E/ R) s6 h, P! W
-
- func run() {/ q! [- r& D9 _5 x
- http.HandleFunc("/block_chain/get", blockChainGetHandle)8 o/ a! p, V( v! w) h
- http.HandleFunc("/block_chain/write", blockChainWriteHandle)
- http.ListenAndServe(":8332", nil)
- }
- 6 p6 ?4 a2 T4 V+ m) c. E! `9 J
- func blockChainGetHandle(w http.ResponseWriter, r *http.Request) {
- bytes, err := json.Marshal(blockChain)
- if err != nil {/ u4 t F5 h% O. D* C/ M v. p$ m0 r
- http.Error(w, err.Error(), http.StatusInternalServerError)8 P! W$ \. z! ^4 r# @$ q" X
- return
- }
- io.WriteString(w, string(bytes))% |% t9 Y f9 {! e5 l7 Z8 }8 O3 @; @
- }
-
- func blockChainWriteHandle(w http.ResponseWriter, r *http.Request) {! F8 o# d9 v" W) t' h
- blockData := r.URL.Query().Get("data")
- blockChain.SendData(blockData). L/ E! e e4 w3 N, `$ J- ~
- blockChainGetHandle(w, r)
- }
-
- func main() {
- blockChain = core.NewBlockChain()
- run()
- }
通过两部分代码实现简易区块链的RPC调用



