用Java来实现区块链原理并简单模拟开发一个小工具

前几天心血来潮,用Java模拟实现了一个区块链小工具,该工具是单机版的,没有实现联网功能,属于是单节点的工具,但是对于区块链的核心wk逻辑功能都实现了,如:wk、钱包、转账、记账等功能。界面实现用到了Java的swing包。

下面先看下运行的效果:

主界面:

转账:

 下面来看看代码:

首先是界面:

package com.yuanlrc.app;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;

import com.yuanlrc.model.Block;
import com.yuanlrc.model.Transaction;
import com.yuanlrc.thread.MinBlockThread;
import com.yuanlrc.util.CryptoUtil;

public class App extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JPanel contentPane;
	private JTextField recieverAddressTextField;
	private JTextArea showRstTextArea;
	
	private String address;//当前钱包地址
	
	private List<Block> blockChain;//区块链
	
	private MinBlockThread minBlockThread;
	
	private List<Transaction> txs = new ArrayList<>();
	
	public JProgressBar currentStatusProgressBar;
	private JTextField amountTextField;
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					App frame = new App();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public App() {
		try {
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedLookAndFeelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		address = UUID.randomUUID().toString();
		
		setTitle("【\u733F\u5E01\u6316\u77FF\u5DE5\u5177】钱包地址:" + address +"【当前余额:0】" );
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 717, 571);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		
		JPanel panel = new JPanel();
		panel.setBorder(new TitledBorder(null, "\u524D\u7F6E\u52A8\u4F5C", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		
		JPanel panel_1 = new JPanel();
		panel_1.setBorder(new TitledBorder(null, "\u8F6C\u8D26\u64CD\u4F5C", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		
		JPanel panel_2 = new JPanel();
		panel_2.setBorder(new TitledBorder(null, "\u6316\u77FF\u7ED3\u679C", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		
		JPanel panel_3 = new JPanel();
		panel_3.setBorder(new TitledBorder(null, "\u5F53\u524D\u72B6\u6001", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		GroupLayout gl_contentPane = new GroupLayout(contentPane);
		gl_contentPane.setHorizontalGroup(
			gl_contentPane.createParallelGroup(Alignment.LEADING)
				.addGroup(Alignment.TRAILING, gl_contentPane.createSequentialGroup()
					.addGap(18)
					.addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING, false)
						.addComponent(panel_2, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
						.addComponent(panel_3, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
						.addComponent(panel_1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
						.addComponent(panel, GroupLayout.DEFAULT_SIZE, 651, Short.MAX_VALUE))
					.addGap(22))
		);
		gl_contentPane.setVerticalGroup(
			gl_contentPane.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_contentPane.createSequentialGroup()
					.addContainerGap()
					.addComponent(panel, GroupLayout.PREFERRED_SIZE, 77, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, 73, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(panel_3, GroupLayout.DEFAULT_SIZE, 41, Short.MAX_VALUE)
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addComponent(panel_2, GroupLayout.PREFERRED_SIZE, 300, GroupLayout.PREFERRED_SIZE))
		);
		
		currentStatusProgressBar = new JProgressBar();
		currentStatusProgressBar.setForeground(Color.GREEN);
		currentStatusProgressBar.setBackground(UIManager.getColor("window"));
		GroupLayout gl_panel_3 = new GroupLayout(panel_3);
		gl_panel_3.setHorizontalGroup(
			gl_panel_3.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel_3.createSequentialGroup()
					.addContainerGap()
					.addComponent(currentStatusProgressBar, GroupLayout.DEFAULT_SIZE, 619, Short.MAX_VALUE)
					.addContainerGap())
		);
		gl_panel_3.setVerticalGroup(
			gl_panel_3.createParallelGroup(Alignment.LEADING)
				.addComponent(currentStatusProgressBar, GroupLayout.DEFAULT_SIZE, 24, Short.MAX_VALUE)
		);
		panel_3.setLayout(gl_panel_3);
		
		JScrollPane scrollPane = new JScrollPane();
		GroupLayout gl_panel_2 = new GroupLayout(panel_2);
		gl_panel_2.setHorizontalGroup(
			gl_panel_2.createParallelGroup(Alignment.LEADING)
				.addComponent(scrollPane, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 639, Short.MAX_VALUE)
		);
		gl_panel_2.setVerticalGroup(
			gl_panel_2.createParallelGroup(Alignment.LEADING)
				.addComponent(scrollPane, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE)
		);
		
		showRstTextArea = new JTextArea();
		showRstTextArea.setForeground(Color.GREEN);
		showRstTextArea.setFont(UIManager.getFont("TitledBorder.font"));
		showRstTextArea.setBackground(Color.BLACK);
		scrollPane.setViewportView(showRstTextArea);
		panel_2.setLayout(gl_panel_2);
		
		JLabel label = new JLabel("\u8F6C\u8D26\u5730\u5740");
		
		recieverAddressTextField = new JTextField();
		recieverAddressTextField.setColumns(10);
		
		JButton submitTransButton = new JButton("\u786E\u5B9A\u8F6C\u8D26");
		submitTransButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				//转账
				String recieverAddress = recieverAddressTextField.getText();
				if(recieverAddress == null || "".equals(recieverAddress)){
					JOptionPane.showMessageDialog(App.this, "请输入转账地址!");
					return;
				}
				String amount = amountTextField.getText();
				if(amount == null || "".equals(amount)){
					JOptionPane.showMessageDialog(App.this, "请输入转账金额!");
					return;
				}
				try {
					double a = Double.valueOf(amount);
					double walletBalance = getWalletBalance(blockChain, address);
					if(walletBalance < a){
						JOptionPane.showMessageDialog(App.this, "您的余额不足!");
						return;
					}
					int showConfirmDialog = JOptionPane.showConfirmDialog(App.this, "确定转账?");
					if(showConfirmDialog == JOptionPane.OK_OPTION){
						Transaction tx = new Transaction(CryptoUtil.UUID(), address, recieverAddress, a);
						txs.add(tx);
						String title = getTitle();
						title = title.substring(0,title.lastIndexOf("【"));
						walletBalance = getWalletBalance(blockChain, address);
						title += "【当前余额:" + walletBalance + "】";
						setTitle(title);
						JOptionPane.showMessageDialog(App.this, "转账成功!");
						showRstTextArea.setText(showRstTextArea.getText() + "\n成功转账:" +a+ "个猿币,对方账户【"+recieverAddress+"】,当前猿币余额:" + walletBalance);
					}
				} catch (Exception e) {
					JOptionPane.showMessageDialog(App.this, "请输入正确的数字类型!");
					return;
				}
				
			}
		});
		
		JLabel label_1 = new JLabel("\u8F6C\u8D26\u91D1\u989D");
		
		amountTextField = new JTextField();
		amountTextField.setColumns(10);
		GroupLayout gl_panel_1 = new GroupLayout(panel_1);
		gl_panel_1.setHorizontalGroup(
			gl_panel_1.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel_1.createSequentialGroup()
					.addContainerGap()
					.addComponent(label)
					.addGap(18)
					.addComponent(recieverAddressTextField, GroupLayout.DEFAULT_SIZE, 192, Short.MAX_VALUE)
					.addGap(18)
					.addComponent(label_1)
					.addGap(27)
					.addComponent(amountTextField, GroupLayout.PREFERRED_SIZE, 122, GroupLayout.PREFERRED_SIZE)
					.addGap(46)
					.addComponent(submitTransButton)
					.addGap(29))
		);
		gl_panel_1.setVerticalGroup(
			gl_panel_1.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel_1.createSequentialGroup()
					.addContainerGap()
					.addGroup(gl_panel_1.createParallelGroup(Alignment.BASELINE)
						.addComponent(recieverAddressTextField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addComponent(label)
						.addComponent(submitTransButton)
						.addComponent(amountTextField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addComponent(label_1))
					.addContainerGap(16, Short.MAX_VALUE))
		);
		panel_1.setLayout(gl_panel_1);
		
		JButton createInitBlockChainButton = new JButton("\u521B\u5EFA\u521D\u59CB\u533A\u5757\u94FE");
		createInitBlockChainButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				//初始化区块链
				if(blockChain != null){
					JOptionPane.showMessageDialog(App.this, "请勿重复初始化!");
					return;
				}
				blockChain = new ArrayList<Block>();
				showRstTextArea.setText("初始化完成!");
			}
		});
		createInitBlockChainButton.setFont(new Font("黑体", Font.PLAIN, 14));
		
		JButton createFirstBlockButton = new JButton("\u751F\u6210\u521B\u4E16\u533A\u5757");
		createFirstBlockButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				//生成创世区块
				if(blockChain == null){
					JOptionPane.showMessageDialog(App.this, "请先初始化创建区块链!");
					return;
				}
				if(blockChain.size() > 0){
					JOptionPane.showMessageDialog(App.this, "创世区块已生成,请勿重复创建!");
					return;
				}
				String hash = UUID.randomUUID().toString();
				Block block = new Block(1, System.currentTimeMillis(), txs, 0, hash, hash);
				showRstTextArea.setText(showRstTextArea.getText() + "\n创世区块已建立!");
				blockChain.add(block);
				showRstTextArea.setText(showRstTextArea.getText() + "\n创世区块已加入到区块链!");
			}
		});
		createFirstBlockButton.setFont(new Font("黑体", Font.PLAIN, 14));
		
		JButton startMineCoinButton = new JButton("\u5F00\u59CB\u6316\u733F\u5E01");
		startMineCoinButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				//开始挖矿
				if("停止挖矿".equals(startMineCoinButton.getText())){
					stopMinBlock();
					startMineCoinButton.setText("开始挖矿");
					return;
				}
				if(blockChain == null){
					JOptionPane.showMessageDialog(App.this, "请先初始化创建区块链!");
					return;
				}
				if(blockChain.size() == 0){
					JOptionPane.showMessageDialog(App.this, "请先生成创世区块!");
					return;
				}
				
				startMineBlock();
				startMineCoinButton.setText("停止挖矿");
			}
		});
		startMineCoinButton.setFont(new Font("黑体", Font.PLAIN, 14));
		GroupLayout gl_panel = new GroupLayout(panel);
		gl_panel.setHorizontalGroup(
			gl_panel.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel.createSequentialGroup()
					.addGap(45)
					.addComponent(createInitBlockChainButton)
					.addPreferredGap(ComponentPlacement.RELATED, 91, Short.MAX_VALUE)
					.addComponent(createFirstBlockButton)
					.addGap(83)
					.addComponent(startMineCoinButton)
					.addGap(69))
		);
		gl_panel.setVerticalGroup(
			gl_panel.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel.createSequentialGroup()
					.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
						.addComponent(startMineCoinButton, GroupLayout.PREFERRED_SIZE, 40, GroupLayout.PREFERRED_SIZE)
						.addComponent(createInitBlockChainButton, GroupLayout.PREFERRED_SIZE, 39, GroupLayout.PREFERRED_SIZE)
						.addComponent(createFirstBlockButton, GroupLayout.PREFERRED_SIZE, 41, GroupLayout.PREFERRED_SIZE))
					.addContainerGap(3, Short.MAX_VALUE))
		);
		panel.setLayout(gl_panel);
		contentPane.setLayout(gl_contentPane);
	}
	
	protected void stopMinBlock() {
		// TODO Auto-generated method stub
		minBlockThread.interrupt();
		currentStatusProgressBar.setValue(100);
	}

	/**
	 * 挖矿
	 * @param blockchain 整个区块链
	 * @param txs 需记账交易记录,包含
	 * @return
	 */
	private void startMineBlock() {
		minBlockThread = new MinBlockThread(showRstTextArea, blockChain, txs, this, address);
		minBlockThread.start();
		currentStatusProgressBar.setValue(0);
    }
	
	/**
	 * 查询余额
	 * @param blockchain
	 * @param address
	 * @return
	 */
	public double getWalletBalance(List<Block> blockchain, String address) {
		double balance = 0;
		for (Block block : blockchain) {
	        List<Transaction> transactions = block.getTransactions();
	        for (Transaction transaction : transactions) {
	            if (address.equals(transaction.getRecipient())) {
	            	balance += transaction.getAmount();
                }
	            if (address.equals(transaction.getSender())) {
	            	balance -= transaction.getAmount();
                }
            }
	        break;
        }
		return balance;
	}
}

 实体类:

package com.yuanlrc.model;

import java.util.List;

/**
 * 区块
 * @author llq
 *
 */
public class Block {

	/**
	 * 区块索引号
	 */
	private int index;
	/**
	 * 当前区块的hash值,区块唯一标识
	 */
	private String hash;
	/**
	 * 生成区块的时间戳
	 */
	private long timestamp;
	/**
	 * 当前区块的交易集合
	 */
	private List<Transaction> transactions;
	/**
	 * 工作量证明,计算正确hash值的次数
	 */
	private int nonce;
	/**
	 * 前一个区块的hash值
	 */
	private String previousHash;
	
	public Block(int index, long timestamp, List<Transaction> transactions, int nonce, String previousHash, String hash) {
		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 String getHash() {
		return hash;
	}
	public void setHash(String hash) {
		this.hash = hash;
	}
	public long getTimestamp() {
		return timestamp;
	}
	public void setTimestamp(long timestamp) {
		this.timestamp = timestamp;
	}
	public List<Transaction> getTransactions() {
		return transactions;
	}
	public void setTransactions(List<Transaction> transactions) {
		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;
	}
	
	
}
package com.yuanlrc.model;
/**
 * 交易集合
 * @author llq
 *
 */
public class Transaction {
	/**
	 * 交易唯一标识
	 */
	private String id;
	/**
	 * 交易发送方
	 */
	private String sender;
	/**
	 * 交易接收方
	 */
	private String recipient;
	/**
	 * 交易金额
	 */
	private double amount;
	
	
	public Transaction(String id, String sender, String recipient, double 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 double getAmount() {
		return amount;
	}
	public void setAmount(double 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.yuanlrc.util;

import java.security.MessageDigest;
import java.util.UUID;


/**
 * 加密类
 * 
 * @author aaron.rao
 *
 */
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();
	}

}

 解谜类:

package com.yuanlrc.util;

import java.security.Key;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;

public class DESUtil {
	
	/**
     * 偏移变量,固定占8位字节
     */
    private final static String IV_PARAMETER = "12345678";
    /**
     * 密钥算法
     */
    private static final String ALGORITHM = "DES";
    /**
     * 加密/解密算法-工作模式-填充模式
     */
    private static final String CIPHER_ALGORITHM = "DES/CBC/PKCS5Padding";
    /**
     * 默认编码
     */
    private static final String CHARSET = "UTF-8";
	
	/**
     * 计算加密key
     * @param password
     * @return
     * @throws Exception
     */
    private static Key generateKey(String password) throws Exception {
        DESKeySpec dks = new DESKeySpec(password.getBytes(CHARSET));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        return keyFactory.generateSecret(dks);
    }

    /**
     * 计算加密后的值
     * @param key
     * @param data
     * @return
     */
    public static String encrypt(String key, String data) {
        if (key== null || key.length() < 8) {
            throw new RuntimeException("加密失败,key不能小于8位");
        }
        if (data == null)
            return null;
        try {
            Key secretKey = generateKey(key);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
            byte[] bytes = cipher.doFinal(data.getBytes(CHARSET));
 
            //JDK1.8及以上可直接使用Base64,JDK1.7及以下可以使用BASE64Encoder
            //Android平台可以使用android.util.Base64
            return new String(Base64.getEncoder().encode(bytes));
 
        } catch (Exception e) {
            e.printStackTrace();
            return data;
        }
    }

    /**
     * DES解密字符串
     *
     * @param key 解密密码,长度不能够小于8位
     * @param data 待解密字符串
     * @return 解密后内容
     */
    public static String decrypt(String key, String data) {
        if (key== null || key.length() < 8) {
            throw new RuntimeException("解密失败,key不能小于8位");
        }
        if (data == null)
            return null;
        try {
            Key secretKey = generateKey(key);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
            cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
            return new String(cipher.doFinal(Base64.getDecoder().decode(data.getBytes(CHARSET))), CHARSET);
        } catch (Exception e) {
            e.printStackTrace();
            return data;
        }
    }

    
    public static void main(String[] args){
    	System.out.println(encrypt("muyi_ylrc", System.currentTimeMillis()+""));
    	System.out.println(decrypt("muyi_ylrc",encrypt("muyi_ylrc", System.currentTimeMillis()+"")));
    	System.out.println(encrypt("muyi_ylrc", "159083378454884859#17347843162"));
    	System.out.println(decrypt("muyi_ylrc","snSZdXC3NRZgoPaigiNyvm0A+Piwa09LDwqhvFZwalU="));
    }
}

点击查看 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个Java模拟一个简单区块链的示例代码,其中包含了添加区块、验证区块、输出整个链的功能。 ```java import java.security.MessageDigest; import java.util.ArrayList; import java.util.Date; public class BlockChain { private ArrayList<Block> blockChain; private int difficulty; public BlockChain(int difficulty) { this.blockChain = new ArrayList<>(); this.difficulty = difficulty; blockChain.add(createGenesisBlock()); } public Block createGenesisBlock() { return new Block(0, new Date(), "Genesis Block", "0"); } public Block getLatestBlock() { return blockChain.get(blockChain.size() - 1); } public void addBlock(Block newBlock) { newBlock.setPreviousHash(getLatestBlock().getHash()); newBlock.mineBlock(difficulty); blockChain.add(newBlock); } public boolean isValidChain() { for (int i = 1; i < blockChain.size(); i++) { Block currentBlock = blockChain.get(i); Block previousBlock = blockChain.get(i - 1); if (!currentBlock.getHash().equals(currentBlock.calculateHash())) { return false; } if (!previousBlock.getHash().equals(currentBlock.getPreviousHash())) { return false; } } return true; } public ArrayList<Block> getBlockChain() { return blockChain; } public static void main(String[] args) { BlockChain blockChain = new BlockChain(3); blockChain.addBlock(new Block(1, new Date(), "Block 1 Data")); blockChain.addBlock(new Block(2, new Date(), "Block 2 Data")); blockChain.addBlock(new Block(3, new Date(), "Block 3 Data")); System.out.println("Block Chain is valid: " + blockChain.isValidChain()); System.out.println("Block Chain: " + blockChain.getBlockChain()); } } class Block { private int index; private Date timestamp; private String data; private String previousHash; private String hash; private int nonce; public Block(int index, Date timestamp, String data) { this.index = index; this.timestamp = timestamp; this.data = data; } public String calculateHash() { String dataToHash = previousHash + index + timestamp + data + nonce; try { MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hash = digest.digest(dataToHash.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); } } public void mineBlock(int difficulty) { String target = new String(new char[difficulty]).replace('\0', '0'); while (!hash.substring(0, difficulty).equals(target)) { nonce++; hash = calculateHash(); } System.out.println("Block mined: " + hash); } public int getIndex() { return index; } public Date getTimestamp() { return timestamp; } public String getData() { return data; } public String getPreviousHash() { return previousHash; } public void setPreviousHash(String previousHash) { this.previousHash = previousHash; } public String getHash() { return hash; } } ``` 在上面的代码中,我们定义了一个 `Block` 类表示区块,该类包含了区块的索引、时间戳、数据、前一个区块的哈希值、当前区块的哈希值和随机数 `nonce`。`BlockChain` 类表示整个区块链,该类包含了区块链、难度系数(即哈希值的前缀 0 的个数)、创建创世块、获取最后一个区块、添加区块、验证区块链、输出整个链等方法。在 `main` 方法中,我们创建了一个区块链并添加了三个区块,然后输出了整个链和验证结果。 运行上面的代码,你会得到一个简单区块链并输出整个链,结果如下: ``` Block mined: 00000311c0c7b5e3e3f3e1ee1a0f4af04ecb92d6d6c08e9cd1fe8c9e49c5c1d Block mined: 00000e8f7a6e2d8d32bda3a1971a4f6620b562c8158f2f5c5c3c2a8f7f5fc0f9 Block mined: 00000d63c7c78c934b51c9d7d9f0d53c2c9b5c9f3d77a6c0dab7b2b7d7e71f4f Block Chain is valid: true Block Chain: [Block 0 [Genesis Block], Block 1 [Block 1 Data], Block 2 [Block 2 Data], Block 3 [Block 3 Data]] ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值