Fabric Hyperledger Learning [9] Go 언어 기반의 단순 블록체인 수동 구현

프로젝트 구조

여기에 이미지 설명 삽입

block.go

package core

import (
	"crypto/sha256"
	"encoding/hex"
	"time"
)

type Block struct {
    
    
	Index         int64  // 区块编号
	Timestamp     int64  // 区块时间戳
	PrevBlockHash string // 上一个区块哈希值
	Hash          string // 当前区块哈希
	Data          string // 区块数据
}

func calculateHash(b Block) string {
    
    
	blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash + b.Data
	hashInBytes := sha256.Sum256([]byte(blockData))
	return hex.EncodeToString(hashInBytes[:])
}

func GenerateNewBlock(preBlock Block, data string) Block {
    
    
	newBlock := Block{
    
    }
	newBlock.Index = preBlock.Index + 1
	newBlock.PrevBlockHash = preBlock.Hash
	newBlock.Timestamp = time.Now().Unix()
	newBlock.Data = data
	newBlock.Hash = calculateHash(newBlock)
	return newBlock
}

func GenerateGenesisBlock() Block {
    
    
	preBlock := Block{
    
    }
	preBlock.Index = -1
	preBlock.Hash = ""
	return GenerateNewBlock(preBlock, "Genesis Block")
}

blockchain.go

package core

import (
	"fmt"
	"log"
)

type Blockchain struct {
    
    
	Blocks []*Block
}

func NewBlockchain() *Blockchain {
    
    
	genesisBlock := GenerateGenesisBlock()
	blockchain := Blockchain{
    
    }
	blockchain.AppendBlock(&genesisBlock)
	return &blockchain
}

func (bc *Blockchain) SendData(data string) {
    
    
	preBlock := bc.Blocks[len(bc.Blocks)-1]
	newBlock := GenerateNewBlock(*preBlock, data)
	bc.AppendBlock(&newBlock)
}

func (bc *Blockchain) AppendBlock(newBlock *Block) {
    
    
	if len(bc.Blocks) == 0 {
    
    
		bc.Blocks = append(bc.Blocks, newBlock)
		return
	}
	if isValid(*newBlock, *bc.Blocks[len(bc.Blocks)-1]) {
    
    
		bc.Blocks = append(bc.Blocks, newBlock)
	} else {
    
    
		log.Fatal("invalid block")
	}
}

func (bc *Blockchain) Print() {
    
    
	for _, block := range bc.Blocks {
    
    
		fmt.Printf("Index: %d\n", block.Index)
		fmt.Printf("PrevHash: %s\n", block.PrevBlockHash)
		fmt.Printf("CurrHash: %s\n", block.Hash)
		fmt.Printf("Data: %s\n", block.Data)
		fmt.Printf("Timestamp: %d\n", block.Timestamp)
	}
}

func isValid(newBlock Block, oldBlock Block) bool {
    
    
	if newBlock.Index-1 != oldBlock.Index {
    
    
		return false
	}
	if newBlock.PrevBlockHash != oldBlock.Hash {
    
    
		return false
	}
	if calculateHash(newBlock) != newBlock.Hash {
    
    
		return false
	}
	return true
}

server.go는 간단한 호출을 위해 인터페이스를 캡슐화합니다.

package main

import (
	"encoding/json"
	"go-blockchain/core"
	"io"
	"net/http"
)

var blockchain *core.Blockchain

func run() {
    
    
	http.HandleFunc("/blockchain/get", blockchainGetHandler)
	http.HandleFunc("/blockchain/write", blockchainWriteHandler)
	http.ListenAndServe("localhost:8080", nil)
}

func blockchainGetHandler(w http.ResponseWriter, r *http.Request) {
    
    

	//bytes, err := json.MarshalIndent(Blockchain, "", "  ")

	bytes, error := json.Marshal(blockchain)
	if error != nil {
    
    
		http.Error(w, error.Error(), http.StatusInternalServerError)
		return
	}
	io.WriteString(w, string(bytes))
}

func blockchainWriteHandler(w http.ResponseWriter, r *http.Request) {
    
    
	blockData := r.URL.Query().Get("data")
	blockchain.SendData(blockData)
	blockchainGetHandler(w, r)
}

func main() {
    
    
	blockchain = core.NewBlockchain()
	run()
}

블록체인의 블록에 데이터 쓰기

http://localhost:8888/blockchain/write?data=Fabric 超级账本学习【9】基于Go语言自己动手实现区块链

여기에 이미지 설명 삽입

블록체인의 블록 데이터 읽기

http://localhost:8888/blockchain/get

여기에 이미지 설명 삽입

Guess you like

Origin blog.csdn.net/weixin_42694422/article/details/129986511