美文网首页
区块链JAVA描述版

区块链JAVA描述版

作者: 钱佳 | 来源:发表于2018-01-21 00:46 被阅读0次

    不知不觉,又到了周末,已经很久没有写东西了,最近看了很多关于区块链的东西,但是简易的入门的很少,于是,我想着写一篇能让小白快速理解最基础的代码。

    区块链概述

    网上有很多关于这方面的文章和历史,这里有几个问题简单描述一下:
    比特币是一个分布式记账系统,既然是记账,那么数据记在哪儿呢?答案是,记在千千万万个网络的节点上。

    分布式记账,要明白几个问题:

    一致性的问题?

    多种原因可能造成不一致,比如

    1. 每台机器的算力是不一样的,计算有快有慢
    2. 当我和你都收到一笔交易A的时候,我要记这一笔账,你也要记,一切顺利的情况下,我们都记成功了,账本也都是一致的结果,那么如果由于网络问题,你没收到这一笔交易,怎么办?

    区块链系统是这样处理的,全网所有的机器都会有一个确认过程,这个确认的过程就是校验交易合法的过程,你遗失了这一笔交易A,最后你算出来的区块和别人不一样,你就白白付出了努力,结果不被认可!

    共同造假的问题?

    比特币可不可能有造假的问题?当然有,当全网参与记账的节点有51%参与造假,记账就是不对的,当前比特币就有这样的算力中心化的问题。

    账记在哪儿?过程怎样?

    用户提交一笔交易到网络,网络各个矿工节点(参与记账的)收到了这一笔交易,不会立即记账,而是把这笔交易标记到下一个区块,当准备好出新的区块的时候,矿工需要先算一道题算出一个值,这个值是表示你经过千辛万苦参与了这一次记账,然后把区块信息(包含交易信息,上一个区块的hash,proof算出的答案),提交到网络,所有节点的矿工发现来了一个新的区块,立即停下算题的脚步,看一下这个区块是不是工作在最长链,如果是,校验一下,如果成功,则确认。

    proof瞎写会怎样?

    接着上面的问题说,如果我没有算这个题,直接瞎写一个答案,提交出去,别的矿工看了,校验了一把,发现你是扯淡的,你算出来的这个区块就丢掉,永远不会被确认。

    代码实现:

    扯淡了那么久,还是开始写一段代码,更直观。

    Block定义
    package com.xingchuan.study.blockchain.domain;
    
    import java.util.Set;
    
    /**
     * @author xingchuan.qxc
     * @since 2018/1/20
     */
    public class Block {
    
        /**
         * 区块的序号
         */
        private Long index;
    
        /**
         * 区块产生的时间
         */
        private Long timestamp;
    
        /**
         * 区块对应哪些交易
         */
        private Set<Transaction> transactions;
    
        /**
         * 工作证明
         */
        private Long proof;
    
        /**
         * 上一个区块的hash
         */
        private String previousHash;
    
        public Long getIndex() {
            return index;
        }
    
        public void setIndex(Long index) {
            this.index = index;
        }
    
        public Long getTimestamp() {
            return timestamp;
        }
    
        public void setTimestamp(Long timestamp) {
            this.timestamp = timestamp;
        }
    
        public Set<Transaction> getTransactions() {
            return transactions;
        }
    
        public void setTransactions(Set<Transaction> transactions) {
            this.transactions = transactions;
        }
    
        public Long getProof() {
            return proof;
        }
    
        public void setProof(Long proof) {
            this.proof = proof;
        }
    
        public String getPreviousHash() {
            return previousHash;
        }
    
        public void setPreviousHash(String previousHash) {
            this.previousHash = previousHash;
        }
    
        @Override
        public String toString() {
            return "{\"Block\":{"
                + "                        \"index\":\"" + index + "\""
                + ",                         \"timestamp\":\"" + timestamp + "\""
                + ",                         \"transactions\":" + transactions
                + ",                         \"proof\":\"" + proof + "\""
                + ",                         \"previousHash\":\"" + previousHash + "\""
                + "}}";
        }
    }
    
    
    Transaction定义
    /**
     * @author xingchuan.qxc
     * @since 2018/1/20
     */
    public class Transaction {
    
        /**
         * 发送人
         */
        private String sender;
    
        /**
         * 接收人
         */
        private String recipient;
    
        /**
         * 金额
         */
        private long amount;
    
        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 long getAmount() {
            return amount;
        }
    
        public void setAmount(long amount) {
            this.amount = amount;
        }
    
        @Override
        public String toString() {
            return "{\"Transaction\":{"
                + "                        \"sender\":\"" + sender + "\""
                + ",                         \"recipient\":\"" + recipient + "\""
                + ",                         \"amount\":\"" + amount + "\""
                + "}}";
        }
    }
    
    

    Blockchain定义

    /**
     * @author xingchuan.qxc
     * @since 2018/1/20
     */
    public class Blockchain {
    
        /**
         * Block 链
         */
        private List<Block> blockchain = new LinkedList<>();
    
        /**
         * 待生成Block的交易
         */
        private Set<Transaction> transactions = new HashSet<>();
    
        /**
         * 初始化的时候,创建genesis block
         * @throws NoSuchAlgorithmException
         */
        public Blockchain() throws NoSuchAlgorithmException {
            //genesis block,真实场景下,应该是同步区块链的最长链最后一个区块
            newBlock(720L);
        }
    
        /**
         * 挖矿产生新的区块
         * @throws NoSuchAlgorithmException
         */
        public void mine() throws NoSuchAlgorithmException {
            Block lastBlock = blockchain.get(blockchain.size() - 1);
            Long lastProof = lastBlock.getProof();
            Long proof = proofOfWork(lastProof);
            newTransaction("0", "mineNode", 1L);
            newBlock(proof);
    
        }
    
        /**
         * 计算工作证明
         * @param lastProof
         * @return
         * @throws NoSuchAlgorithmException
         */
        public Long proofOfWork(Long lastProof) throws NoSuchAlgorithmException {
            Long proof = 0L;
    
            while (!validProof(lastProof, proof)) {
                proof++;
            }
            return proof;
        }
    
        /**
         * 算题,这里定义为,直到算出来的值以0000开头,才算正确答案
         * @param lastProof
         * @param proof
         * @return
         * @throws NoSuchAlgorithmException
         */
        private boolean validProof(Long lastProof, Long proof) throws NoSuchAlgorithmException {
            String guess = "" + lastProof + proof;
            String guessHash = hash(guess);
            return guessHash.startsWith("0000");
        }
    
        /**
         * 新建一个区块
         * @param proof
         * @return
         * @throws NoSuchAlgorithmException
         */
        public Block newBlock(Long proof) throws NoSuchAlgorithmException {
            Set<Transaction> transactions = new HashSet<>();
            transactions.addAll(this.transactions);
            int index = blockchain.size() - 1;
            Block lastBlock = null;
            if (index >= 0) {
                lastBlock = blockchain.get(index);
            }
            if (lastBlock == null) {
                lastBlock = new Block();
            }
            Block block = new Block();
            block.setIndex(Long.valueOf(blockchain.size() + 1));
            block.setTimestamp(System.currentTimeMillis());
            block.setTransactions(transactions);
            block.setProof(proof);
            block.setPreviousHash(hash(lastBlock.toString()));
            blockchain.add(block);
            this.transactions.clear();
            return block;
        }
    
        /**
         * 提交一笔新的交易
         * @param sender
         * @param recipient
         * @param amount
         * @return
         */
        public long newTransaction(String sender, String recipient, Long amount) {
            Transaction transaction = new Transaction();
            transaction.setSender(sender);
            transaction.setRecipient(recipient);
            transaction.setAmount(amount);
            this.transactions.add(transaction);
    
            int lastBlockIndex = blockchain.size() - 1;
            if (lastBlockIndex >= 0) {
                Block block = blockchain.get(lastBlockIndex);
                return block.getIndex() + 1;
            }
            return 0;
        }
    
        /**
         * SHA-512 算工作量证明
         * @param value
         * @return
         * @throws NoSuchAlgorithmException
         */
        private static String hash(String value) throws NoSuchAlgorithmException {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-512");
            messageDigest.update(value.getBytes());
            return bytesToHexString(messageDigest.digest());
        }
    
        private static String bytesToHexString(byte[] src) {
            StringBuilder stringBuilder = new StringBuilder();
            if (src == null || src.length <= 0) {
                return null;
            }
            for (int i = 0; i < src.length; i++) {
                int v = src[i] & 0xFF;
                String hv = Integer.toHexString(v);
                if (hv.length() < 2) {
                    stringBuilder.append(0);
                }
                stringBuilder.append(hv);
            }
            return stringBuilder.toString();
        }
    
        public List<Block> getBlockchain() {
            return blockchain;
        }
    
        public Set<Transaction> getTransactions() {
            return transactions;
        }
    }
    
    

    测试代码

    /**
     * @author xingchuan.qxc
     * @since 2018/1/20
     */
    public class TestBlockChain {
    
        public static void main(String[] args) throws Exception {
    
            //初始化
            Blockchain blockchain = new Blockchain();
    
            //提交一笔交易
            blockchain.newTransaction("xingchuan", "shine", 7201L);
    
            //挖矿记录这一笔交易
            blockchain.mine();
    
            List<Block> blockList = blockchain.getBlockchain();
            blockList.forEach(block->{
                System.out.println(block);
            });
    
            Set<Transaction> transactions = blockchain.getTransactions();
            for (Transaction transaction : transactions) {
                System.out.println(transaction);
            }
    
        }
    }
    
    

    运行结果:

    测试运行结果

    相关文章

      网友评论

          本文标题:区块链JAVA描述版

          本文链接:https://www.haomeiwen.com/subject/oxpxaxtx.html