通过http实现RPC命令的调用 实现添加块
查询当前所有块的信息# G0 l( `+ S; t2 e1 P7 b
& W, V& S4 h* u! a- T- M
这里只做了两个命令 分别是get和write) g4 @1 N/ ]- s8 n6 u3 N" q! B; K
源代码如下
基础功能的实现
package core6 U, b$ K: ?( n- ]8 B. X3 R& @3 D* d
import (
"crypto/sha256"
"encoding/hex"
"time"
)
//定义区块
type Block struct {
Index int64 //区块编号3 U h$ S' v7 t+ u- g
- Timestamp int64 //区块时间戳6 Q6 v. A9 O) W6 {* L2 @0 v) o
- PrevBlockHash string //上一个区块的hash值
- Hash string //当前区块哈希值
- Data string //区块数据
- }
- //计算Hash
- func calculateHash(b *Block) string {- W+ l8 M% f3 m, ]3 Y T6 i
- blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash7 \3 S2 X( w5 ^1 y' v2 v
- hashInBytes := sha256.Sum256([]byte(blockData))8 l5 N3 \5 ~% D. ?
- return hex.EncodeToString(hashInBytes[:])
- }
1 D, Z) p9 j$ W5 d
//生成新的区块: B) {1 x) f1 [5 y
func GenerateNewBlock(preBlock *Block, data string) *Block {
newBlock := &Block{}
newBlock.Index = preBlock.Index + 15 s# z% K3 R5 n7 E
newBlock.PrevBlockHash = preBlock.Hash
newBlock.Timestamp = time.Now().Unix()
newBlock.Hash = calculateHash(newBlock)
newBlock.Data = data3 G' J: j. A: F0 n" d: t2 H
return newBlock' x! ~7 s: f* L+ v# ~$ R6 I
}1 f/ d: k' {% N4 v% I; m
7 J( _: l, ~. L6 k! i9 Z
//生成创始区块6 [0 g' q; s0 J1 x5 H/ r
func GenerateGenesisBlock() *Block {, f, C, m7 @3 c+ z! s
preBlock := &Block{}- Z, d, M) |) \9 |2 Z
preBlock.Index = -1+ [3 N" d9 ^1 c3 U( G7 C
preBlock.Hash = ""
return GenerateNewBlock(preBlock, "Genesis Block")
}
将基础功能实现的块进行链接 实现blockchain3 g0 S- x7 c/ e& p8 H
package core4 ?8 i0 J4 Z( g/ a/ c1 e7 U: S
import (
"fmt"
"log"
)" f! E+ `( ~ W0 m. ^1 `4 f
//定义区块链
type BlockChain struct {
Blocks []*Block
}
# C2 v" }0 C! c! q3 ~* W, g- U
//创建一个区块链
func NewBlockChain() *BlockChain {% d5 t2 K N4 v8 q* B% v9 R. M; {
genesisBlock := GenerateGenesisBlock()
blockChain := &BlockChain{}
blockChain.AppendBlock(genesisBlock)# ?( i7 F' d) r1 j) k6 D+ C" }2 c
return blockChain# ?* W' h5 m# k- S! @/ J/ S
}
//记录区块数据
func (bc *BlockChain) SendData(data string) {
preBlock := bc.Blocks[len(bc.Blocks)-1]
newBlock := GenerateNewBlock(preBlock, data)+ x& w5 Y% U9 [$ a; C$ ?2 w2 T
bc.AppendBlock(newBlock)
}
//往区块链添加区块0 F3 @6 r6 J; p" B
func (bc *BlockChain) AppendBlock(newBlock *Block) {
if len(bc.Blocks) == 0 {
bc.Blocks = append(bc.Blocks, newBlock)
return) h" Q; O' `, Q: u
}4 m$ X0 ~0 H H- j8 {! C
if isValid(newBlock, bc.Blocks[len(bc.Blocks)-1]) {
bc.Blocks = append(bc.Blocks, newBlock)/ i% q4 b0 W( M4 Z) \
} else {/ B* y* k% `8 I
log.Fatal("invalid block")( h4 D& |$ M; ~' o
}
return; t. q+ d* m# v# q c: D
}
//输出区块链信息- x5 K- Y' @# q) f) i' Y
func (bc *BlockChain) Print() {' X; o, b, U: @: @
for _, block := range bc.Blocks {% |& G' e" O" a. z6 y- b) a
fmt.Printf("Index : %d\n", block.Index)% Z, p8 y% H" y
fmt.Printf("Prev.Hash : %s\n", block.PrevBlockHash)
fmt.Printf("Curr.Hash : %s\n", block.Hash)
fmt.Printf("Curr.Data : %s\n", block.Data)
fmt.Printf("Curr.Timestamp : %d\n", block.Timestamp); ~8 O" `9 h0 m! `
fmt.Println("==========================================")
}
}+ H- S' Z& u+ m
8 O7 Y: F& \- v/ h& q
//验证区块
func isValid(newBlock *Block, oldBlock *Block) bool {
if newBlock.Index-1 != oldBlock.Index {
return false. x7 }" K6 d" I" J$ R( u# _- X' v8 i
}& A, S# d ?9 b) j4 X$ e
if newBlock.PrevBlockHash != oldBlock.Hash {
return false+ _$ r; |/ y- _9 c r6 T
}
if calculateHash(newBlock) != newBlock.Hash {
return false1 s K' z6 T. _9 u6 `
}) Z1 |3 L% |& |# q9 J1 W
return true: O9 a" V) q8 p5 P
}# l4 w; F" L: Z$ y7 p
实现RPC接口的交互! D7 B4 V& e' t
- package main3 F, g$ W: D. B" c6 G S6 g" s
- 4 p( M* V# \ ?- v
- import (
- "encoding/json"" l2 Q8 J, D8 z: {
- "BlockChain/core"& w ^' Z/ O. d) h
- "io"
- "net/http"
- )
-
- var blockChain *core.BlockChain$ u' J: a9 @. L( b( }
-
- func run() {
- http.HandleFunc("/block_chain/get", blockChainGetHandle), D4 [8 i. _: o g
- http.HandleFunc("/block_chain/write", blockChainWriteHandle)
- http.ListenAndServe(":8332", nil)3 C( P/ x0 t: W; k( z: T
- }
-
- func blockChainGetHandle(w http.ResponseWriter, r *http.Request) {
- bytes, err := json.Marshal(blockChain)8 j! k2 T! f& Z* K! }
- if err != nil {( n& j4 K" n# v1 F3 @5 Z, e
- http.Error(w, err.Error(), http.StatusInternalServerError)2 ^6 h% G; x" Y/ J; ^5 e
- return' Y S$ h! q" F0 o
- }
- io.WriteString(w, string(bytes))
- }
-
- func blockChainWriteHandle(w http.ResponseWriter, r *http.Request) {
- blockData := r.URL.Query().Get("data")
- blockChain.SendData(blockData)
- blockChainGetHandle(w, r)0 H' V' H% b; |- o
- }5 v1 L% J0 y+ t6 g
-
- func main() {
- blockChain = core.NewBlockChain()
- run()% J$ i, ?! w; n- r( g1 |7 o
- }
通过两部分代码实现简易区块链的RPC调用