首先弄清楚需要哪些信息
自身的hash值,上一个区块的hash值,保存的数据信息,时间戳,随机数。
创建一个Block类
package blockChain;
import java.util.Date;
/**
* @author WuYongheng
* @date 2022/10/22
* @description
*/
public class Block {
public String hash;
public String previousHash;
private String data;
private long timeStamp;
private int nonce;
/**
* 区块构造函数
*
* @param previousHash
* @param data
*/
public Block(String data, String previousHash) {
this.previousHash = previousHash;
this.data = data;
this.timeStamp = new Date().getTime();
this.hash = calculateHash();
}
/**
* 计算区块的hash值,使用SHA256加密算法
* nonce每加一次,都会调用一次applySha256()方法
*
* @return calculateHash
*/
private String calculateHash() {
String calculateHash = StringUtil.applySha256(
previousHash
+ Long.toString(timeStamp)
+ data
+ Integer.toString(nonce)
);
return calculateHash;
}
/**
* 通过随机数nonce的递增,不断地尝试,得到符合要求的哈希值,使用SHA256加密
* 人为制造哈希碰撞的可能性很低,可以认为随机数是唯一的
*
* @param difficulty 困难度,表示哈希值的开头有多少个零
*/
public void mineBlock(int difficulty) {
String target = StringUtil.getDifficultyString(difficulty);
while (!hash.substring(0, difficulty).equals(target)) {
nonce++;
hash = calculateHash();
}
System.out.println("Block Mined!!! : " + hash);
}
}
创建一个工具类
需要手动添加一下gson的jar包
package blockChain;
import com.google.gson.GsonBuilder;
import java.security.MessageDigest;
/**
* @author WuYongheng
* @date 2022/10/22
* @description 工具类,负责加密,返回‘困难度’个零,解析json数据
*/
public class StringUtil {
/**
* for循环的解释:0xff & hash[i]
*
* @param input 未加密的字符串
* @return 加密之后的字符串
*/
public static String applySha256(String input) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
// 传入需要计算的字符串,把输入变成ascii值
byte[] hash = digest.digest(input.getBytes("UTF-8"));
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < hash.length; i++) {
String hex = Integer.toHexString(0xff & hash[i]);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 困难度是多少,就返回多少个零
* 比如 difficulty=6 返回 000000
* @param difficulty 困难度
* @return 一个字符串
*/
public static String getDifficultyString(int difficulty) {
return new String(new char[difficulty]).replace('\0', '0');
}
/**
* 将数据以json的格式显示
* @param o
* @return
*/
public static String getJson(Object o) {
return new GsonBuilder().setPrettyPrinting().create().toJson(o);
}
}
单独解释一下for循环
for (int i = 0; i < hash.length; i++) {
String hex = Integer.toHexString(0xff & hash[i]);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
理解:0xff & hash[i] 与 操作 hexString.append('0') 补零操作
有了这两步,就能确保得到一共64位的哈希值,每一位上的数可以转换成4位2进制数,比如a转换成1010,64*4一共256位0和1组成的哈希值。
创建一个测试类
package blockChain;
import java.util.ArrayList;
/**
* @author WuYongheng
* @date 2022/10/22
* @description 测试类
*/
public class TestBlockChain {
public static ArrayList<Block> blockchain = new ArrayList<Block>();
// 设置挖矿困难度为5,会体现在哈希值,以5个0开头,困难度越大,计算花的时间越多
public static int difficulty = 5;
/**
* 手动创建3个区块,将区块的内容以json的格式展示
* @param args
*/
public static void main(String[] args) {
System.out.println("Trying to Mine block 1... ");
// 创世块,前一个区块的哈希值为 0
addBlock(new Block("Hi im the first block", "0"));
System.out.println("Trying to Mine block 2... ");
addBlock(new Block("Yo im the second block", blockchain.get(blockchain.size() - 1).hash));
System.out.println("Trying to Mine block 3... ");
addBlock(new Block("Hey im the third block", blockchain.get(blockchain.size() - 1).hash));
String blockchainJson = StringUtil.getJson(blockchain);
System.out.println("\nThe block chain: ");
System.out.println(blockchainJson);
}
/**
* 创建新的区块
* @param newBlock
*/
private static void addBlock(Block newBlock) {
newBlock.mineBlock(difficulty);
blockchain.add(newBlock);
}
}
结果
"C:\Program Files\Java\jdk1.8.0_221\bin\java.exe" "-javaagent:D:\devenv\IntelliJ IDEA 2021.1.1\lib\idea_rt.jar=51144:D:\devenv\IntelliJ IDEA 2021.1.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_221\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\rt.jar;D:\code\before\csdncode\out\production\CSDNcode;C:\Users\Administrator\Desktop\学习笔记\老刘\jar包\gson-2.8.2.jar" blockChain.TestBlockChain
Trying to Mine block 1...
Block Mined!!! : 0000071d5ed7e99267ffbe73df5b01affe62928347bbe4032187f20fac1c8bb0
Trying to Mine block 2...
Block Mined!!! : 00000015080301d4e8a24786cc9ed85949fc96607d28373e04dfd5dd003a0233
Trying to Mine block 3...
Block Mined!!! : 0000096564160a2b6758839900780138760fb210044cb8685715646e4b511534
The block chain:
[
{
"hash": "0000071d5ed7e99267ffbe73df5b01affe62928347bbe4032187f20fac1c8bb0",
"previousHash": "0",
"data": "Hi im the first block",
"timeStamp": 1666431244665,
"nonce": 1214985
},
{
"hash": "00000015080301d4e8a24786cc9ed85949fc96607d28373e04dfd5dd003a0233",
"previousHash": "0000071d5ed7e99267ffbe73df5b01affe62928347bbe4032187f20fac1c8bb0",
"data": "Yo im the second block",
"timeStamp": 1666431246529,
"nonce": 656899
},
{
"hash": "0000096564160a2b6758839900780138760fb210044cb8685715646e4b511534",
"previousHash": "00000015080301d4e8a24786cc9ed85949fc96607d28373e04dfd5dd003a0233",
"data": "Hey im the third block",
"timeStamp": 1666431247645,
"nonce": 157564
}
]
Process finished with exit code 0
使用在线加密工具验证
以第一个区块为例
源码地址
https://gitee.com/ipkiss/csdncode文章来源:https://www.toymoban.com/news/detail-542166.html
参考
sunny_ice文章来源地址https://www.toymoban.com/news/detail-542166.html
到了这里,关于Java实现区块链 --- 代码篇的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!