- Proof-of-Work 简称 PoW,即为工作量证明
- 通过计算一个数值,使得拼揍上交易数据后内容的值满足规定的上限,在节点成功 找到满足的 Hash 值之后,会马上对全网进行广播打包区块,网络的节点收到广播 打包区块,会立刻对其进行验证
- 网络中只有最快解密的区块,才会添加的账本中,其他的节点进行复制,这样就保 证了整个账本的唯一性
- 假如节点有任何的作弊行为,都会导致网络的节点验证不通过,直接丢弃其打包的 区块,这个区块就无法记录到总账本中,作弊的节点耗费的成本就白费了,因此在 巨大的挖矿成本下,也使得矿工自觉自愿的遵守比特币系统的共识协议,也就确保 了整个系统的安全
安装依赖
- go get github.com/davecgh/go-spew/spew
在cmd或控制台格式化输出相应的结果
- go get github.com/gorilla/mux
编写web处理程序的软件包
- go get github.com/joho/godotenv
可以从项目根目录读取 .env结束的文件,读取文件中的数据,如果在linux开发,.env文件放在项目的根目录下即可,如果windows和mac开发,.env是放在GOPATH/src下
PoW总结
- 优点
- 挖矿机制本身比较复杂,难度的自动调整,区块奖励逐步减半,这些是基于经济学原理,能吸引和鼓励更多人参与其中
- 越先参与的获得越多,会促使加密货币初始阶段迅速发展,网络节点迅速扩大,比特币吸引了N多人参与挖矿
- 通过挖矿,发行新币,把比特币分散给了个人,实现了相对的公平
- 缺点
- 算力是计算机硬件提供的,直接耗费电力,对能源的直接消耗
- 随着发展,算力已经不是单纯CPU能搞定的了,GPU,FPGA,以及ASIC矿机,这些可能不是个人能轻松实现的,导致算力中心化,长远来看,与去中心和背道而驰,网络的安全受到威胁
- 比特币区块奖励每4年减半,挖矿成本越来越高,当挖矿成本高于挖矿收益时,挖矿的积极性降低,整体网络不稳定
代码
@定义区块
第一步:定义区块
type Block struct {
//上一个区块的哈希
PreHash string
//当前区块的哈希
HashCode string
//时间戳
TimeStamp string
//难度系数
Diff int
//交易信息
Data string
//区块高度
Index int
//随机值
Nonce int
}
第二步:定义第一个区块(创世区块)
//第一个区块:创世区块
func GenerateFirstBlock(data string) Block {
//创建第一个Block
var firstblock Block
firstblock.PreHash = "0"
firstblock.TimeStamp = time.Now().String()
//暂设为4
firstblock.Diff = 4
//交易信息
firstblock.Data = data
firstblock.Index = 1
firstblock.Nonce = 0
//通过sha256得到自己的哈希
firstblock.HashCode = GenerationHashValue(firstblock)
return firstblock
}
//生成区块的哈希值
func GenerationHashValue(block Block) string {
//按照比特币的写法,将区块的所有属性拼接后做哈希运算
//int转为字符串
var hashdata = strconv.Itoa(block.Index) + strconv.Itoa(block.Nonce) +
strconv.Itoa(block.Diff) + block.TimeStamp
//算哈希
var sha = sha256.New()
sha.Write([]byte(hashdata))
hashed := sha.Sum(nil)
return hex.EncodeToString(hashed)
}
第三步:定义PoW算法
//pow算法
func pow(diff int, block *Block) string {
//实现不停地去挖矿
for {
//认为是挖了一次矿了
hash := GenerationHashValue(*block)
//挖矿过程的哈希打印
fmt.Println(hash)
//判断哈希值前导0是否为diff个0
//strings.Repeat:判断hash是否有diff个0,写1,就判断为有多少个1
if strings.HasPrefix(hash, strings.Repeat("0", diff)) {
//挖矿成功
fmt.Println("挖矿成功")
return hash
} else {
//没挖到
//随机值自增
block.Nonce++
}
}
}
第四步:创建新的区块
//产生新的区块
func GenerateNextBlock(data string, oldBolock Block) Block {
//产生一个新的区块
var newBlock Block
newBlock.TimeStamp = time.Now().String()
//难度系数
newBlock.Diff = 5
//高度
newBlock.Index = 2
newBlock.Data = data
newBlock.PreHash = oldBolock.HashCode
newBlock.Nonce = 0
//创建pow()算法的方法
//计算前导0为4个的哈希值
newBlock.HashCode = pow(newBlock.Diff, &newBlock)
return newBlock
}
第五步:主函数
func main() {
//测试创建创世区块
var firstBlock = GenerateFirstBlock("创世区块")
fmt.Println(firstBlock)
fmt.Println(firstBlock.Data)
//需要生成下一个区块
GenerateNextBlock("第二区块", firstBlock)
}
@定义区块链,用链表实现区块链的链
第一步:定义区块链
//定义区块链
type Node struct {
//指针域
NextNode *Node
//数据域
Data *Block.Block
}
第二步:创建头节点
//创建头节点,保存创世区块
func CreateHeaderNode(data *Block.Block) *Node {
//先去初始化
var headerNode = new(Node)
//指针域指向nil
headerNode.NextNode = nil
//数据域
headerNode.Data = data
//返回头节点,后面再添加
return headerNode
}
第三步:添加区块,添加节点
func AddNode(data *Block.Block, node *Node) *Node {
//创建新节点
var newNode = new(Node)
//指针域指向nil
newNode.NextNode = nil
newNode.Data = data
//链表连起来
node.NextNode = newNode
return newNode
}
第四步:查看链表中的数据
func ShowNodes(node *Node) {
//接收node
n := node
for {
//如果下个节点为nil
if n.NextNode == nil {
fmt.Println(n.Data)
break
} else {
fmt.Println(n.Data)
n = n.NextNode
}
}
}
第五步:定义主函数
func main() {
var first = Block.GenerateFirstBlock("创世区块")
var second = Block.GenerateNextBlock("第二区块", first)
//创建链表
//头节点保存创世区块
var header = Blockchain.CreateHeaderNode(&first)
//将第二区块加入链表
Blockchain.AddNode(&second, header)
//查看链表信息
Blockchain.ShowNodes(header)
}