用java写一个简单的区块链(上)

 

创建区块链

区块链就是一串或者是一系列区块的集合,类似于链表的概念,每个区块都指向于后面一个区块,然后顺序的连接在一起。那么每个区块中的内容是什么呢?在区块链中的每一个区块都存放了很多很有价值的信息,主要包括三个部分:自己的数字签名,上一个区块的数字签名,还有一切需要加密的数据(这些数据在比特币中就相当于是交易的信息,它是加密货币的本质)。每个数字签名不但证明了自己是特有的一个区块,而且指向了前一个区块的来源,让所有的区块在链条中可以串起来,而数据就是一些特定的信息,你可以按照业务逻辑来保存业务数据。

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/qukuai/qukuai01.png

这里的hash指的就是数字签名

所以每一个区块不仅包含前一个区块的hash值,同时包含自身的一个hash值,自身的hash值是通过之前的hash值和数据data通过hash计算出来的。如果前一个区块的数据一旦被篡改了,那么前一个区块的hash值也会同样发生变化(因为数据也被计算在内),这样也就导致了所有后续的区块中的hash值。所以计算和比对hash值会让我们检查到当前的区块链是否是有效的,也就避免了数据被恶意篡改的可能性,因为篡改数据就会改变hash值并破坏整个区块链。

一、封装区块对象

package com.pibigstar.blockchain;

import java.util.Date;
/**
 * 封装区块对象
 * @author pibigstar
 *
 */
public class Block {
	
	public String hash;
	//上一个区块的hash值
	public String previousHash; 
	//每个区块存放的信息,这里我们存放的是一串字符串
	private String data; 
	//时间戳
	private long timeStamp; 
	//挖矿者的工作量证明
	private int nonce;
	
	//构造  
	public Block(String data,String previousHash ) {
		this.data = data;
		this.previousHash = previousHash;
		this.timeStamp = new Date().getTime();
		//根据previousHash、data和timeStamp产生唯一hash
		this.hash = calculateHash(); 
	}
	
	//基于上一块的内容计算新的散列
	public String calculateHash() {
		String calculatedhash = StringUtil.applySha256( 
				previousHash +
				Long.toString(timeStamp) +
				Integer.toString(nonce) + 
				data 
				);
		return calculatedhash;
	}
	
	//挖矿
	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);
	}
	
}

二、封装工具类

package com.pibigstar.blockchain;
import java.security.MessageDigest;

import com.google.gson.GsonBuilder;
/**
 * 工具类
 * 创建数字签名、返回JSON格式数据、返回难度字符串目标
 * @author pibigstar
 *
 */
public class StringUtil {
	
	//将Sha256应用到一个字符串并返回结果 
	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格式数据
	public static String getJson(Object o) {
		return new GsonBuilder().setPrettyPrinting().create().toJson(o);
	}
	
	//返回难度字符串目标,与散列比较。难度5将返回“00000”  
	public static String getDificultyString(int difficulty) {
		return new String(new char[difficulty]).replace('\0', '0');
	}
	
	
}

三、主函数,开始创建区块链

package com.pibigstar.blockchain;
import java.util.ArrayList;
import com.google.gson.GsonBuilder;
/**
 * 创建区块链
 * @author pibigstar
 *
 */
public class BlockChain{
	//存放所有的区块集合
	public static ArrayList<Block> blockchain = new ArrayList<Block>();
	public static int difficulty = 5;//挖矿的难度,数字越大越难

	public static void main(String[] args) {	
		System.out.println("正在创建第一个区块链....... ");
		addBlock(new Block("我是第一个区块链", "0"));//创世块
		
		System.out.println("正在创建第二个区块链....... ");
		addBlock(new Block("我是第二个区块链",blockchain.get(blockchain.size()-1).hash));
		
		System.out.println("正在创建第三个区块链.......");
		addBlock(new Block("我是第三个区块链",blockchain.get(blockchain.size()-1).hash));	
		
		System.out.println("区块链是否有效的: " + isChainValid());
		
		String blockchainJson = StringUtil.getJson(blockchain);
		System.out.println(blockchainJson);
	}
	
	/**
	 * 检查区块链的完整性
	 * @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);
	}
}

运行结果

项目地址:https://github.com/pibigstar/blockchain

好的,下面是一个简易的区块链系统的Go语言实现示例: 首先,我们定义一个区块的结构体: ``` type Block struct { Index int Timestamp string Data string Hash string PrevHash string } ``` 其中,Index代表区块的索引,Timestamp代表区块产生的时间戳,Data是区块中存储的数据,Hash是该区块的哈希值,PrevHash是前一个区块的哈希值。 接下来,我们定义一个区块链的结构体: ``` type Blockchain struct { blocks []*Block } ``` 其中,blocks是一个Block类型的切片,用于存储整个区块链。接下来,我们实现一些区块链的基本操作: 1.创建创世区块: ``` func (bc *Blockchain) createGenesisBlock() { block := &Block{ Index: 0, Timestamp: time.Now().String(), Data: "Genesis Block", PrevHash: "", } block.Hash = calculateHash(block) bc.blocks = append(bc.blocks, block) } ``` 2.添加新的区块: ``` func (bc *Blockchain) addBlock(data string) { prevBlock := bc.blocks[len(bc.blocks)-1] newBlock := &Block{ Index: prevBlock.Index + 1, Timestamp: time.Now().String(), Data: data, PrevHash: prevBlock.Hash, } newBlock.Hash = calculateHash(newBlock) bc.blocks = append(bc.blocks, newBlock) } ``` 3.计算区块的哈希值: ``` func calculateHash(block *Block) string { record := strconv.Itoa(block.Index) + block.Timestamp + block.Data + block.PrevHash h := sha256.New() h.Write([]byte(record)) hash := h.Sum(nil) return hex.EncodeToString(hash) } ``` 最后,我们可以使用以下代码来测试我们的区块链系统: ``` func main() { bc := Blockchain{} bc.createGenesisBlock() bc.addBlock("Block 1") bc.addBlock("Block 2") for _, block := range bc.blocks { fmt.Printf("Index: %d\n", block.Index) fmt.Printf("Timestamp: %s\n", block.Timestamp) fmt.Printf("Data: %s\n", block.Data) fmt.Printf("Hash: %s\n", block.Hash) fmt.Printf("PrevHash: %s\n", block.PrevHash) fmt.Println() } } ``` 运行结果: ``` Index: 0 Timestamp: 2022-05-09 21:15:14.0970406 +0800 CST m=+0.004974101 Data: Genesis Block Hash: 5c8a5b5f29b7b0a9f4ab3d1c3f4c5b9e5a3d5f6d7cf1f51a7c9b4d5d0d2f44e4 PrevHash: Index: 1 Timestamp: 2022-05-09 21:15:14.0980389 +0800 CST m=+0.005972401 Data: Block 1 Hash: 4e59b5aae5b8d83f1c2f8ce7f6d8d9a6a2c5c34b4a37a9ea6a8178567e0e34d2 PrevHash: 5c8a5b5f29b7b0a9f4ab3d1c3f4c5b9e5a3d5f6d7cf1f51a7c9b4d5d0d2f44e4 Index: 2 Timestamp: 2022-05-09 21:15:14.0980389 +0800 CST m=+0.005972401 Data: Block 2 Hash: 73c4d5e8d166c7f4e1f1c5c50289597f7990a1cda3dd953f03d1d4400f8e71e2 PrevHash: 4e59b5aae5b8d83f1c2f8ce7f6d8d9a6a2c5c34b4a37a9ea6a8178567e0e34d2 ``` 这样,我们就实现了一个简易的区块链系统。当然,这只是一个基础的示例,实际的区块链系统要比这个复杂得多,包括更多的功能和安全性考虑。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值