Java语言编写第一个区块链程序

区块链技术 12/26 阅读 205 views次 人气 0
摘要:

区块链是目前最热门的话题,广大读者都听说过比特币,或许还有智能合约,相信大家都非常想了解这一切是如何工作的,本文章就是帮助你使用 Java 语言来实现一个简单的区块链。

区块链就是一串或者是一系列区块的集合,类似于链表的概念,每个区块都指向于后面一个区块,然后顺序的连接在一起。

在区块链中的每一个区块都存放了很多很有价值的信息,主要包括三个部分:自己的数字签名,上一个区块的数字签名,还有一切需要加密的数据(这些数据在比特币中就相当于是交易的信息,它是加密货币的本质)。每个数字签名不但证明了自己是特有的一个区块,而且指向了前一个区块的来源,让所有的区块在链条中可以串起来,而数据就是一些特定的信息,你可以按照业务逻辑来保存业务数据。


pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	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">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.what21.demo</groupId>
	<artifactId>blockchain</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>blockchain</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.google.code.gson</groupId>
			<artifactId>gson</artifactId>
			<version>2.8.5</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>


StringUtil.java

package com.what21.demo.blockchain;

import java.security.MessageDigest;

import com.google.gson.GsonBuilder;

public class StringUtil {

	/**
	 * 将Sha256应用到一个字符串并返回结果
	 * 
	 * @param input
	 * @return
	 */
	public static String applySha256(String input) {

		try {
			MessageDigest digest = MessageDigest.getInstance("SHA-256");
			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);
		}
	}

	/**
	 * 返回JSON格式数据
	 * 
	 * @param o
	 * @return
	 */
	public static String getJson(Object o) {
		return new GsonBuilder().setPrettyPrinting().create().toJson(o);
	}

	/**
	 * 返回难度字符串目标,与散列比较。难度5将返回“00000”
	 * 
	 * @param difficulty
	 * @return
	 */
	public static String getDificultyString(int difficulty) {
		return new String(new char[difficulty]).replace('\0', '0');
	}

}


Block.java

package com.what21.demo.blockchain;


import java.util.Date;

/**
 * 封装区块对象
 */
public class Block {
	
	public String hash;
	//上一个区块的hash值
	public String previousHash; 
	//每个区块存放的信息,这里我们存放的是一串字符串
	private String data; 
	//时间戳
	private long timeStamp; 
	//挖矿者的工作量证明
	private int nonce;
	
	/**
	 * 构造  
	 * 
	 * @param data
	 * @param previousHash
	 */
	public Block(String data,String previousHash ) {
		this.data = data;
		this.previousHash = previousHash;
		this.timeStamp = new Date().getTime();
		//根据previousHash、data和timeStamp产生唯一hash
		this.hash = calculateHash(); 
	}
	
	/**
	 * 基于上一块的内容计算新的散列
	 * 
	 * @return
	 */
	public String calculateHash() {
		String calculatedhash = StringUtil.applySha256( 
				previousHash +
				Long.toString(timeStamp) +
				Integer.toString(nonce) + 
				data 
				);
		return calculatedhash;
	}
	
	/**
	 * 挖矿
	 * 
	 * @param difficulty
	 */
	public void mineBlock(int difficulty) {
		//目标值,difficulty越大,下面计算量越大
		String target = StringUtil.getDificultyString(difficulty);
		//difficulty如果为5,那么target则为 00000
		while(!hash.substring( 0, difficulty).equals(target)) {
			nonce ++;
			hash = calculateHash();
		}
		System.out.println("创建区块:" + hash);
	}
	
}


BlockChain.java

package com.what21.demo.blockchain;

import java.util.ArrayList;

public class BlockChain {

	// 存放所有的区块集合
	public static ArrayList<Block> blockchain = new ArrayList<Block>();

	// 挖矿的难度,数字越大越难
	public static int difficulty = 5;

	/**
	 * 检查区块链的完整性
	 * 
	 * @return
	 */
	public static Boolean isChainValid() {
		Block currentBlock;
		Block previousBlock;
		String hashTarget = new String(new char[difficulty]).replace('\0', '0');

		// 循环区块链检查散列:
		for (int i = 1; i < blockchain.size(); i++) {
			currentBlock = blockchain.get(i);
			previousBlock = blockchain.get(i - 1);
			// 比较注册散列和计算散列:
			if (!currentBlock.hash.equals(currentBlock.calculateHash())) {
				System.out.println("Current Hashes not equal");
				return false;
			}
			// 比较以前的散列和注册的先前的散列
			if (!previousBlock.hash.equals(currentBlock.previousHash)) {
				System.out.println("Previous Hashes not equal");
				return false;
			}
			// 检查哈希是否被使用
			if (!currentBlock.hash.substring(0, difficulty).equals(hashTarget)) {
				System.out.println("这个区块还没有被开采。。。");
				return false;
			}

		}
		return true;
	}

	/**
	 * 增加一个新的区块
	 * 
	 * @param newBlock
	 */
	public static void addBlock(Block newBlock) {
		newBlock.mineBlock(difficulty);
		blockchain.add(newBlock);
	}
	
	public static ArrayList<Block> getBlockchain() {
		return blockchain;
	}

}


App.java

package com.what21.demo.blockchain;

public class App {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("正在创建第一个区块链....... ");
		BlockChain.addBlock(new Block("我是第一个区块链", "0"));

		System.out.println("正在创建第二个区块链....... ");
		BlockChain.addBlock(
				new Block("我是第二个区块链", BlockChain.getBlockchain().get(BlockChain.getBlockchain().size() - 1).hash));

		System.out.println("正在创建第三个区块链.......");
		BlockChain.addBlock(
				new Block("我是第三个区块链", BlockChain.getBlockchain().get(BlockChain.getBlockchain().size() - 1).hash));

		System.out.println("区块链是否有效的: " + BlockChain.isChainValid());

		String blockchainJson = StringUtil.getJson(BlockChain.getBlockchain());
		System.out.println(blockchainJson);
	}

}


运行输出

正在创建第一个区块链....... 
创建区块:00000186a73d88de92f7787a510fb23ce7e73a40c936435ab44036a5dc69331d
正在创建第二个区块链....... 
创建区块:0000000d16d891c9a09e84ab070d362ed49f8ab2bc818a0a5be539355ec9f223
正在创建第三个区块链.......
创建区块:00000c27ae0f6c993e50e1fa9f0852aa0a049ede2cff41d3194a119c78a4f8e7
区块链是否有效的: true
[
  {
    "hash": "00000186a73d88de92f7787a510fb23ce7e73a40c936435ab44036a5dc69331d",
    "previousHash": "0",
    "data": "我是第一个区块链",
    "timeStamp": 1545814134460,
    "nonce": 958686
  },
  {
    "hash": "0000000d16d891c9a09e84ab070d362ed49f8ab2bc818a0a5be539355ec9f223",
    "previousHash": "00000186a73d88de92f7787a510fb23ce7e73a40c936435ab44036a5dc69331d",
    "data": "我是第二个区块链",
    "timeStamp": 1545814136577,
    "nonce": 2466683
  },
  {
    "hash": "00000c27ae0f6c993e50e1fa9f0852aa0a049ede2cff41d3194a119c78a4f8e7",
    "previousHash": "0000000d16d891c9a09e84ab070d362ed49f8ab2bc818a0a5be539355ec9f223",
    "data": "我是第三个区块链",
    "timeStamp": 1545814142208,
    "nonce": 1962680
  }
]


评论

表情

分享到: