200行go语言代码自建一个区块链体验挖矿乐趣(代码片段)

Technofiend Technofiend     2022-12-08     598

关键词:

谈谈区块链:
挖矿的目的:通过挖矿证明算力,防止他人作弊,自己又能获得奖励【给自己加钱】。
挖矿的过程:将网上别的合法且最新的用户交易同步过来,加入到区块,然后加随机数哈希后 与系统给出的值去比较。若符合条件则表示挖矿成功,挖矿成功了还不行,要赶紧告诉别人,我挖成功了,别让其他人抢风头。

挖矿更通俗的表现形式:我这里有编号为 1~1000000000000000个宝箱,其中某些宝箱里面有金子,获得这些金子的方法就是一个个去用钥匙打开,而这个宝箱钥匙的锻造方法就是用 其他人提供的金属来打造。

挖矿需要实时联网吗?
答案:否,只需要把最后的一个区块的哈希放进本区块的PrevHash即可,一般10分钟就更新最后一个区块了,所以还是得10分钟上链同步一下,至于别人提交的交易的账单,可放可不放到区块上,当然交易的账单里面有手续费,若放到区块可以将里面的手续费划到自己账上, 到时候世界上的矿都挖光了,矿场节点就是通过帮别人打包赚点手续费而已,但一般矿场都几乎实时在线同步其他节点收到的交易过来。

区块链以最长链为主链:
若有人捣乱,发一些错误的区块到其他节点上,其他节点不是傻子,肯定不接受,因此无法加入到链上。
除非,有一个算力很强的人想捣乱,他能在1秒钟算出正确的区块,并发布到其他节点,会出现什么情况?这个人由于算力太强了,他在算出区块的时候,不接受任何人的交易记录就生成区块了,那么对于用户来说,用户的交易久久不能进链,自然而然的放弃使用区块链了,而别的矿工看到如此强劲的对手也纷纷离场。

若同时算出区块,并提交到链上的情况:
有两个人同时算出答案,并告知其他小伙伴,我已经算出了答案。他们两个人都告诉了别人。那么他们谁才是胜利者?
这种情况则以下一个人算出的答案来决定上一次的胜利者。
由于下一个人是最新算出的,所以任何人无异议。

关于浪费
挖矿花掉的电力差不多150多个国家电力的总和,要是把挖矿改成算π,那样多少都有点贡献。
呃… 挖矿真的浪费了好多电力,于是乎有人发明一种不需要挖矿的方法,这种方式叫proof of shake,股权证明,大家有兴趣可以去研究一下。

比特币是泡沫吗?
不是,它是人类共同认可的一种虚拟货币,只不过它的价格决定于人民的认可度,而且没人能凭空造出比特币,因为比特币有很强的防伪,若有人伪造,一下子就能瞄出来了,在账本上别人账户上有多少钱都能看到,但是花不了,若要花自己的比特币之前,需要用一把超级安全的防伪造印章去盖一个章,就可以使用授权的钱了。
不妨我们改一种说法,美元是泡沫吗?可它只是一张纸啊,只不过它的价格决定于人民的认可度还有国家的调控,而且国家能凭空造出美元,因为美元由一个美国控制,别人不能通过银行看别人的账户,使用前只需要在银行输入密码取钱出来就可以与人交换货物或者服务了。

关于空气币
有某些黑恶原子份子制作了他们的区块链虽说是真的,但是缺乏人民的认可度,因此不值钱,那么他们通过什么方式赚钱?还是挖矿(挖一大部分币在自己手里先)----然后大肆宣扬什么什么新技术,大家赶紧过来买啊买啊买,哄抬市价,然后将手上的币卖出,只不过开始挖矿易如反掌,后期人多了,挖不了了,就产生了价值,但挖的人不多,币还是容易挖,容易挖就不值钱了,这种就叫做空气币。

package main

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/gorilla/mux"
)

const difficulty = 1 // 真正的比特币每两个星期就更新一次难度,其实是共识更新。

// 区块链的 块结构
type Block struct 
	Index      int
	Timestamp  string
	BPM        int
	Hash       string
	PrevHash   string
	Difficulty int
	Nonce      string


// 区块链的链(这里是块的一个数组,真正的是用kv数据库保存的呢!)
var Blockchain []Block

// 心跳值
type Message struct 
	BPM int


// 一把锁
var mutex = &sync.Mutex

func main() 
	// 创世块,啥都没
	go func() 
		t := time.Now()
		genesisBlock := Block
		genesisBlock = Block
			0,
			t.String(),
			0,
			calculateHash(genesisBlock),
			"",
			difficulty,
			"",
		

		spew.Dump(genesisBlock) // 显示创世块

		// 将创世块加入链
		mutex.Lock()
		Blockchain = append(Blockchain, genesisBlock)
		mutex.Unlock()
	()

	// 开启HTTP服务器
	log.Fatal(run())


// 网页服务器
func run() error 
	mux := makeMuxRouter()
	httpPort := "8080"
	log.Println("HTTP Server Listening on port :", httpPort)
	s := &http.Server
		Addr:           ":" + httpPort,
		Handler:        mux,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20,
	

	if err := s.ListenAndServe(); err != nil 
		return err
	

	return nil


// 创建路由
func makeMuxRouter() http.Handler 
	muxRouter := mux.NewRouter()
	muxRouter.HandleFunc("/", handleGetBlockchain).Methods("GET")
	muxRouter.HandleFunc("/", handleWriteBlock).Methods("POST")
	return muxRouter


// http 方法,得到当前所有区块
func handleGetBlockchain(w http.ResponseWriter, r *http.Request) 
	bytes, err := json.MarshalIndent(Blockchain, "", "  ")
	if err != nil 
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	
	io.WriteString(w, string(bytes))


// 上传心跳值,并且在挖出矿后将此心跳值加入区块。
func handleWriteBlock(w http.ResponseWriter, r *http.Request) 
	w.Header().Set("Content-Type", "application/json")
	var m Message

	decoder := json.NewDecoder(r.Body)
	if err := decoder.Decode(&m); err != nil 
		respondWithJSON(w, r, http.StatusBadRequest, r.Body)
		return
	
	defer r.Body.Close()

	//ensure atomicity when creating new block
	mutex.Lock()
	newBlock := generateBlock(Blockchain[len(Blockchain)-1], m.BPM)
	mutex.Unlock()

	if isBlockValid(newBlock, Blockchain[len(Blockchain)-1]) 
		Blockchain = append(Blockchain, newBlock)
		spew.Dump(Blockchain)
	

	respondWithJSON(w, r, http.StatusCreated, newBlock)


// 显示出json数据
func respondWithJSON(w http.ResponseWriter, r *http.Request, code int, payload interface) 
	w.Header().Set("Content-Type", "application/json")
	response, err := json.MarshalIndent(payload, "", "  ")
	if err != nil 
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte("HTTP 500: Internal Server Error"))
		return
	
	w.WriteHeader(code)
	w.Write(response)


// 验证区块是否正确
func isBlockValid(newBlock, oldBlock Block) bool 
	if oldBlock.Index+1 != newBlock.Index 
		return false
	

	if oldBlock.Hash != newBlock.PrevHash 
		return false
	

	if calculateHash(newBlock) != newBlock.Hash 
		return false
	

	return true


// 计算区块哈希
func calculateHash(block Block) string 
	record := strconv.Itoa(block.Index) + block.Timestamp + strconv.Itoa(block.BPM) + block.PrevHash + block.Nonce
	h := sha256.New()
	h.Write([]byte(record))
	hashed := h.Sum(nil)
	return hex.EncodeToString(hashed)


// 挖矿
func generateBlock(oldBlock Block, BPM int) Block 
	var newBlock Block

	t := time.Now()

	newBlock.Index = oldBlock.Index + 1
	newBlock.Timestamp = t.String()
	newBlock.BPM = BPM
	newBlock.PrevHash = oldBlock.Hash
	newBlock.Difficulty = difficulty

	for i := 0; ; i++ 
		hex := fmt.Sprintf("%x", i)
		newBlock.Nonce = hex
		if !isHashValid(calculateHash(newBlock), newBlock.Difficulty) 
			fmt.Println(calculateHash(newBlock), " do more work!")
			time.Sleep(time.Second) // 此处延时为了模拟真实
			continue
		 else 
			fmt.Println(calculateHash(newBlock), " work done!")
			newBlock.Hash = calculateHash(newBlock)
			break
		

	
	return newBlock


// 区块验证
func isHashValid(hash string, difficulty int) bool 
	prefix := strings.Repeat("0", difficulty)
	return strings.HasPrefix(hash, prefix)

以上代码的原理:
该区块链的区块用于存储的【人类心跳】,好处是别人想存必须先通过挖矿。
实际的区块链将【人类心跳】换成 交易记录。
本区块链由于是单节点,因此没有 币的地址。
只阐明挖矿原理。

代码详细解析:
https://medium.com/@mycoralhealth/code-your-own-blockchain-mining-algorithm-in-go-82c6a71aba1f

请在启动服务后,安装postman,向http://127.0.0.1:8080, 提交原生数据“BPM”: 50

只用200行go代码写一个自己的区块链!

 CoralHealth · 大约23小时之前 ·220次点击· 预计阅读时间7分钟 · 不到1分钟之前 开始浏览  区块链是目前最热门的话题,广大读者都听说过比特币,或许还有智能合约,相信... 查看详情

200行go代码实现自己的区块链——区块生成与网络通信(代码片段)

在第一篇文章[1]中,我们向大家展示了如何通过精炼的Go代码实现一个简单的区块链。如何计算每个块的Hash值,如何验证块数据,如何让块链接起来等等,但是所有这些都是跑在一个节点上的。文章发布后,读者反响热烈,纷纷... 查看详情

200行go代码实现自己的区块链——区块生成与网络通信(代码片段)

英文原版:https://medium.com/@mycoralhealth/code-your-own-blockchain-in-less-than-200-lines-of-go-e296282bcffc  原创 2018-02-09 CoralHealth 高可用架构在第一篇文章[1]中,我们向大家展示了如何通过精炼的Go代码实现一个简单的 查看详情

golang区块链开发002-初始化区块链与pow挖矿实现

目录:一.初始化区块链1.代码结构2.定义区块结构与方法3.定义区块链结构与方法4.帮助库代码5.测试生成区块与初始化区块链6.测试代码二.POW挖矿实现1.代码结构2.定义pow算法实现3.修改区块的生成方式(从自定义到挖矿)4.测试代码... 查看详情

只用120行java代码写一个自己的区块链-3挖矿算法(代码片段)

...列前两篇文章中,我们向大家展示了如何通过精炼的Java代码实现一个简单的区块链。包括生成块,验证块数据,广播通信等等,这一篇让我们聚焦在如何实现PoW算法。 大家都无不惊呼比特币、以太坊及其他加密电子货币的... 查看详情

区块链软件开发的搭建环境(代码片段)

区块链开发搭建的私有链环境通过本文所述方法和项目中的脚本,我们可以快速的搭建好自己的私有链进行区块链开发测试,本文基于以太坊技术进行搭建,两个部分,Windwos下搭建方法、Ubuntu下搭建方法一:??????使用节点进行... 查看详情

自己动手写区块链之交易中继(代码片段)

文章目录概览交易池广播未决交易有效性验证记账更新交易池体验启动两个节点(建议在两个命令行终端下)查看节点钱包地址挖矿查看未消费交易outputs查看节点自己拥有的未消费outputs发起交易节点1挖矿并记账查看未决交易池查... 查看详情

用go语言撸一个简易版的区块链(代码片段)

用go撸一个简易版的区块链引言这个最初的版本时多年以前学习go的时候,自己撸的一个简易版本的区块链。不过麻雀虽小,五脏俱全。通过这个代码你了解区块链内部的大概运行机制时没有问题的。比特币底层区块链的... 查看详情

用go语言撸一个简易版的区块链(代码片段)

用go撸一个简易版的区块链引言这个最初的版本时多年以前学习go的时候,自己撸的一个简易版本的区块链。不过麻雀虽小,五脏俱全。通过这个代码你了解区块链内部的大概运行机制时没有问题的。比特币底层区块链的... 查看详情

用go语言撸一个简易版的区块链(代码片段)

用go撸一个简易版的区块链引言这个最初的版本时多年以前学习go的时候,自己撸的一个简易版本的区块链。不过麻雀虽小,五脏俱全。通过这个代码你了解区块链内部的大概运行机制时没有问题的。比特币底层区块链的... 查看详情

区块链(代码片段)

...块链,搭建私链,智能合约以及开发DAPP。概念用人类的语言讲什么是区块链、挖矿、智能合约区块链公有链和私有链、联盟链、许可链区块链主流开源技术体系介绍什么是区块链广义:区块链是分布式数据存储,点对点传输,... 查看详情

使用go语言编写区块链p2p网络(译)(代码片段)

外文发表日期:2018-04-14外文链接:https://medium.com/coinmonks/code-a-simple-p2p-blockchain-in-go-46662601f417在之前的文章中,我们已经知道了怎么编写PoW也知道了IPFS怎么工作,但是有一个致命的缺点,我们的服务都是中心化的&#x... 查看详情

[go]用go语言实现区块链工作原理(代码片段)

基本原理这里就不写了,只写一个简单demo的实现首先得有一个区块用来存储区块头和区块体typeBlockstructVersionint64PreBlockHash[]byteHash[]byte//区块体内是不存储HASH值的,这是网络中某个节点在计算时存储在息本地的,这里是为了方便... 查看详情

cpp区块链模拟示例序列化(代码片段)

...币中是使用的是谷歌出品、c++编写的 LevelDB数据库,go语言示例中使用的是BoltDB。我本来考虑使 查看详情

基于共识算法和区块链模拟实现超级账本(代码片段)

基于共识算法和区块链模拟实现超级账本实验语言:GO实验环境:GoLand2022.1;go1.13.4.widows-amd64.msi;curl-7.83.1实验中使用的开源包:http://github.com/davecgh/go-spew/spew;http://github.com/gorilla/mux;http://github.com/joho... 查看详情

基于go语言构建区块链:part1(代码片段)

Golang语言和区块链理论学习完毕后,快速入门方法无疑是项目实战。本文将参考https://jeiwan.cc/tags/blockchain/教程,学习如何基于Go语言构建区块链。1、编程环境设置编程工具使用GoLand,前文已介绍软件安装经验。软件安装完成后... 查看详情

基于java语言构建区块链——持久化&命令行

引言上一篇文章我们实现了区块链的工作量证明机制(Pow),尽可能地实现了挖矿。但是距离真正的区块链应用还有很多重要的特性没有实现。今天我们来实现区块链数据的存储机制,将每次生成的区块链数据保存下来。有一点... 查看详情

用go构建一个区块链--part3:持久化和命令行接口(代码片段)

...在GitHub上,可能就不在这里同步了。如果想直接运行代码,也可以cloneGitHub上的教程仓库,进入src目录执行make即可。引言到目前为止,我们已经构建了一个有工作量证明机制的区块链。有了工作量证明ÿ 查看详情