简易区块链源码研究

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 区块链

区块链源码研究


目前看了一哈一个简易区块链的源码,下面贴贴自己的研究结果:


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

-----------------------------------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) {

        this.index = index;

    }


    public String getPreviousHash() {

        return previousHash;

    }


    public void setPreviousHash(String previousHash) {

        this.previousHash = previousHash;

    }


    public long getTimestamp() {

        return timestamp;

    }


    public void setTimestamp(long timestamp) {

        this.timestamp = timestamp;

    }


    public String getData() {

        return data;

    }


    public void setData(String data) {

        this.data = data;

    }


    public String getHash() {

        return hash;

    }


    public void setHash(String hash) {

        this.hash = hash;

    }

}



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

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

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


package com.fpfpp.server.blockchain;


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

            return false;

        } 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;

        } else {

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

        }

    }


    private boolean isValidBlocks(List<Block> newBlocks) {

    //校验第一个区块是否一致.

    Block fristBlock = newBlocks.get(0);

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

            return false;

        }

        //再依次校验所有的区块是否一致。

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

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

                fristBlock = newBlocks.get(i);

            } else {

                return false;

            }

        }

        return true;

    }


    public List<Block> getBlockChain() {

        return blockChain;

    }


}


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

package com.fpfpp.server.blockchain;


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-------------------------------------
-------------------------------------------------------------------------------------------

package com.fpfpp.server.blockchain;

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) {
        try {
//            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();
        } catch (Exception e) {
            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 {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doPost(req, resp);
        }

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setCharacterEncoding("UTF-8");
            String peer = req.getParameter("peer");
            p2pService.connectToPeer(peer);
            resp.getWriter().print("ok");
        }
    }


    private class PeersServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setCharacterEncoding("UTF-8");
            for (WebSocket socket : p2pService.getSockets()) {
                InetSocketAddress remoteSocketAddress = socket.getRemoteSocketAddress();
                resp.getWriter().print(remoteSocketAddress.getHostName() + ":" + remoteSocketAddress.getPort());
            }
        }
    }


    private class MineBlockServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doPost(req, resp);
        }

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setCharacterEncoding("UTF-8");
            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-----------------------------------------
-------------------------------------------------------------------------------------------
package com.fpfpp.server.blockchain;

import java.io.Serializable;

public class Message implements Serializable{
    private int    type;
    private String data;

    public Message() {
    }

    public Message(int type) {
        this.type = type;
    }

    public Message(int type, String data) {
        this.type = type;
        this.data = data;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }
}

-------------------------------------------------------------------------------------------
-----------------------------------P2PService.java----------------------------------------
-------------------------------------------------------------------------------------------
package com.fpfpp.server.blockchain;

import com.alibaba.fastjson.JSON;
import org.java_websocket.WebSocket;
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.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

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.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) {
                System.out.println("connection failed to peer:" + webSocket.getRemoteSocketAddress());
                sockets.remove(webSocket);
            }

            //服务开始时触发
            public void onStart() {

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

    //
    private void handleMessage(WebSocket webSocket, String s) {
        try {
            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());
                    break;
                case RESPONSE_BLOCKCHAIN:
                    handleBlockChainResponse(message.getData());
                    break;
            }
        } catch (Exception e) {
            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());
            } else {
                blockService.replaceChain(receiveBlocks);
            }
        } else {
            System.out.println("received blockchain is not longer than received blockchain. Do nothing");
        }
    }

    public void connectToPeer(String peer) {
        try {
            final WebSocketClient socket = new WebSocketClient(new URI(peer)) {
                @Override
                public void onOpen(ServerHandshake serverHandshake) {
                    write(this, queryChainLengthMsg());
                    sockets.add(this);
                }

                @Override
                public void onMessage(String s) {
                    handleMessage(this, s);
                }

                @Override
                public void onClose(int i, String s, boolean b) {
                    System.out.println("connection failed");
                    sockets.remove(this);
                }

                @Override
                public void onError(Exception e) {
                    System.out.println("connection failed");
                    sockets.remove(this);
                }
            };
            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的方式广播出去。
技术本身没啥奇怪的。
结果又被疯狂炒作。
这个疯狂的结果是啥?想割中国的羊毛想疯了?这种算术的加密字符串应该不算是啥有效货币哈。

目录
相关文章
|
4月前
|
安全 区块链
区块链积分商城系统开发详细指南//需求功能/指南教程/源码流程
Developing a blockchain points mall system involves multiple aspects such as blockchain technology, smart contracts, front-end development, and business logic design. The following is the general process for developing a blockchain points mall system
|
4月前
|
安全 JavaScript 前端开发
区块链钱包系统开发解决方案/需求设计/功能逻辑/案例详细/源码步骤
The development of a blockchain wallet system involves multiple aspects, and the following is the detailed logic for developing a blockchain wallet system:
|
4月前
|
数据采集 监控 算法
区块链量化交易系统开发策略详细丨需求步骤丨案例设计丨规则玩法丨成熟源码
策略:建立数据采集系统,获取各种市场数据,包括交易数据、新闻情报、社交媒体消息等。
|
4月前
|
安全 区块链
区块链农场游戏系统开发运营版/玩法详情/规则方案/案例设计/项目源码
Developing a blockchain farm game system is an interesting and challenging task. Here is a design solution that can help you get started developing such a system
|
12月前
|
供应链 安全 物联网
区块链去中心化交易所源码|去中心化交易系统开发
随着区块链技术的发展,应用的扩展,区块链软件开√发也随之应用到物联网、供应链管理等领域,其中包含区块链交Y所系统,区块链去中心化交Y所,依托于区块链技术,具有去中心化、匿名性、信息不可纂改等特点
|
2月前
|
存储 安全 前端开发
区块链 DAPP 互助逻辑模式系统开发技术方案[源码示例]
Dapp(Decentralized Application)是指不受任何中心化组织或机构控制的、使用特定区块链技术为基础的去中心化应用程序。Dapp 是一种特殊类型的应用,它可以在任何基于区块链技术的系统,例如 Ethereum、EOS 或其他的智能合约系统上运行。
|
3月前
|
存储 供应链 安全
区块链技术在供应链管理中的透明性与可追溯性研究
区块链技术在供应链管理中的透明性与可追溯性研究
|
3月前
|
供应链 区块链
基于区块链的供应链管理追溯系统研究
基于区块链的供应链管理追溯系统研究
|
4月前
|
监控 前端开发 安全
区块链积分商城系统开发详细步骤及源码
区块链积分商城系统涉及到多个方面的技术和流程。以下是一般开发流程的简要概述
|
4月前
|
安全 AndFix 区块链
区块链3D元宇宙游戏系统开发规则玩法/步骤指南/源码项目
Developing a blockchain metaverse 3D game system is a complex and innovative process that requires comprehensive consideration of blockchain technology, game design and development, and virtual reality (VR). The following is the general process for developing the system:

热门文章

最新文章