天天看點

簡易區塊鍊源碼研究

區塊鍊源碼研究

目前看了一哈一個簡易區塊鍊的源碼,下面貼貼自己的研究結果:

-------------------------------------------------------------------------------------------

-----------------------------------Block.java---------------------------------------------

package com.fpfpp.server.blockchain;

public class Block {

    //索引值

private int    index;

    //上一條記錄的hash值

    private String previousHash;

    //插入block時的時間戳

    private long   timestamp;

    //插入的資料

    private String data;

    //計算得出的目前的hash值

    private String hash;

    public Block() {

    }

    public Block(int index, String previousHash, long timestamp, String data, String hash) {

        this.index = index;

        this.previousHash = previousHash;

        this.timestamp = timestamp;

        this.data = data;

        this.hash = hash;

    public int getIndex() {

        return index;

    public void setIndex(int index) {

    public String getPreviousHash() {

        return previousHash;

    public void setPreviousHash(String previousHash) {

    public long getTimestamp() {

        return timestamp;

    public void setTimestamp(long timestamp) {

    public String getData() {

        return data;

    public void setData(String data) {

    public String getHash() {

        return hash;

    public void setHash(String hash) {

}

-----------------------------------BlockService.java-------------------------------------

import java.util.ArrayList;

import java.util.List;

public class BlockService {

//用來儲存所有資料的區塊連結清單

    private List<Block> blockChain;

    public BlockService() {

        this.blockChain = new ArrayList<Block>();

        blockChain.add(this.getFristBlock());

    //非常原始的。就時把previousHash加上時間戳,加上資料。然後算出hash值。

    private String calculateHash(int index, String previousHash, long timestamp, String data) {

        StringBuilder builder = new StringBuilder(index);

        builder.append(previousHash).append(timestamp).append(data);

        return CryptoUtil.getSHA256(builder.toString());

    //擷取插入的最後一個區塊

    public Block getLatestBlock() {

        return blockChain.get(blockChain.size() - 1);

    //擷取第一個區塊

    private Block getFristBlock() {

        return new Block(1, "0", System.currentTimeMillis(), "Hello Block", "aa212344fc10ea0a2cb885078fa9bc2354e55efc81be8f56b66e4a837157662e");

    //産生下一個區塊

    public Block generateNextBlock(String blockData) {

        Block previousBlock = this.getLatestBlock();

        int nextIndex = previousBlock.getIndex() + 1;

        long nextTimestamp = System.currentTimeMillis();

        String nextHash = calculateHash(nextIndex, previousBlock.getHash(), nextTimestamp, blockData);

        return new Block(nextIndex, previousBlock.getHash(), nextTimestamp, blockData, nextHash);

    public void addBlock(Block newBlock) {

        if (isValidNewBlock(newBlock, getLatestBlock())) {

            blockChain.add(newBlock);

        }

    //比較新區塊是否有效區塊。

    private boolean isValidNewBlock(Block newBlock, Block previousBlock) {

        if (previousBlock.getIndex() + 1 != newBlock.getIndex()) {

            System.out.println("invalid index");

            return false;

        } else if (!previousBlock.getHash().equals(newBlock.getPreviousHash())) {

            System.out.println("invalid previoushash");

        } else {

            String hash = calculateHash(newBlock.getIndex(), newBlock.getPreviousHash(), newBlock.getTimestamp(),

                    newBlock.getData());

            if (!hash.equals(newBlock.getHash())) {

                System.out.println("invalid hash: " + hash + " " + newBlock.getHash());

                return false;

            }

        return true;

    public void replaceChain(List<Block> newBlocks) {

        if (isValidBlocks(newBlocks) && newBlocks.size() > blockChain.size()) {

            blockChain = newBlocks;

            System.out.println("Received blockchain invalid");

    private boolean isValidBlocks(List<Block> newBlocks) {

    //校驗第一個區塊是否一緻.

    Block fristBlock = newBlocks.get(0);

        if (fristBlock.equals(getFristBlock())) {

        //再依次校驗所有的區塊是否一緻。

        for (int i = 1; i < newBlocks.size(); i++) {

            if (isValidNewBlock(newBlocks.get(i), fristBlock)) {

                fristBlock = newBlocks.get(i);

            } else {

    public List<Block> getBlockChain() {

        return blockChain;

-----------------------------------CryptoUtil.java----------------------------------------

import java.security.MessageDigest;

public class CryptoUtil {

    private CryptoUtil() {

    //加密字元串成hash值。

    public static String getSHA256(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;

    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();

-----------------------------------HTTPService.java-------------------------------------

import com.alibaba.fastjson.JSON;

import org.java_websocket.WebSocket;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.net.InetSocketAddress;

public class HTTPService {

    private BlockService blockService;

    private P2PService   p2pService;

    public HTTPService(BlockService blockService, P2PService p2pService) {

        this.blockService = blockService;

        this.p2pService = p2pService;

    public void initHTTPServer(int port) {

//            Server server = new Server(port);

//            System.out.println("listening http port on: " + port);

//            ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);

//            context.setContextPath("/");

//            server.setHandler(context);

//            context.addServlet(new ServletHolder(new BlocksServlet()), "/blocks");

//            context.addServlet(new ServletHolder(new MineBlockServlet()), "/mineBlock");

//            context.addServlet(new ServletHolder(new PeersServlet()), "/peers");

//            context.addServlet(new ServletHolder(new AddPeerServlet()), "/addPeer");

//            server.start();

//            server.join();

            System.out.println("init http server is error:" + e.getMessage());

    private class BlocksServlet extends HttpServlet {

        @Override

        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

            resp.setCharacterEncoding("UTF-8");

            resp.getWriter().println(JSON.toJSONString(blockService.getBlockChain()));

    private class AddPeerServlet extends HttpServlet {

            this.doPost(req, resp);

        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

            String peer = req.getParameter("peer");

            p2pService.connectToPeer(peer);

            resp.getWriter().print("ok");

    private class PeersServlet extends HttpServlet {

            for (WebSocket socket : p2pService.getSockets()) {

                InetSocketAddress remoteSocketAddress = socket.getRemoteSocketAddress();

                resp.getWriter().print(remoteSocketAddress.getHostName() + ":" + remoteSocketAddress.getPort());

    private class MineBlockServlet extends HttpServlet {

            String data = req.getParameter("data");

            Block newBlock = blockService.generateNextBlock(data);

            blockService.addBlock(newBlock);

            p2pService.broatcast(p2pService.responseLatestMsg());

            String s = JSON.toJSONString(newBlock);

            System.out.println("block added: " + s);

            resp.getWriter().print(s);

-----------------------------------Message.java-----------------------------------------

import java.io.Serializable;

public class Message implements Serializable{

    private int    type;

    public Message() {

    public Message(int type) {

        this.type = type;

    public Message(int type, String data) {

    public int getType() {

        return type;

    public void setType(int type) {

-----------------------------------P2PService.java----------------------------------------

import org.java_websocket.client.WebSocketClient;

import org.java_websocket.handshake.ClientHandshake;

import org.java_websocket.handshake.ServerHandshake;

import org.java_websocket.server.WebSocketServer;

import java.net.URI;

import java.net.URISyntaxException;

import java.util.Collections;

import java.util.Comparator;

public class P2PService {

    private List<WebSocket> sockets;

    private BlockService    blockService;

    private final static int QUERY_LATEST        = 0;

    private final static int QUERY_ALL           = 1;

    private final static int RESPONSE_BLOCKCHAIN = 2;

    public P2PService(BlockService blockService) {

        this.sockets = new ArrayList<WebSocket>();

    //初始化一個P2P的server,用傳入的port做端口進行服務

    public void initP2PServer(int port) {

        final WebSocketServer socket = new WebSocketServer(new InetSocketAddress(port)) {

        //打開端口時觸發

        public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {

                write(webSocket, queryChainLengthMsg());

                sockets.add(webSocket);

        //關閉端口時觸發

            public void onClose(WebSocket webSocket, int i, String s, boolean b) {

                System.out.println("connection failed to peer:" + webSocket.getRemoteSocketAddress());

                sockets.remove(webSocket);

            //接受消息時觸發

            public void onMessage(WebSocket webSocket, String s) {

                handleMessage(webSocket, s);

            //消息出錯時觸發

            public void onError(WebSocket webSocket, Exception e) {

            //服務開始時觸發

            public void onStart() {

        };

        socket.start();

        System.out.println("listening websocket p2p port on: " + port);

    //

    private void handleMessage(WebSocket webSocket, String s) {

            Message message = JSON.parseObject(s, Message.class);

            System.out.println("Received message" + JSON.toJSONString(message));

            switch (message.getType()) {

                case QUERY_LATEST:

                    write(webSocket, responseLatestMsg());

                    break;

                case QUERY_ALL:

                    write(webSocket, responseChainMsg());

                case RESPONSE_BLOCKCHAIN:

                    handleBlockChainResponse(message.getData());

            System.out.println("hanle message is error:" + e.getMessage());

    private void handleBlockChainResponse(String message) {

        List<Block> receiveBlocks = JSON.parseArray(message, Block.class);

        Collections.sort(receiveBlocks, new Comparator<Block>() {

            public int compare(Block o1, Block o2) {

                return o1.getIndex() - o1.getIndex();

        });

        Block latestBlockReceived = receiveBlocks.get(receiveBlocks.size() - 1);

        Block latestBlock = blockService.getLatestBlock();

        if (latestBlockReceived.getIndex() > latestBlock.getIndex()) {

            if (latestBlock.getHash().equals(latestBlockReceived.getPreviousHash())) {

                System.out.println("We can append the received block to our chain");

                blockService.addBlock(latestBlockReceived);

                broatcast(responseLatestMsg());

            } else if (receiveBlocks.size() == 1) {

                System.out.println("We have to query the chain from our peer");

                broatcast(queryAllMsg());

                blockService.replaceChain(receiveBlocks);

            System.out.println("received blockchain is not longer than received blockchain. Do nothing");

    public void connectToPeer(String peer) {

            final WebSocketClient socket = new WebSocketClient(new URI(peer)) {

                @Override

                public void onOpen(ServerHandshake serverHandshake) {

                    write(this, queryChainLengthMsg());

                    sockets.add(this);

                }

                public void onMessage(String s) {

                    handleMessage(this, s);

                public void onClose(int i, String s, boolean b) {

                    System.out.println("connection failed");

                    sockets.remove(this);

                public void onError(Exception e) {

            };

            socket.connect();

        } catch (URISyntaxException e) {

            System.out.println("p2p connect is error:" + e.getMessage());

    private void write(WebSocket ws, String message) {

        ws.send(message);

    public void broatcast(String message) {

        for (WebSocket socket : sockets) {

            this.write(socket, message);

    private String queryAllMsg() {

        return JSON.toJSONString(new Message(QUERY_ALL));

    private String queryChainLengthMsg() {

        return JSON.toJSONString(new Message(QUERY_LATEST));

    private String responseChainMsg() {

        return JSON.toJSONString(new Message(RESPONSE_BLOCKCHAIN, JSON.toJSONString(blockService.getBlockChain())));

    public String responseLatestMsg() {

        Block[] blocks = {blockService.getLatestBlock()};

        return JSON.toJSONString(new Message(RESPONSE_BLOCKCHAIN, JSON.toJSONString(blocks)));

    public List<WebSocket> getSockets() {

        return sockets;

---------------------------------------------------------------------------------------

簡單來說,區塊鍊,就是一種對一個block的加密

不過是因為消耗了計算能力來擷取特定的加密字元串,也就是要求sha碼前16位全是0, 

當礦工挖到礦以後,調用addPeers接口,釋出自己挖到的礦,然後再通過peers2peers的方式廣播出去。

技術本身沒啥奇怪的。

結果又被瘋狂炒作。

這個瘋狂的結果是啥?想割中國的羊毛想瘋了?這種算術的加密字元串應該不算是啥有效貨币哈。

繼續閱讀