golang 100行代码实现区块链原型

有人说今年(2018年)是区块链技术元年,作为一种新兴的技术,它不仅弯道超车盖过了人工智能、大数据的风头,而且发展速度更是一日千里。各大厂商都相继推出区块链服务,你可能觉得难以置信。不管你信不信,当你还在熟睡时,有一群人还在挑灯夜战。

在周未闲来无事,虽然之前网上也有各版本的区块链代码,还是动手用golang写了一下,简单实现了区块链的原型。代码如下:

package main

import (
	"crypto/sha256"
	"encoding/json"
	"fmt"
)

//Block 结构
type Block struct {
	Index        int
	Timestamp    string
	Data         string
	PreviousHash string
	Hash         string
}

//CalculateHash 计算HASH
func (b *Block) CalculateHash() string {
	s := fmt.Sprintf("%d%s%s%s", b.Index, b.PreviousHash, b.Timestamp, b.Data)
	sum := sha256.Sum256([]byte(s))
	return fmt.Sprintf("%x", sum)
}

//BlockChain 结构
type BlockChain struct {
	Chain []*Block
}

//NewBlockChain 创建区块链
func NewBlockChain() *BlockChain {
	bc := &BlockChain{}
	bc.Chain = append(bc.Chain, bc.CreateGenesisBlock())
	return bc
}

//CreateGenesisBlock 创建创世块
func (bc *BlockChain) CreateGenesisBlock() *Block {
	b := &Block{
		Index:        0,
		Timestamp:    "2018-01-01",
		Data:         "Genesis Block",
		PreviousHash: "0",
	}
	b.Hash = b.CalculateHash()
	return b
}

//GetLatestBlock 最新区块
func (bc *BlockChain) GetLatestBlock() *Block {
	return bc.Chain[len(bc.Chain)-1]
}

//AddBlock 增加区块
func (bc *BlockChain) AddBlock(newBlock *Block) {
	newBlock.Index = bc.GetLatestBlock().Index + 1
	newBlock.PreviousHash = bc.GetLatestBlock().Hash
	newBlock.Hash = newBlock.CalculateHash()
	bc.Chain = append(bc.Chain, newBlock)
}

//IsChainValid 区块是否有效
func (bc *BlockChain) IsChainValid() bool {
	for i := 1; i < len(bc.Chain); i++ {
		currentBlock := bc.Chain[i]
		previousBlock := bc.Chain[i-1]

		if currentBlock.Hash != currentBlock.CalculateHash() {
			return false
		}

		if currentBlock.PreviousHash != previousBlock.Hash {
			return false
		}
	}
	return true
}

func main() {
	bc := NewBlockChain()
	bc.AddBlock(&Block{Timestamp: "2018-02-01", Data: `{"amout":10}`})
	bc.AddBlock(&Block{Timestamp: "2018-03-01", Data: `{"amout":20}`})
	bc.AddBlock(&Block{Timestamp: "2018-04-01", Data: `{"amout":30}`})

	blockchain, _ := json.MarshalIndent(bc, "", "\t")
	fmt.Println(string(blockchain))

	fmt.Println("is BlockChain valid ", bc.IsChainValid())
}