通过http实现RPC命令的调用 实现添加块
- X" f# e% z( M n- a, P: ?* L
查询当前所有块的信息0 u1 u0 G- Y$ a/ \& q9 J
- P: ^+ V/ P* r$ m8 @6 j" H2 u3 i
这里只做了两个命令 分别是get和write
源代码如下
基础功能的实现, I& N& v6 [/ _% m
0 Q$ q; V8 ~9 L% J }, o, c
package core7 {. `$ d3 k% C) p
import (* J# ]( J7 p$ u5 B$ B4 w! }1 r+ H
"crypto/sha256"& f9 a0 [" I) j( y; M
"encoding/hex"
"time". S% m* L. b" g/ q6 }5 C
)
//定义区块
type Block struct {! J9 Y* r5 T( f3 \$ N
Index int64 //区块编号
- Timestamp int64 //区块时间戳
- PrevBlockHash string //上一个区块的hash值
- Hash string //当前区块哈希值 `; K7 s1 t. i- b
- Data string //区块数据
- }2 g% B* h! b4 }' S% @
- //计算Hash
- func calculateHash(b *Block) string {4 b1 R- `. G+ f! o
- blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash
- hashInBytes := sha256.Sum256([]byte(blockData))
- return hex.EncodeToString(hashInBytes[:])
- }
//生成新的区块* T4 F! g! r9 E. u+ Z/ E7 Z
func GenerateNewBlock(preBlock *Block, data string) *Block {* g3 r3 M: i- {0 B
newBlock := &Block{}2 G! z! s$ e H* V7 s' X1 T
newBlock.Index = preBlock.Index + 1
newBlock.PrevBlockHash = preBlock.Hash! r/ c5 d$ \$ X' c+ y- `
newBlock.Timestamp = time.Now().Unix() ~' A, M$ T8 I! G" i
newBlock.Hash = calculateHash(newBlock)3 q5 q Z7 z f: j
newBlock.Data = data
return newBlock6 }3 L5 E1 Y6 ^9 T% n
}* y) @' c. p1 X# U
//生成创始区块 { v1 u) c" z
func GenerateGenesisBlock() *Block {; R1 Z0 J/ g$ |1 Z
preBlock := &Block{}
preBlock.Index = -1
preBlock.Hash = ""& D" M; D8 c% j+ b, K
return GenerateNewBlock(preBlock, "Genesis Block")
}- m" \2 K) A$ A+ L5 J
将基础功能实现的块进行链接 实现blockchain. e' d. o$ U; K# Y# b r
package core
import (
"fmt"6 P% v0 }" {9 e, ]6 n* E
"log") o+ z& z: X6 h' M; r: u2 _+ U
)
//定义区块链
type BlockChain struct {
Blocks []*Block
}
//创建一个区块链
func NewBlockChain() *BlockChain {9 @& t. W( o$ s5 `- b
genesisBlock := GenerateGenesisBlock()) h5 \" H5 c' B" {( a6 K
blockChain := &BlockChain{}
blockChain.AppendBlock(genesisBlock)
return blockChain+ J* f# A5 n' d& J( T. T4 d0 m" J
}
: F+ |, ~( ^# p
//记录区块数据/ `3 ^; e' Q1 C, `& ?
func (bc *BlockChain) SendData(data string) {3 ~: x. w. {. A8 V1 `$ W
preBlock := bc.Blocks[len(bc.Blocks)-1]
newBlock := GenerateNewBlock(preBlock, data)9 d9 B9 K) T$ `) z( i2 Y
bc.AppendBlock(newBlock)
}$ a, S, e2 L$ P0 A5 D
//往区块链添加区块
func (bc *BlockChain) AppendBlock(newBlock *Block) {
if len(bc.Blocks) == 0 {" H7 q# x9 v9 \3 z
bc.Blocks = append(bc.Blocks, newBlock)
return. Q- q- k! e$ ^8 Z0 [* f% @, x' N
}- U5 Q5 o7 b; T* I, y7 M/ p1 x
if isValid(newBlock, bc.Blocks[len(bc.Blocks)-1]) {
bc.Blocks = append(bc.Blocks, newBlock), u6 ], j6 _8 b, a+ e% `
} else {- H8 X2 H; X2 M% O
log.Fatal("invalid block")" l$ W* O8 }* P0 B1 r
}3 Z( ]9 ]6 ]0 Y) H
return: A, c2 K }# }: U1 R, q2 h: t6 ]
}
//输出区块链信息4 w6 B6 G1 {2 G# y
func (bc *BlockChain) Print() {
for _, block := range bc.Blocks {' S* H: i3 z+ k' ^* `
fmt.Printf("Index : %d\n", block.Index)
fmt.Printf("Prev.Hash : %s\n", block.PrevBlockHash)
fmt.Printf("Curr.Hash : %s\n", block.Hash)& f$ D% h& A h6 W. s
fmt.Printf("Curr.Data : %s\n", block.Data)! k3 E2 {5 a) f! @6 K- L. ]6 j6 s
fmt.Printf("Curr.Timestamp : %d\n", block.Timestamp); V% {" U+ G* @1 g& m, Z
fmt.Println("==========================================")
}
}" D8 c$ [% m1 X' z
//验证区块8 u$ o* F0 |4 O7 B3 t5 h0 S
func isValid(newBlock *Block, oldBlock *Block) bool {# N3 c) i" J. ~7 K P
if newBlock.Index-1 != oldBlock.Index {
return false6 U2 U. {6 z5 S( X7 m
}
if newBlock.PrevBlockHash != oldBlock.Hash {, D; U8 j: Z' c( [& o* s6 X
return false
}$ ~, p3 I9 R t/ d2 B
if calculateHash(newBlock) != newBlock.Hash {
return false
}( i2 |8 _* A& x; r0 @% M* h
return true8 \* `: w2 d, Z/ w ?! M- ]' Z
}
实现RPC接口的交互4 \/ ~5 y# b' j* b: X
- package main
-
- import (( P$ y. t. Z* b+ o
- "encoding/json"
- "BlockChain/core"
- "io"
- "net/http"6 I9 q6 A) d* f# j: K- E% q1 t
- )" m; S9 s5 K: ]7 e* Z' @
- 0 O/ v m( {( N) y) i1 f; I( t y
- var blockChain *core.BlockChain
-
- func run() {7 P3 \! J% G4 Z9 J/ ]
- http.HandleFunc("/block_chain/get", blockChainGetHandle)5 l$ ~8 f1 u Y" `0 C
- http.HandleFunc("/block_chain/write", blockChainWriteHandle)
- http.ListenAndServe(":8332", nil)
- }9 X( [" [/ [) `( g
- 9 ?* L5 r! Q. K# g3 P8 Q5 U# u
- func blockChainGetHandle(w http.ResponseWriter, r *http.Request) {; g- @" K- Z5 ^: V* y
- bytes, err := json.Marshal(blockChain)
- if err != nil {! {, V; R& k5 B: G } g
- http.Error(w, err.Error(), http.StatusInternalServerError)( P# u( K1 Y! R2 P
- return9 n0 P% q4 y- ~3 `5 y7 M. L
- }
- io.WriteString(w, string(bytes)), l, Z' U, P. v* C+ f
- }; a2 Y% L, W) q1 a$ k
-
- func blockChainWriteHandle(w http.ResponseWriter, r *http.Request) {/ d8 j1 Y- P( N. d' K0 P
- blockData := r.URL.Query().Get("data")
- blockChain.SendData(blockData)
- blockChainGetHandle(w, r)/ S0 N1 n7 h# i+ R* w- O5 G
- }) f' ]: ]4 D; O! n4 t1 a( ]2 C7 c
- * \* S* y/ F# e+ p0 b' u
- func main() {7 D% t6 @/ x; R5 ^
- blockChain = core.NewBlockChain()6 i& @& q! I2 L/ K
- run()
- }
通过两部分代码实现简易区块链的RPC调用