只用120行Java代码写一个自己的区块链-3挖矿算法 - 文和-Mignet - 博客园
会员
周边
新闻
博问
AI培训
云市场
所有博客
当前博客
我的博客
我的园子
账号设置
简洁模式 ...
退出登录
注册
登录
架构理念:[简单][高效][可依赖] 管理理念:[价值][勇气][专注]
Certified Scrum Master/MapReduce Raft /Java Go Rust
https://github.com/Mignet - 文和-MIGNET
博客园
首页
新随笔
联系
订阅
管理
只用120行Java代码写一个自己的区块链-3挖矿算法
在本系列前两篇文章中,我们向大家展示了如何通过精炼的Java代码实现一个简单的区块链。包括生成块,验证块数据,广播通信等等,这一篇让我们聚焦在如何实现 PoW算法。
大家都无不惊呼比特币、以太坊及其他加密电子货币的持续狂热,特别是对于刚接触这个领域的新手,不断得听到张三李四通过 GPU “挖矿”而聚集价值数万乃至数百万加密电子货币。那么“挖矿”到底是什么? 它是如何工作的? 相信对于程序员来说,没有什么比自己动手实践一遍“挖矿”算法更好的学习办法了。在这篇文章中,让我们一起逐个解读每一个问题,并最终编写出自己的“挖矿”算法。这个算法称为工作证明算法(Proof-of-Work),它是比特币和以太坊这两种最流行的加密货币的基础。
什么是“挖矿”?
加密电子货币因为稀缺才具有价值。以现在的比特币为例,如果任何人任何时候都可以随意“制造”比特币,那么作为电子货币它会变得毫无价值。比特币通过算法来控制产出的速率并在大约122年内达到最大量。这种随着时间推移缓慢、稳定并逐步产出的方式有效避免了通货膨胀。比特币的产出是通过给予“获胜矿工”奖励来实现,为了获取比特币奖励矿工之间会进行竞争。这个过程之所以被称为“挖矿”,是因为它类似于“Gold Rush”时每个黄金矿工通过辛苦劳作并最终(希望)找到一点黄金。
“挖矿”是如何工作的?
如果 Google 一下这个问题,你会得到大量的结果。简单来说,“挖矿”就是“解决一个数学难题”的过程。我们先来了解一些密码学和哈希算法的知识。
密码学简要介绍
单向加密以人类可读的文本(明文)作为输入,比如“Hello world”这个字符串,再通过一个数学函数产生出难以辨认的输出(密文)。 这类函数或算法的性质和复杂性各不相同。 算法越复杂,逆向工程就越困难。 以流行的 SHA-256 算法为例。 通过这个网站可以让你计算任意给定输入的输出,也就是 SHA-256 哈希值。比如让我们输入“Hello world”,看看得到了什么:
通过不断尝试计算“Hello world”的哈希值。你会发现每次的结果都完全相同。 这个过程称为幂等性。
加密算法一个最基本的特性是,非常难以通过反向工程来求解输入,但是非常容易验证输出。比如上面的例子,你可以很容易验证给定输入“Hello world”的SHA-256哈希值是否正确,但很难通过给定的哈希值判断它的输入是什么。这就是为什么将这种类型的算法称为单向加密。比特币使用 Double SHA-256,它将 SHA-256 求得的哈希值作为输入再次计算 SHA-256 哈希值。 为了简化,我们只使用一次SHA-256。
挖矿
回到加密电子货币中,比特币就是通过让参与者利用这样的加密算法求解出符合特定条件的哈希值来实现“挖矿”过程。具体来说,比特币要求参与者通过 double SHA-256 算法计算出“前导0”超过若干位的哈希值,第一个求解出来的参与者就是“获胜的矿工”。比如,我们求“886”这个字符串的 SHA-256 哈希值:
可以看到,是一个“前导0”为3位的哈希值(前三位是0)。
回忆我们前面说到的“单向加密”的特点:任何人都可以很容易地验证“886”是否产生3位“前导0”的哈希值。但为了找到这样一个能产生3位“前导0”的输入(就是这里的“886”),我们做了大量繁琐的计算工作:从一个很大的数字和字母集合中逐个计算它们的哈希值并判断是否满足上述条件。如果我是第一个找到“886”的人,那其他人通过验证就能判断我做了这样大量繁琐的工作。在比特币、以太坊中这样的过程就称为工作证明算法。“如果我运气非常好,第一次尝试就找到了一个符合条件的(输入)值呢?” —— 这是非常不可能的,你可以试试随意输入一些字母和数字。比特币中实际的算法和约束要比上说要求复杂,当然也更难(要求更多位的“前导0”)。同时它也可以动态调整难度,目标是确保每隔10分钟产出一次比特币,不管参与“挖矿”的人多还是少。
差不多可以动手了
了解了足够的背景知识,接着我们就用 Java语言来编码实践下工作量证明(Proof-of-Work)算法。建议你阅读之前的系列文章,因为下面工作证明算法部分会涉及之前的代码。
Proof-of-work
创建新块并加入到链上之前需要完成“工作量证明”过程。我们先写一个简单的函数来检查给定的哈希值是否满足要求。
哈希值必须具有给定位的“前导0”
“前导0”的位数是由难度(difficulty)决定的
可以动态调整难度(difficulty)来确保 Proof-of-Work 更难解
下面就是 isHashValid 这个函数:
/**
* 校验HASH的合法性
*
* @param hash
* @param difficulty
* @return
*/
public static boolean isHashValid(String hash, int difficulty) {
String prefix = repeat("0", difficulty);
return hash.startsWith(prefix);
}
private static String repeat(String str, int repeat) {
final StringBuilder buf = new StringBuilder();
for (int i = 0; i < repeat; i++) {
buf.append(str);
}
return buf.toString();
}
我们定义prefix 变量,它代表“前导0”,接着检查哈希值是否具有满足条件的“前导0”,然后返回 True 或 False 。我们修改之前生成块的generateBlock 函数:
public static Block generateBlock(Block oldBlock, int vac) {
Block newBlock = new Block();
newBlock.setIndex(oldBlock.getIndex() + 1);
newBlock.setTimestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
newBlock.setVac(vac);
newBlock.setPrevHash(oldBlock.getHash());
newBlock.setDifficulty(difficulty);
/*
* 这里的 for 循环很重要: 获得 i 的十六进制表示 ,将 Nonce 设置为这个值,并传入 calculateHash 计算哈希值。
* 之后通过上面的 isHashValid 函数判断是否满足难度要求,如果不满足就重复尝试。 这个计算过程会一直持续,直到求得了满足要求的
* Nonce 值,之后通过 handleWriteBlock 函数将新块加入到链上。
*/
for (int i = 0;; i++) {
String hex = String.format("%x", i);
newBlock.setNonce(hex);
if (!isHashValid(calculateHash(newBlock), newBlock.getDifficulty())) {
System.out.printf("%s do more work!\n", calculateHash(newBlock));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
LOGGER.error("error:", e);
}
continue;
} else {
System.out.printf("%s work done!\n", calculateHash(newBlock));
newBlock.setHash(calculateHash(newBlock));
break;
}
}
return newBlock;
}
篇幅有限,我已经将完整代码发布在 Github上,可以从这里获得。
跑起来看看
启动程序,在浏览器中访问 http://localhost:4567
接着通过 RestClient 来发送一个包含vac数据的POST 请求。我们观察命令行窗口,不断得计算哈希值,如果不满足难度要求就继续重试,直到找到满足要求的哈希值及 Nonce
可以看到最后一个哈希值满足我们设定的难度要求(1位“前导0”)。我们再来刷新下浏览器:
可以看到第二个块创建成功并加到链上了,其中Nonce 就是通过Proof-of-Work计算出来满足难度要求的值。
下一步
到这里要先祝贺你,上面的内容很有价值。尽管我们的示例中使用了非常低的难度,但本质上,工作证明算法就是比特币、以太坊等区块链的重要组成根本。对于下一步应该深入区块链的哪个方向,我们推荐可以学习如何通过 IPFS存取大文件并与区块链打通。[IPFS]此外相比 Proof-of-Work,Proof-of-Stake 算法正越来越受到关注和青睐,你也可以学习如何将本文的 PoW 算法改为实现 PoS 算法。
posted @
2018-03-09 18:29
文和-Mignet
阅读(5652)
评论(3)
编辑
收藏
举报
会员力量,点亮园子希望
刷新页面返回顶部
公告
Copyright © 2024 文和-Mignet
Powered by .NET 8.0 on Kubernetes
挖矿原理 - 廖雪峰的官方网站
Index
廖雪峰的官方网站
Blog
Java教程
手写Spring
手写Tomcat
Makefile教程
Python教程
JavaScript教程
区块链教程
SQL教程
Git教程
文章
问答
More
Java教程
手写Spring
手写Tomcat
Makefile教程
Python教程
JavaScript教程
区块链教程
SQL教程
Git教程
文章
问答
Java教程
手写Spring
手写Tomcat
Makefile教程
Python教程
JavaScript教程
区块链教程
SQL教程
Git教程
文章
问答
Profile
Passkey
Sign Out
Sign In
English
简体中文
Index
区块链教程
比特币
区块链原理
P2P交易原理
私钥
公钥和地址
签名
挖矿原理
可编程支付原理
多重签名
UTXO模型
Segwit地址
HD钱包
钱包层级
助记词
地址监控
以太坊
账户
区块结构
交易
智能合约
编写合约
部署合约
调用合约
编写Dapp
常用合约
ERC20
Wrapped Ether
关注公众号不定期领红包:
加入知识星球社群:
关注微博获取实时动态:
挖矿原理
Last updated: ...
/
Reads: 3281443
Edit
在比特币的P2P网络中,有一类节点,它们时刻不停地进行计算,试图把新的交易打包成新的区块并附加到区块链上,这类节点就是矿工。因为每打包一个新的区块,打包该区块的矿工就可以获得一笔比特币作为奖励。所以,打包新区块就被称为挖矿。
比特币的挖矿原理就是一种工作量证明机制。工作量证明POW是英文Proof of Work的缩写。
在讨论POW之前,我们先思考一个问题:在一个新区块中,凭什么是小明得到50个币的奖励,而不是小红或者小军?
当小明成功地打包了一个区块后,除了用户的交易,小明会在第一笔交易记录里写上一笔“挖矿”奖励的交易,从而给自己的地址添加50个比特币。为什么比特币的P2P网络会承认小明打包的区块,并且认可小明得到的区块奖励呢?
因为比特币的挖矿使用了工作量证明机制,小明的区块被认可,是因为他在打包区块的时候,做了一定的工作,而P2P网络的其他节点可以验证小明的工作量。
工作量证明
什么是工作量证明?工作量证明是指,证明自己做了一定的工作量。例如,在驾校学习了50个小时。而其他人可以简单地验证该工作量。例如,出示驾照,表示自己确实在驾校学习了一段时间:
比特币的工作量证明需要归结为计算机计算,也就是数学问题。如何构造一个数学问题来实现工作量证明?我们来看一个简单的例子。
假设某个学校的一个班里,只有一个女生叫小红,其他都是男生。每个男生都想约小红看电影,但是,能实现愿望的只能有一个男生。
到底选哪个男生呢?本着公平原则,小红需要考察每个男生的诚意,考察的方法是,出一道数学题,比如说解方程,谁第一个解出这个方程,谁就有资格陪小红看电影:
因为解高次方程没有固定的公式,需要进行大量的计算,才能算出正确的结果,这个计算过程就需要一定的工作量。假设小明率先计算出了结果x=2.5,小红可以简单地验证这个结果是否正确:
可以看出,解方程很困难,但是,验证结果却比较简单。所以,一个有效的工作量证明在于:计算过程非常复杂,需要消耗一定的时间,但是,验证过程相对简单,几乎可以瞬间完成。
现在出现了另一个问题:如果其他人偷看了小明的答案并且抢答了怎么办?
要解决这个问题也很容易,小红可以按照男生的编号,给不同的男生发送不同的方程,方程的第一项的系数就是编号。这样,每个人要解的方程都是不一样的。小明解出的x=2.5对于小军来说是无效的,因为小军的编号是3,用小明的结果验证小军的方程是无法通过验证的。
事实上如果某个方程被验证通过了,小红可以直接从方程的第一项系数得知是谁解出的方程。所以,窃取别人的工作量证明的结果是没有用的。
通过工作量证明,可以有效地验证每个人确实都必须花费一定时间做了计算。
在比特币网络中,矿工的挖矿也是一种工作量证明,但是,不能用解多项式方程来实现,因为解多项式方程对人来说很难计算,对计算机来说非常容易,可以在1秒钟以内完成。
要让计算机实现工作量证明,必须找到一种工作量算法,让计算机无法在短时间内算出来。这种算法就是哈希算法。
通过改变区块头部的一个nonce字段的值,计算机可以计算出不同的区块哈希值:
直到计算出某个特定的哈希值的时候,计算结束。这个哈希和其他的哈希相比,它的特点是前面有好几个0:
hash256(block data, nonce=0) = 291656f37cdcf493c4bb7b926e46fee5c14f9b76aff28f9d00f5cca0e54f376f
hash256(block data, nonce=1) = f7b2c15c4de7f482edee9e8db7287a6c5def1c99354108ef33947f34d891ea8d
hash256(block data, nonce=2) = b6eebc5faa4c44d9f5232631f39ddf4211443d819208da110229b644d2a99e12
hash256(block data, nonce=3) = 00aeaaf01166a93a2217fe01021395b066dd3a81daffcd16626c308c644c5246
hash256(block data, nonce=4) = 26d33671119c9180594a91a2f1f0eb08bdd0b595e3724050acb68703dc99f9b5
hash256(block data, nonce=5) = 4e8a3dcab619a7ce5c68e8f4abdc49f98de1a71e58f0ce9a0d95e024cce7c81a
hash256(block data, nonce=6) = 185f634d50b17eba93b260a911ba6dbe9427b72f74f8248774930c0d8588c193
hash256(block data, nonce=7) = 09b19f3d32e3e5771bddc5f0e1ee3c1bac1ba4a85e7b2cc30833a120e41272ed
...
hash256(block data, nonce=124709132) = 00000000fba7277ef31c8ecd1f3fef071cf993485fe5eab08e4f7647f47be95c
比特币挖矿的工作量证明原理就是,不断尝试计算区块的哈希,直到计算出一个特定的哈希值,它比难度值要小。
比特币使用的SHA-256算法可以看作对随机输入产生随机输出,例如,我们对字符串Hello再加上一个数字计算两次SHA-256,根据数字的不同,得到的哈希是完全无规律的256位随机数:
hash256("Hello?") = ????????????????????????????????????????????????????????????????
大约计算16次,我们可以在得到的哈希中找到首位是0的哈希值,因为首位是0出现的概率是1/16:
hash256("Hello1") = ffb7a43d629d363026b3309586233ab7ffc1054c4f56f43a92f0054870e7ddc9
hash256("Hello2") = e085bf19353eb3bd1021661a17cee97181b0b369d8e16c10ffb7b01287a77173
hash256("Hello3") = c5061965d37b8ed989529bf42eaf8a90c28fa00c3853c7eec586aa8b3922d404
hash256("Hello4") = 42c3104987afc18677179a4a1a984dbfc77e183b414bc6efb00c43b41b213537
hash256("Hello5") = 652dcd7b75d499bcdc61d0c4eda96012e3830557de01426da5b01e214b95cd7a
hash256("Hello6") = 4cc0fbe28abb820085f390d66880ece06297d74d13a6ddbbab3b664582a7a582
hash256("Hello7") = c3eef05b531b56e79ca38e5f46e6c04f21b0078212a1d8c3500aa38366d9786d
hash256("Hello8") = cf17d3f38036206cfce464cdcb44d9ccea3f005b7059cff1322c0dd8bf398830
hash256("Hello9") = 1f22981824c821d4e83246e71f207d0e49ad57755889874d43def42af693a077
hash256("Hello10") = 8a1e475d67cfbcea4bcf72d1eee65f15680515f65294c68b203725a9113fa6bf
hash256("Hello11") = 769987b3833f082e31476db0f645f60635fa774d2b92bf0bab00e0a539a2dede
hash256("Hello12") = c2acd1bb160b1d1e66d769a403e596b174ffab9a39aa7c44d1e670feaa67ab2d
hash256("Hello13") = dab8b9746f1c0bcf5750e0d878fc17940db446638a477070cf8dca8c3643618a
hash256("Hello14") = 51a575773fccbb5278929c08e788c1ce87e5f44ab356b8760776fd816357f6ff
hash256("Hello15") = 0442e1c38b810f5d3c022fc2820b1d7999149460b83dc680abdebc9c7bd65cae
如果我们要找出前两位是0的哈希值,理论上需要计算256次,因为00出现的概率是162=256,实际计算44次:
hash256("Hello44") = 00e477f95283a544ffac7a8efc7decb887f5c073e0f3b43b3797b5dafabb49b5
如果我们要找出前3位是0的哈希值,理论上需要计算163=4096次,实际计算6591次:
hash256("Hello6591") = 0008a883dacb7094d6da1a6cefc6e7cbc13635d024ac15152c4eadba7af8d11c
如果我们要找出前4位是0的哈希值,理论上需要计算164=6万5千多次,实际计算6万7千多次:
hash256("Hello67859") = 00002e4af0b80d706ae749d22247d91d9b1c2e91547d888e5e7a91bcc0982b87
如果我们要找出前5位是0的哈希值,理论上需要计算165=104万次,实际计算158万次:
hash256("Hello1580969") = 00000ca640d95329f965bde016b866e75a3e29e1971cf55ffd1344cdb457930e
如果我们要找出前6位是0的哈希值,理论上需要计算166=1677万次,实际计算1558万次:
hash256("Hello15583041") = 0000009becc5cf8c9e6ba81b1968575a1d15a93112d3bd67f4546f6172ef7e76
对于给定难度的SHA-256:假设我们用难度1表示必须算出首位1个0,难度2表示必须算出首位两个0,难度N表示必须算出首位N个0,那么,每增加一个难度,计算量将增加16倍。
对于比特币挖矿来说,就是先给定一个难度值,然后不断变换nonce,计算Block Hash,直到找到一个比给定难度值低的Block Hash,就算成功挖矿。
我们用简化的方法来说明难度,例如,必须计算出连续17个0开头的哈希值,矿工先确定Prev Hash,Merkle Hash,Timestamp,bits,然后,不断变化nonce来计算哈希,直到找出连续17个0开头的哈希值。我们可以大致推算一下,17个十六进制的0相当于计算了1617次,大约需要计算2.9万亿亿次。
17个0 = 1617 = 295147905179352825856 = 2.9万亿亿次
实际的难度是根据bits由一个公式计算出来,比特币协议要求计算出的区块的哈希值比难度值要小,这个区块才算有效:
Difficulty = 402937298
= 0x18 0455d2
= 0x0455d2 * 28 * (0x18 - 3)
= 106299667504289830835845558415962632664710558339861315584
= 0x00000000000000000455d2000000000000000000000000000000000000000000
注意,难度值的数值越小,说明哈希值前面的0越多,计算的难度越大。
比特币网络的难度是不断变化的,它的难度保证大约每10分钟产生一个区块,而难度值在每2015个区块调整一次:如果区块平均生成时间小于10分钟,说明全网算力增加,难度也会增加,如果区块平均生成时间大于10分钟,说明全网算力减少,难度也会减少。因此,难度随着全网算力的增减会动态调整。
比特币设计时本来打算每2016个区块调整一次难度,也就是两周一次,但是由于第一版代码的一个bug,实际调整周期是2015个区块。
根据比特币每个区块的难度值和产出时间,就可以推算出整个比特币网络的全网算力。
比特币网络的全网算力一直在迅速增加。目前,全网算力已经超过了100EH/每秒,也就是大约每秒钟计算1万亿亿次哈希:
所以比特币的工作量证明被通俗地称之为挖矿。在同一时间,所有矿工都在努力计算下一个区块的哈希。而挖矿难度取决于全网总算力的百分比。举个例子,假设小明拥有全网总算力的百分之一,那么他挖到下一个区块的可能性就是1%,或者说,每挖出100个区块,大约有1个就是小明挖的。
由于目前全网算力超过了100EH/s,而单机CPU算力不过几M,GPU算力也不过1G,所以,单机挖矿的成功率几乎等于0。比特币挖矿已经从早期的CPU、GPU发展到专用的ASIC芯片构建的矿池挖矿。
当某个矿工成功找到特定哈希的新区块后,他会立刻向全网广播该区块。其他矿工在收到新区块后,会对新区块进行验证,如果有效,就把它添加到区块链的尾部。同时说明,在本轮工作量证明的竞争中,这个矿工胜出,而其他矿工都失败了。失败的矿工会抛弃自己当前正在计算还没有算完的区块,转而开始计算下一个区块,进行下一轮工作量证明的竞争。
为什么区块可以安全广播?因为Merkle Hash锁定了该区块的所有交易,而该区块的第一个coinbase交易输出地址是该矿工地址。每个矿工在挖矿时产生的区块数据都是不同的,所以无法窃取别人的工作量。
比特币总量被限制为约2100万个比特币,初始挖矿奖励为每个区块50个比特币,以后每4年减半。
共识算法
如果两个矿工在同一时间各自找到了有效区块,注意,这两个区块是不同的,因为coinbase交易不同,所以Merkle Hash不同,区块哈希也不同。但它们只要符合难度值,就都是有效的。这个时候,网络上的其他矿工应该接收哪个区块并添加到区块链的末尾呢?答案是,都有可能。
通常,矿工接收先收到的有效区块,由于P2P网络广播的顺序是不确定的,不同的矿工先收到的区块是有可能的不同的。这个时候,我们说区块发生了分叉:
在分叉的情况下,有的矿工在绿色的分叉上继续挖矿,有的矿工在蓝色的分叉上继续挖矿:
但是最终,总有一个分叉首先挖到后续区块,这个时候,由于比特币网络采用最长分叉的共识算法,绿色分叉胜出,蓝色分叉被废弃,整个网络上的所有矿工又会继续在最长的链上继续挖矿。
由于区块链虽然最终会保持数据一致,但是,一个交易可能被打包到一个后续被孤立的区块中。所以,要确认一个交易被永久记录到区块链中,需要对交易进行确认。如果后续的区块被追加到区块链上,实际上就会对原有的交易进行确认,因为链越长,修改的难度越大。一般来说,经过6个区块确认的交易几乎是不可能被修改的。
小结
比特币挖矿是一种带经济激励的工作量证明机制;
工作量证明保证了修改区块链需要极高的成本,从而使得区块链的不可篡改特性得到保护;
比特币的网络安全实际上就是依靠强大的算力保障的。
Comments
Make a comment
Sign in to
make a comment
Index
区块链教程
比特币
区块链原理
P2P交易原理
私钥
公钥和地址
签名
挖矿原理
可编程支付原理
多重签名
UTXO模型
Segwit地址
HD钱包
钱包层级
助记词
地址监控
以太坊
账户
区块结构
交易
智能合约
编写合约
部署合约
调用合约
编写Dapp
常用合约
ERC20
Wrapped Ether
廖雪峰的官方网站
©Copyright 2019-2021
Powered by iTranswarp
Feedback
License
比特币挖矿算法详解 - 知乎首发于清源的区块链实验室切换模式写文章登录/注册比特币挖矿算法详解清源区块链工程师比特币网络中,源源不断的收到交易,需要节点不断的打包这些交易,而网络中的所有节点都是对等的,如何判断谁可以打包这些交易,如何避免重复打包这些交易呢?这个时候就需要用到工作量证明(PoW,Proof-of-Work)的方式决定记账权。网络中的任何全节点,都可以试图创建区块,但区块只有在至少满足下列条件时创建的区块才会被其他节点认可和接受。 区块中包含的交易都是合法的; 区块哈希要小于等于一个目标值;要满足第一个条件很简单,节点只要将每笔交易都验证一遍,丢弃掉不合法的交易即可。但要满足第二个条件就需要挖矿。挖矿比特币挖矿就是找到一个随机数(Nonce)参与哈希运算Hash(Block Header),使得最后得到的哈希值符合难度要求,用公式表示就是Hash(Block Header)<= target 比特币采用的哈希算法是 SHA-256 ,也就是说最后会产生256位的输出,一共2^256种可能的取值。 最后得到的哈希值小于target的意思是把哈希后得到的bytes转换成数字后小于target转换成的数字。举个例子,直观的感受一下挖矿的难度;SHA-256计算123的值
a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3
下面这段字符是比特币第1000个区块的哈希(2009年1月产生);
00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09
可以看到前面有8个0,虽然哈希值的生成是随机的,但是生成前面有8个0的值对计算机穷举来说也并不算太难。
再看一下这段字符,是比特币第560000个区块的哈希(2019年1月产生);
0000000000000000002c7b276daf6efb2b6aa68e2ce3be67ef925b3264ae7122
可以看到前面有18个0,要生成满足这个条件的哈希对于普通电脑来说几乎是不可能完成的任务了。简单来看挖矿难度的高低就是生成区块头的哈希值有多少0。挖矿难度在比特币系统中出块时间被设置为一个常数10分钟,但是挖出区块的速度并不是固定的,而是随着挖矿难度的变化在10分钟上下浮动, 挖矿难度越大,出块时间就越长,为了得到相对平均的出块时间,需要动态调整挖矿难度。 比特币每产生2016个区块调整一次挖矿难度,一个块10分钟,2016个块大概是两周的时间,而调整挖矿难度的这些逻辑都在代码中,当大多数诚实节点采用这个策略的时候整个网络就会自动遵循这个策略。挖矿难度的计算公式如下:diffculty = difficulty_1_target / target此处的 difficulty_1_target 为一个常数,非常大的一个数字( 2^(256-32)−1 )。表示挖矿的初始难度,目标值越小,区块生成难度越大。 2^(256-32)−1 是比特币的初始难度,是前2016个块的难度。 这个难度被存储在比特币的区块头nBits字段中,当有恶意节点篡改这个策略时,挖矿产生的区块头的哈希值就会和诚实节点产生冲突,不会被接收,白白浪费了算力。 因为策略不同,也就是nBits不同,恶意节点产生的区块哈希无法被诚实节点验证。 调整出块时间比特币系统中区块的生产速度是根据之前产生区块速度调整的,之前出块速度大于10分钟,则认为需要降低难度,则需要提高第一个公式中target的值,而target则通过如下公式计算;target = current_target * ( actual time / excepted time )current_target是当前系统中的难度值,target是调整后的难度值,actual time是实际产生区块的时间,excepted time是期望出块时间(2016块*10分钟),actual time有上下限,actual time最多8周,最小二分之一周。挖矿算法比特币中nBits标识了挖矿的难度,也就是说这个区块头进行SHA-256哈希算法后得到的bytes转换成数字后要小于这个难度,而SHA-256计算后的结果有256位,如果直接存储需要32个字节比较占用空间,所以采用了一种压缩算法。压缩算法nBits有4个字节32位,将SHA-256计算得到的值经过如下算法压缩到32位;将数字转换为 256 进制。如果第一位数字大于 127(0x7f),则前面添加 0。压缩结果中的第一位存放该256进制数的位数。后面三个数存放该256进制数的前三位,如果不足三位,从后补零。举个例子,将十进制1000压缩;1. 1000转换256进制数,1000 = 3 * 256 + 232 = 3*256^(2-1) + 232*256^(1-1)
2. 3小于127,不需要补0,跳过
3. 从第一部看到1000转换成256位数有2位,压缩结果第一位应该存放2
4. 因为只有两位,所以最后一位补0,得到存放的值为 [2, 3, 232, 0]十进制,转换十六进制 [0x02, 0x03, 0xe8, 0x00] 合并存储到nbits为 0x0203e800难度计算在第一个公式中difficulty_1_target的值为 2^(256-32)-1,转换成256进制为;FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF第一位大于0x7f,前面补0,变为00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF其长度等于 28+1=29 (0x1d),且长度超过三位,无需补零,则压缩结果为:0x1d00FFFF,因为压缩存储容量只有才4个字节,前两字节已经被长度和添加的 00 所占用,只剩下2个字节来存储数字,这样后面的26个 FF 值被丢弃。T=0x00FFFF * 256^(0x1b-3) = 0x00000000FFFF0000000000000000000000000000000000000000000000000000比特币中的difficulty就是0x1d00FFFF,如果区块中的nBits为0x1d00FFFF则说明这个区块挖矿难度为最小挖矿难度1.实际上专业的矿池程序会保留被截断的FF:00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF我们算一下比特币101799号区块的挖矿难度,通过区块链浏览器可以看到101799号区块的nBits为0x1b0404cbD = 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF / 0x00000000000404CB000000000000000000000000000000000000000000000000 = 16307.669773817162 (pdiFF)pdiFF也被称为矿池难度。算力为了找到符合条件的值在挖矿的时候需要不断的调整区块头中Nonce的值,但是又会有一个问题,在比特币中Nonce的值是32位的,如果挖矿难度太大,就算穷尽Nonce的所有可能还是不能算出符合条件的值。铸币交易在一个区块产生的时候,会有一个铸币交易(coinbase),也就是矿工为自己铸币,产生新的比特币。铸币交易没有UTXO输入,只有输出指向自己的比特币地址,当挖矿成功,这个区块被网络接收的时候,新产生的币就转移到这个矿工地址了。看一下铸币交易包含的字段; transaction hash:“交易哈希”字段32个字节全部填充0(因为其没有UTXO输入);ouput index:“交易输出索引”字段全部填充0xFF(十进制的255); coinbase data:coinbase数据长度最小2字节,最大100字节。除了开始的几个字节外,矿工可以任意使用coinbase的其他部分,随意填充任何数据。以创世块为例,中本聪在coinbase中填入了这样的数据“The Times 03/Jan/ 2009 -Chancellor on brink of second bailout for banks“; - coinbase data size:coinbase数据大小; sequence number:现在未使用,设置为0xffffffff可以看到铸币交易的coinbase data字段是我们可以控制的,当Nonce不能满足挖矿难度的时候,我们可以通过调整coinbase data字段,从而影响区块头的默克尔树根的值,提供更多的可能来满足挖矿难度的要求。算力单位通过上面的流程,进行一次可能的挖矿尝试被称为H。 1 H/s = 每秒可执行一次哈希运算。 1 KH/s = 每秒1,000哈希(一千次)。 1 MH/s = 每秒1,000,000次哈希(百万次)。 1 GH/s = 每秒1,000,000,000次哈希(十亿次)。 1 TH/s = 每秒1,000,000,000,000次哈希(万亿次)。 1 PH/s = 每秒1,000,000,000,000,000次哈希。 1 EH/s = 每秒1,000,000,000,000,000,000次哈希。挖矿收益矿机挖矿的时候就会出现很长的时间找不到符合条件的哈希值,如果找不到哈希值不能打包区块就没有收益,显然对矿工十分不友好,但是如果挖到就像中彩票一样获得非常丰厚的回报。矿池为了避免单个矿工挖矿收益的不稳定性,就出现了矿池,矿池集合了大量的矿工,平均挖矿的收益,避免了挖矿收益的不稳定性。 矿池组织大量的矿工挖矿面临很重要的一个问题就是如何把高难度计算哈希的任务拆解成相对简单的任务,发送给单个矿工,回顾之前挖矿难度的计算,可以简单的认为前面0的多少表明了挖矿的难易。 0越多,挖矿难度越高,为了降低挖矿难度我们就要增加挖矿哈希0的数量,举个例子假设挖矿目标值 0x000abc,只要满足这个值就可以打包区块获得挖矿收益;
降低挖矿难度为 0x001abc,发送给矿工,矿工只要计算区块头满足这个相对低一点的难度就可以得到一个分片(shared),但是单个矿工挖到这个简单难度的块是无法发布到整个网络中的,但是矿池可以把这个分片记录下来,作为以后给这个矿工奖励的凭证。
0x001abc是0x000abc的子集,只要子集足够多总有一个会满足目标值。
当有一个矿工挖出一个满足目标值之后就可以获得挖矿收益,而挖矿就可以根据矿工分片多少来获得收益。
矿工收益 = 挖矿收益 / 挖到的分片数量但是现在还有一个问题没有解决,单个矿工挖到目标值以后如果私吞收益,私自广播区块怎么办?矿池有集中托管式的,也有分布式的。 集中托管式矿池,矿工可以把挖矿的机器托管给矿池,由矿池统一操作维护,只需要支付一些电费管理费即可,这样就避免了私自广播。 分布式矿池,矿工将机器自行管理,通过矿池协议从网络连接矿池即可,这样就会出现私自广播的可能。回顾一下铸币交易coinbase,可以看到有output字段,UTXO模型中币的来源都是上一个交易的output,所以可以把铸币交易的output字段设置为矿池的地址,然后随机生成一些coinbase data的填充后生成区块头的默克尔树,最后发由矿工去尝试目标值。通过这样的方式,即使矿工找到满足条件的哈希值,铸币交易的地址也是矿池的地址,私自广播区块没有任何收益,如果调整铸币交易的地址,这样又回到了独立挖矿的场景。全网算力如果要获知全网算力,可以通过出块时间,挖矿难度大致反推出全网算力。区块确认当一个区块产生之后,它不是立即可信的,网络上的节点总是相信最长的区块链,当一条交易记录被打包进一个区块之后,就有了一个确认,而这个区块所在的链后面被再加入一个区块,就是第二个确认,如此下去,一个交易有了6个确认,我们就认为这个交易已经确定了,会被永远记录在区块链中。 为什么是6个确认呢?因为每一个确认就是一个挖矿过程,需要大量的工作量证明,因此,这6个区块被同一个矿工创建的可能性微乎其微(可以说是不可能),因此矿工伪造交易也基本不可能。由于比特币的区块平均产生时间是10分钟,所以一个交易要1小时左右才能保证成功(最快),不过也不是所有的系统都这样认为,有些网站在接受比特币支付时,认为4个确认就可以给客户发货了,区块确认越多则越难被逆转。区块广播在区块链中,为了尽快收到其他节点的信息,节点间并不是直接传递区块信息的。 节点向附近节点发送一个Inv消息,Inv消息中包含已经被发送者(sender)接收并验证过的“交易记录的哈希”、以及“区块哈希”。接收者(receiver)收到Inv消息后,如果他还尚未从其他节点收到过相同的信息,他会发送一个getdata消息给发送者,要求得到交易记录及区块哈希包含的具体信息。此时,区块和交易记录的信息才会进行整体传递。 其中Inv消息结构如下;type MsgInv struct {
InvList []*InvVect
}
type InvVect struct {
Type InvType // Type of data
Hash chainhash.Hash // Hash of the data
}欢迎关注我的博客(qyuan.top),不定期分享一些区块链底层技术文章,博客排版要比知乎好一点(ㄟ( ▔, ▔ )ㄏ)。编辑于 2020-05-12 11:18挖矿区块链(Blockchain)比特币 (Bitcoin)赞同 8311 条评论分享喜欢收藏申请转载文章被以下专栏收录清源的区块链
8-1 比特币挖矿原理_java模拟实现挖矿第1讲1_哔哩哔哩_bilibili 首页番剧直播游戏中心会员购漫画赛事投稿GO语言+区块链 VIP就业班(700P完结)
6.7万
128
2020-06-22 19:30:48
6692114391226转载于:http://www.mobiletrain.org/
目录:前言基础+计算机基础+GO语言基础+比特币+分布式项目+以太坊项目+以太坊进阶编程+智能合约项目+人人都懂区块链。
技术成长:https://www.nfcoder.com --> 技术栈经验
如果视频对你有帮助的话,麻烦三连支持一下!知识校园学习区块链gogolanggo语言
逆风微笑的代码狗
发消息
WX订阅号:0x00实验室 |莫道桑榆晚,为霞尚满天
关注 35.9万
桌面AI伙伴,陪你High翻天!视频选集(301/667)自动连播《区块链之新》第5集:区块链的金钱游戏,一半贪婪,一半伟大三橙视频
6.1万
413
如何跟朋友解释区块链 两个通俗易懂小故事告诉你央视网
15.9万
50
Go语言与区块链在线就业班(第二部分)我叫阿鑫ッ
9380
3
Go与区块链supreme_AI
5816
5
【千锋】区块链从入门到精通(小白必看)zj9540
5.1万
28
【整整300集】达摩院花196小时讲完的Go语言教程(golang进阶实战)全程干货无废话AIT_快知名UP煮
6977
8
Go语言与区块链在线就业班完整(第一部分)我叫阿鑫ッ
2.3万
20
Go语言与区块链在线就业班喔咔咔耶耶
1.6万
13
最新 Go语言零基础微服务项目喔咔咔耶耶
1.9万
58
Golang学习手册之:带你21周搞定Go语言爱吃蓝猫的代码狗
48.5万
1.1万
区块链工程师年薪百万?真实的情况是什么样的?FiduciaBridge
1.2万
2
go语言基础与区块链实战教程混的不错的程序员
3114
5
【golang-web开发】gin框架手把手教学枫枫知道
7.0万
677
Go区块链实战精选海外教程postcode
2786
1
区块链开发从零到实战孔子曰莫装逼i
4299
0
2023年啦!带你重新了解Go语言,不要再盲目说golang开发岗没前途了!学好golang同样轻松拿捏大厂!Linux-技术大师
8703
66
区块链技术斜杠凉森
7128
5
【清华团队】区块链技术开发入门到精通视频教程无力取闹的小浣熊
7.5万
220
【白嫖党必备】三个小时带你用go语言仿百度网盘,再不用担心被限速了!| golang项目实战、golang微服务阿栗Go
1.0万
9
区块链入门和就业建议熊熊熊熊爷
1.1万
0
展开
小窗
客服
顶部
赛事库 课堂 2021
GitHub - jimilai/bitcoin-java: java比特币开发详解:本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是java工程师不可多得的比特币开发学习课程。
Skip to content
Toggle navigation
Sign in
Product
Actions
Automate any workflow
Packages
Host and manage packages
Security
Find and fix vulnerabilities
Codespaces
Instant dev environments
Copilot
Write better code with AI
Code review
Manage code changes
Issues
Plan and track work
Discussions
Collaborate outside of code
Explore
All features
Documentation
GitHub Skills
Blog
Solutions
For
Enterprise
Teams
Startups
Education
By Solution
CI/CD & Automation
DevOps
DevSecOps
Resources
Learning Pathways
White papers, Ebooks, Webinars
Customer Stories
Partners
Open Source
GitHub Sponsors
Fund open source developers
The ReadME Project
GitHub community articles
Repositories
Topics
Trending
Collections
Pricing
Search or jump to...
Search code, repositories, users, issues, pull requests...
Search
Clear
Search syntax tips
Provide feedback
We read every piece of feedback, and take your input very seriously.
Include my email address so I can be contacted
Cancel
Submit feedback
Saved searches
Use saved searches to filter your results more quickly
Name
Query
To see all available qualifiers, see our documentation.
Cancel
Create saved search
Sign in
Sign up
You signed in with another tab or window. Reload to refresh your session.
You signed out in another tab or window. Reload to refresh your session.
You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
jimilai
/
bitcoin-java
Public
Notifications
Fork
6
Star
18
java比特币开发详解:本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是java工程师不可多得的比特币开发学习课程。
xc.hubwiz.com/course/5bb35c90c02e6b6a59171df0?affid=1111github
18
stars
6
forks
Branches
Tags
Activity
Star
Notifications
Code
Issues
0
Pull requests
0
Actions
Projects
0
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security
Insights
jimilai/bitcoin-java
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
masterBranchesTagsGo to fileCodeFolders and filesNameNameLast commit messageLast commit dateLatest commit History4 CommitsApp.javaApp.java README.mdREADME.md build.gradlebuild.gradle View all filesRepository files navigationREADMEbitcoin-java
本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易、SPV节点等,是Java工程师不可多得的比特币开发学习课程。
http://xc.hubwiz.com/course/5bb35c90c02e6b6a59171df0
课程目录如下:
1.比特币概述
什么是比特币
区块链结构
去中心化机制
课程内容
2.Hi,比特币
比特币协议与实现
节点软件与客户端
身份:密钥与地址
节点钱包
挖矿:交易确认与激励
比特币转账交易
理解交易的结构
查看交易输入与输出
3.使用PRC应用开发接口
RPC API概述
使用curl测试RPC API
在java中访问RPC API
使用JSON RPC封装库
利用UTXO计算钱包余额
让网站支持比特币支付
4.地址的离线生成与管理
概述
创建私钥和公钥
创建P2PKH地址
身份验证逻辑
P2PKH脚本执行原理
创建P2SH地址
多重签名赎回脚本
5.使用分层确定性密钥
概述
生成主密钥
派生子密钥
使用扩展密钥
使用强化派生密钥
路径表示法
6.离线构造裸交易
解读sendtoaddress
裸交易的构造与广播
理解交易费
多重签名裸交易
7.使用SPV节点
SPV节点概述
使用钱包应用套件
钱包密钥与地址管理
钱包交易池
钱包余额算法
交易可信度模型
区块链库组件
区块链组件
P2P节点组件
P2P节点管理器
http://xc.hubwiz.com/course/5bb35c90c02e6b6a59171df0
About
java比特币开发详解:本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是java工程师不可多得的比特币开发学习课程。
xc.hubwiz.com/course/5bb35c90c02e6b6a59171df0?affid=1111github
Resources
Readme
Activity
Stars
18
stars
Watchers
3
watching
Forks
6
forks
Report repository
Releases
No releases published
Packages
0
No packages published
Languages
Java
100.0%
Footer
© 2024 GitHub, Inc.
Footer navigation
Terms
Privacy
Security
Status
Docs
Contact
Manage cookies
Do not share my personal information
You can’t perform that action at this time.
23.比特币挖矿原理.java模拟实现挖矿第2讲1_哔哩哔哩_bilibili 首页番剧直播游戏中心会员购漫画赛事投稿区块链视频教程:玩转比特币(从入门到进阶)
5.3万
58
2018-11-18 05:38:52
65837829382541章(0):初识区块链家族
2章(1-2):区块链基础入门
3章(3-7):比特币及区块链常见问题
4章(8-13):区块链密码学算法
5章(14-17):比特币地址生成算法及代码实现
6章(18-19):ECDSA交易签名及签名验证
7章(20-21):区块链共识算法
8章(22-24):比特币挖矿原理及代码实现
9章(25-31):比特币系统架构及BitcoinCore
10章(32-36):比特币交易脚本及交易数据解析
11章(37-39):比特币交易开发知识校园学习入门课程视频教程教程编程比特币挖矿区块链bitcoin
RealWilliamWang
发消息
不定时更新编程类的教学视频。粉丝群465838033,商业合作454030959
关注 19.0万
桌面AI伙伴,陪你High翻天!视频选集(48/84)自动连播《区块链之新》第4集:以太坊,“世界计算机”?还是危机引爆者?三橙视频
16.5万
699
比特币到底能不能赚钱?挖矿真能免费获得吗?还曾有人用上亿美元比特币买张披萨?三味新知
17.4万
99
如何跟朋友解释区块链 两个通俗易懂小故事告诉你央视网
15.9万
50
币圈入门必备技能区块拿铁
1.8万
2
【纪录片】比特币:我们所知的货币结局哔哩哔哩纪录片
57.7万
1751
区块链从入门到精通极客CTO
3791
3
小白入门币圈技术分析moyu001
2.7万
13
区块链从入门到精通-Go语言基础教程无力取闹的小浣熊
3819
0
卖比特币赚了,能提现到国内个人账户吗?匀枫财技大兜底
2.6万
18
【千锋】区块链从入门到精通(小白必看)zj9540
5.1万
28
币圈入门第一课爱囤硬币的B总
3.6万
16
【干货】玩转比特币前必看|币圈宝典|新手入门(上集)web3航海指南
699
0
这1000万赚得莫名其妙莫大韭菜
340.6万
743
区块链开发教程:5分钟搭建自己的区块链挨踢韭菜
7269
0
《币圈入门》第五期——概念及术语one_snowball
2966
0
数字币杠杆交易入门到精通详解国民晓哥日记
1.2万
20
韭菜买3.4万比特币一个月后变成多少钱,第一天我是沛奇
9.8万
85
股票技术分析入门到精通20讲:从零开始学炒股A股交易员
42.5万
946
【区块链】比特币技术入门教程锐势力
8402
5
持有10万枚比特币的大佬“李笑来”,现在怎么样了?韭菜知识圈-堂哥
39.7万
299
展开
小窗
客服
顶部
赛事库 课堂 2021
pom.xml:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
Blockpackage com.blockchain.model;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.blockchain.security.CryptoUtil;
/**
* 区块结构
* @author zhiwei liao
*
*/
public class Block {
/**
* 区块索引号
*/
private int index;
/**
* 当前区块的hash值,区块唯一标识
*/
private String hash;
/**
* 生成区块的时间戳
*/
private long timestamp;
/**
* 当前区块的交易集合
*/
private List
/**
* 工作量证明,计算正确hash值的次数
*/
private int nonce;
/**
* 前一个区块的hash值
*/
private String previousHash;
public Block() {
super();
}
public Block(int index, long timestamp, List
super();
this.index = index;
this.timestamp = timestamp;
this.transactions = transactions;
this.nonce = nonce;
this.previousHash = previousHash;
this.hash = hash;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public List
return transactions;
}
public void setTransactions(List
this.transactions = transactions;
}
public int getNonce() {
return nonce;
}
public void setNonce(int nonce) {
this.nonce = nonce;
}
public String getPreviousHash() {
return previousHash;
}
public void setPreviousHash(String previousHash) {
this.previousHash = previousHash;
}
public String getHash() {
return hash;
}
public void setHash(String hash) {
this.hash = hash;
}
/**
* 挖矿
* @param blockchain 整个区块链
* @param txs 需记账交易记录
* @param address 矿工钱包地址
* @return
*/
public static void mineBlock(List
//加入系统奖励的交易
Transaction sysTx = new Transaction(CryptoUtil.UUID(), "", address, 10);
txs.add(sysTx);
//获取当前区块链里的最后一个区块
Block latestBlock = blockchain.get(blockchain.size() - 1);
//随机数
int nonce = 1;
String hash = "";
while(true){
hash = CryptoUtil.SHA256(latestBlock.getHash() + JSON.toJSONString(txs) + nonce);
if (hash.startsWith("0000")) {
System.out.println("=====计算结果正确,计算次数为:" +nonce+ ",hash:" + hash);
break;
}
nonce++;
System.out.println("计算错误,hash:" + hash);
}
//解出难题,可以构造新区块并加入进区块链里
Block newBlock = new Block(latestBlock.getIndex() + 1, System.currentTimeMillis(), txs, nonce, latestBlock.getHash(), hash);
blockchain.add(newBlock);
System.out.println("挖矿后的区块链:" + JSON.toJSONString(blockchain));
}
}复制Transactionpackage com.blockchain.model;
/**
* 交易
* @author zhiwei liao
*/
public class Transaction {
/**
* 交易唯一标识
*/
private String id;
/**
* 交易发送方
*/
private String sender;
/**
* 交易接收方
*/
private String recipient;
/**
* 交易金额
*/
private int amount;
public Transaction() {
super();
}
public Transaction(String id, String sender, String recipient, int amount) {
super();
this.id = id;
this.sender = sender;
this.recipient = recipient;
this.amount = amount;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getRecipient() {
return recipient;
}
public void setRecipient(String recipient) {
this.recipient = recipient;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Transaction other = (Transaction) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}复制加密工具类package com.blockchain.security;
import java.security.MessageDigest;
import java.util.UUID;
/**
* 加密工具类
*
* @author zhiwei liao
*
*/
public class CryptoUtil {
private CryptoUtil() {
}
public static String SHA256(String str) {
MessageDigest messageDigest;
String encodeStr = "";
try {
messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(str.getBytes("UTF-8"));
encodeStr = byte2Hex(messageDigest.digest());
} catch (Exception e) {
System.out.println("getSHA256 is error" + e.getMessage());
}
return encodeStr;
}
public static String UUID() {
return UUID.randomUUID().toString().replaceAll("\\-", "");
}
private static String byte2Hex(byte[] bytes) {
StringBuilder builder = new StringBuilder();
String temp;
for (int i = 0; i < bytes.length; i++) {
temp = Integer.toHexString(bytes[i] & 0xFF);
if (temp.length() == 1) {
builder.append("0");
}
builder.append(temp);
}
return builder.toString();
}
}复制Main方法执行:package com.blockchain;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.blockchain.model.Block;
import com.blockchain.model.Transaction;
import com.blockchain.security.CryptoUtil;
/**
* 交易
* @author zhiwei liao
*/
public class Main {
public static void main(String[] args) {
//创建一个空的区块链
List
//生成创世区块
Block block = new Block(1, System.currentTimeMillis(), new ArrayList
//加入创世区块到区块链里
blockchain.add(block);
System.out.println(JSON.toJSONString(blockchain));
// 发送方钱包地址
String sender = "sender_wallet";
//接收方钱包地址
String recipient = "recipient_wallet";
//创建一个空的交易集合
List
//挖矿
Block.mineBlock(blockchain, txs, sender);
System.out.println(sender + "钱包的余额为:" + getWalletBalance(blockchain, sender));
//创建一个空的交易集合
List
//已发生但未记账的交易记录,发送者给接收者转账3个比特币
Transaction tx1 = new Transaction(CryptoUtil.UUID(), sender, recipient, 3);
//已发生但未记账的交易记录,发送者给接收者转账1个比特币
Transaction tx2 = new Transaction(CryptoUtil.UUID(), sender, recipient, 1);
txs1.add(tx1);
txs1.add(tx2);
//挖矿
Block.mineBlock(blockchain, txs1, sender);
System.out.println(sender + "钱包的余额为:" + getWalletBalance(blockchain, sender));
System.out.println(recipient + "钱包的余额为:" + getWalletBalance(blockchain, recipient));
}
/**
* 查询余额
* @param blockchain
* @param address
* @return
*/
public static int getWalletBalance(List
int balance = 0;
for (Block block : blockchain) {
List
for (Transaction transaction : transactions) {
if (address.equals(transaction.getRecipient())) {
balance += transaction.getAmount();
}
if (address.equals(transaction.getSender())) {
balance -= transaction.getAmount();
}
}
}
return balance;
}
}复制这样一个简单的比特币系统就做好啦本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。 原始发表:2021-09-14 ,如有侵权请联系 cloudcommunity@tencent.com 删除前往查看比特币xmlmavenblock工具类本文分享自 作者个人站点/博客 前往查看如有侵权,请联系 cloudcommunity@tencent.com 删除。本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!比特币xmlmavenblock工具类评论登录后参与评论0 条评论热度最新登录 后参与评论推荐阅读LV.关注文章0获赞0领券社区专栏文章阅读清单互动问答技术沙龙技术视频团队主页腾讯云TI平台活动自媒体分享计划邀请作者入驻自荐上首页技术竞赛资源技术周刊社区标签开发者手册开发者实验室关于社区规范免责声明联系我们友情链接腾讯云开发者扫码关注腾讯云开发者领取腾讯云代金券热门产品域名注册云服务器区块链服务消息队列网络加速云数据库域名解析云存储视频直播热门推荐人脸识别腾讯会议企业云CDN加速视频通话图像分析MySQL 数据库SSL 证书语音识别更多推荐数据安全负载均衡短信文字识别云点播商标注册小程序开发网站监控数据迁移Copyright © 2013 - 2024 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有 深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档Copyright © 2013 - 2024 Tencent Cloud.All Rights Reserved. 腾讯云 版权所有登录 后参与评论00
46_比特币挖矿原理_java模拟实现挖矿第1讲1_哔哩哔哩_bilibili 首页番剧直播游戏中心会员购漫画赛事投稿千锋区块链视频教程:玩转区块链
5216
4
2018-10-16 20:36:59
未经作者授权,禁止转载14614616学区块链开发须从学习比特币开始,本视频带领大家彻底掌握比特币的核心技术,从而为学习以太坊和超级账本打下根基。区块链交流群:675081326知识野生技能协会千锋教育千锋区块链教程玩转区块链
zj9540
发消息
为大家提供IT行业好的学习视频,多多关注,多多转发哦!
关注 9233
桌面AI伙伴,陪你High翻天!视频选集(46/63)自动连播【千锋】区块链从入门到精通(小白必看)zj9540
5.1万
28
千锋区块链视频教程③:玩转比特币zj9540
5160
3
区块链视频教程④:以太坊solidity智能合约实战-1zj9540
1.5万
24
千锋区块链视频教程②:Go编程语言篇zj9540
3894
0
【千锋区块链】最全的Go语言教程zj9540
1290
3
千锋Tornado视频教程:教你掌握Tornado开发流程zj9540
5567
9
【千锋】区块链免费体验视频zj9540
508
2
千锋html5教程:angular入门精讲课程zj9540
941
0
千锋大数据教程:数据可视化zj9540
1251
0
【千锋Linux】Shell脚本入门全套教程zj9540
2.4万
43
千锋Html5教程:vue框架从入门到实战zj9540
753
0
千锋html5基础入门教程:史上最容易听懂的基础教程(专为零基础学员打造)zj9540
3.7万
216
千锋Linux云计算网络管理实战教程zj9540
901
0
千锋最新ElasticSearch6实战教程zj9540
4565
6
千锋Html5第三阶段教程:知识点讲解zj9540
892
1
千锋UI视频教程:PS基础教程精讲zj9540
2330
0
2018千锋区块链视频教程-两天快速get比特币zj9540
828
2
千锋PHP异步通信框架Swoole解读zj9540
1198
0
2019千锋区块链视频教程-免费体验课zj9540
685
0
千锋python前端基础教程:学python前端,其实很简单zj9540
5202
0
展开
小窗
客服
顶部
赛事库 课堂 2021