区块链的hello world实现(三

2018-04-13  本文已影响66人  abaeccdce206

由于在笔记二中提到区块链数据有2大部分组成
1:交易数据
2:区块信息(hash值 工作量等)

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONObject;

public class BlockChain {
// 存储区块链
private List<Map<String, Object>> chain;
// 该实例变量用于当前的交易信息列表
private List<Map<String, Object>> currentTransactions;
private static BlockChain blockChain = null;

private BlockChain() {
        // 初始化区块链以及当前的交易信息列表
        chain = new ArrayList<Map<String, Object>>();
        currentTransactions = new ArrayList<Map<String, Object>>();

        // 创建创世区块
        newBlock(100, "0");
        }
//因为新的区块都是依赖上一个区块hash值产生,所以创世区块稍微特殊,在初始化的时候生成,用于理解比特币的创世区块

// 创建单例对象,保持区块一致性
public static BlockChain getInstance() {
        if (blockChain == null) {
synchronized (BlockChain.class) {
        if (blockChain == null) {
        blockChain = new BlockChain();
        }
        }
        }
        return blockChain;
        }

public List<Map<String, Object>> getChain() {
        return chain;
        }

public void setChain(List<Map<String, Object>> chain) {
        this.chain = chain;
        }

public List<Map<String, Object>> getCurrentTransactions() {
        return currentTransactions;
        }

public void setCurrentTransactions(List<Map<String, Object>> currentTransactions) {
        this.currentTransactions = currentTransactions;
        }

/**
 * @return 得到区块链中的最后一个区块
* 用于存放最近的交易记录,也是为下次生成新的区块做准备
 */
public Map<String, Object> lastBlock() {
        return getChain().get(getChain().size() - 1);
        }

/**
 * 在区块链上新建一个区块
 *
 * @param proof



 * @param previous_hash
 *            上一个区块的hash值
 * @return 返回新建的区块
 */
public Map<String, Object> newBlock(long proof, String previous_hash) {

        Map<String, Object> block = new HashMap<String, Object>();
        block.put("index", getChain().size() + 1);
        block.put("timestamp", System.currentTimeMillis());
        block.put("transactions", getCurrentTransactions());
        block.put("proof", proof);
        // 如果没有传递上一个区块的hash就计算出区块链中最后一个区块的hash
        block.put("previous_hash", previous_hash != null ? previous_hash : hash(getChain().get(getChain().size() - 1)));

        // 重置当前的交易信息列表
        setCurrentTransactions(new ArrayList<Map<String, Object>>());

        getChain().add(block);

        return block;
        }

/**
 * 生成新交易信息,信息将加入到下一个待挖的区块中
 *
 * @param sender
 *            发送方的地址
 * @param recipient
 *            接收方的地址
 * @param amount
 *            交易数量
 * @return 返回该交易事务的块的索引
 */
public int newTransactions(String sender, String recipient, long amount) {

        Map<String, Object> transaction = new HashMap<String, Object>();
        transaction.put("sender", sender);
        transaction.put("recipient", recipient);
        transaction.put("amount", amount);

        getCurrentTransactions().add(transaction);

        return (Integer) lastBlock().get("index") + 1;
        }

/**
 * 生成区块的 SHA-256格式的 hash值
 *
 * @param block
 *            区块
 * @return 返回该区块的hash
 */
public static Object hash(Map<String, Object> block) {
        return new Encrypt().getSHA256(new JSONObject(block).toString());
        }

        /**
         * 简单的工作量证明:
         *   - 查找一个 p' 使得 hash(pp') 以4个0开头
         *   - p 是上一个块的证明, p' 是当前的证明
         *
         * @param last_proof
         *               上一个块的证明
         * @return
         */
        public long proofOfWork(long last_proof) {
                long proof = 0;
                while (!validProof(last_proof, proof)) {
                        proof += 1;
                }
                return proof;
        }

        /**
         * 验证证明: 是否hash(last_proof, proof)以4个0开头?
         *
         * @param last_proof
         *            上一个块的证明
         * @param proof
         *            当前的证明
         * @return 以4个0开头返回true,否则返回false
        *目前比特币是18个0开头的hash值,计算难度相当大
         */
        public boolean validProof(long last_proof, long proof) {
                String guess = last_proof + "" + proof;
                String guess_hash = new Encrypt().getSHA256(guess);
                return guess_hash.startsWith("0000");
        }

 }



上一篇下一篇

猜你喜欢

热点阅读