【原】用Java编写第一个区块链(一)

摘要:
  写这篇随笔主要是尝试帮助自己了解如何学习区块链技术开发。环境:JDK8IDEAMaven开始吧  区块链就好比多个块连接起来。通过计算和比较所得的hash值,我们可以判断区块链是否合法。换句话说,改变区块链中的任意内容,将会改变整个区块链的签名。publicclassMain{publicstaticvoidmain{Blockfirst=newBlock;System.out.println;Blocksecond=newBlock;System.out.println;Blockthird=newBlock;System.out.println;}}  可以看见每个Block都有自己唯一的数字签名,当然,现在还没有构成一个区块链,将这些块存放到一个ArrayList中吧。

  写这篇随笔主要是尝试帮助自己了解如何学习区块链技术开发。

 【本文禁止任何形式的全文粘贴式转载,本文来自zacky31的随笔】

目标:

  • 创建一个最基本的“区块链”
  • 实现一个简单的挖矿系统

前提:

对面向对象编程有一定的基础

注意:

值得注意的是,这不会是一个完整的功能,恰恰相反,这是一个概念证明的实例,可以帮助您进一步了解区块链。

准备:

  我将会使用Java来实现,当然你也可以使用任何面向对象的语言。

环境:

  • JDK 8
  • IDEA
  • Maven

开始吧

  区块链就好比多个块连接起来。其中每一块都将拥有自己的签名,签名中包含其前面的块信息和一些数据(例如交易信息)。

【原】用Java编写第一个区块链(一)第1张

  每个块不仅仅包含它之前的块信息,同时也包含自身。如果前面一块内容改变了,其 hash 值也会改变,将会导致其后面所有的块发生变化。通过计算和比较所得的 hash 值,我们可以判断区块链是否合法。换句话说,改变区块链中的任意内容,将会改变整个区块链的签名。

  根据上面的分析,我们先创建一个 Block 类。

importjava.util.Date;
public classBlock {
    public String hash; //存放数字签名
    public String preHash; //前面块的签名
    privateString data;
    private longtimeStamp;
    publicBlock(String data, String preHash) {
        this.data =data;
        this.preHash =preHash;
        this.timeStamp = newDate().getTime();
    }
}

  接下来,我们需要一个生成签名的方法。有很多加密算法可供选择,这里使用 SHA256 刚刚好。

importjava.security.MessageDigest;
public classStringUtil {
    public staticString applySha256(String input) {
        try{
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(input.getBytes("UTF-8"));
            StringBuilder hexString = newStringBuilder();
            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);
            }
            returnhexString.toString();
        } catch(Exception e) {
            throw newRuntimeException(e);
        }
    }
}

  现在,我们向 Block 类中添加计算数字签名的方法,并修改一下其构造方法。

publicBlock(String data, String preHash) {
        this.data =data;
        this.preHash =preHash;
        this.timeStamp = newDate().getTime();
        this.hash =calculateHash();
    }
    publicString calculateHash() {
        String calculatedhash = StringUtil.applySha256(preHash + Long.toString(timeStamp) +data);
        returncalculatedhash;
    }

  到这里,可以写个 Main 方法看一下效果。

public classMain {
    public static voidmain(String[] args) {
        Block first = new Block("Hi i am the first block", "0");
        System.out.println("Hash for block 1 : " +first.hash);
        Block second = new Block("Hi i am the second block", first.hash);
        System.out.println("Hash for block 2 : " +second.hash);
        Block third = new Block("Hi i am the third block", second.hash);
        System.out.println("Hash for block 3 : " +third.hash);
    }
}

【原】用Java编写第一个区块链(一)第2张

  可以看见每个 Block 都有自己唯一的 数字签名,当然,现在还没有构成一个区块链,将这些块存放到一个 ArrayList 中吧。修改 Main 类后再次运行。

importcom.google.gson.GsonBuilder;
importjava.util.ArrayList;
public classMain {
    public static ArrayList<Block> blockchain = new ArrayList<Block>();
    public static voidmain(String[] args) {
        blockchain.add(new Block("Hi i am the first block", "0"));
        blockchain.add(new Block("Hi i am the second block", blockchain.get(blockchain.size() - 1).hash));
        blockchain.add(new Block("Hi i am the third block", blockchain.get(blockchain.size() - 1).hash));
        String blockchainJson = newGsonBuilder().setPrettyPrinting().create().toJson(blockchain);
        System.out.println(blockchainJson);
    }
}

【原】用Java编写第一个区块链(一)第3张

  现在,需要一种方法去验证创建的区块链。编写一段 isChainValid() 方法。任何块的改变将会导致这个方法失效。

public staticBoolean isChainValid() {
        Block currentBlock;
        Block previousBlock;
        for (int i = 1; i < blockchain.size(); i++) {
            currentBlock =blockchain.get(i);
            previousBlock = blockchain.get(i - 1);
            if (!currentBlock.hash.equals(currentBlock.calculateHash())) {
                System.out.println("Current Hashes not equal!");
                return false;
            }
            if (!previousBlock.hash.equals(currentBlock.preHash)) {
                System.out.println("Previous Hashes not equal!");
                return false
            }
        }
        return true;
    }

  接下来,尝试一下挖矿!

  【原】用Java编写第一个区块链(一)第4张

  在 Block 类中,新增一个变量 nonce,并且添加到 calculateHash() 这个方法中,同时需要 mineBlock() 这个方法。这个方法中的 difficulty 变量就是用来控制计算量的。当设置的值较低时,大部分计算机很快就能算出来。

importjava.util.Date;
public classBlock {
    publicString hash;
    publicString preHash;
    privateString data;
    private longtimeStamp;
    private intnonce;
    publicBlock(String data, String preHash) {
        this.data =data;
        this.preHash =preHash;
        this.timeStamp = newDate().getTime();
        this.hash =calculateHash();
    }
    publicString calculateHash() {
        String calculatedhash = StringUtil.applySha256(preHash + Long.toString(timeStamp) + Integer.toString(nonce) +
                data);
        returncalculatedhash;
    }
    public void mineBlock(intdifficulty) {
        String target = new String(new char[difficulty]).replace('

免责声明:内容来源于网络,仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Firefox关闭GET请求到detectportal.firefox.com网站的方法使用Elasticsearch的processors来对csv格式数据进行解析下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【nodejs】 文件系统(fs) 之读写文件

//写入文件 var data = "hello world"; fs.writeFile('c:\a.txt', data, 'ascii', function(err) { if(err) { console.log('写入文件失败'); } else{ console.log('保存成功, 赶紧去看看...

noip2011普及组:统计单词

题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位 置,有的还能统计出特定单词在文章中出现的次数。 现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章 中出现的次数和第一次出现的位置。注意:匹配单词时,不区分大小写,但要求完全匹配, 即给定单词必须与文章中的某一独立单词在不区分大小写的情况下完全相...

ASP.NET Core 实现 MQTT通讯协议 Demo(开源库:MQTTnet)

1、什么是MQTT   MQTT(message queuing telemetry transport)是IBM开发的即时通讯协议,是一种发布/订阅极其轻量级的消息传输协议,专门为网络受限设备、低宽带以及高延迟和不可靠的网络而设计的。由于以上轻量级的特点,是实现智能家居的首选传输协议,相比于XMPP,更加轻量级而且占用宽带低。简单来说HQTT是一种通信...

Go语言正则表达式提取网页文本

为了方便提取,我们会把正则表达式中要提取的数据使用命名方式来书写正则表达式。这个技术在Go语言中如何实现,可以看下面这篇博客: Using the Go Regexp Packagehttp://blog.kamilkisiel.net/blog/2012/07/05/using-the-go-regexp-package/ 简单期间,这里复制其中几个例子...

Unity面试题汇总(第一部分)

一、什么是渲染管道? 答:就是告诉GPU一些数据,经过一系列的操作,得到最终要显示的数据。渲染管道中的很多步骤,总的来说是将几何物体从一个坐标系变换到另一个坐标系中去。 主要步骤如下: 本地坐标系 -- 经过世界变换矩阵 --> 世界坐标系 -- 经过视图变换矩阵 --> 视图坐标系 -- 经过投影变换矩阵 --> 投影坐标系 -- 经过...

WPF多语言化的实现

  Metro插件系统系列就暂时停一下,这次我们讨论一下WPF的资源本地化实现,主要用到的:CultureInfo,ResourceManger,MarkupExtension,RESX文件,这些都是.NET框架提供的。 项目结构: 运行结果: 可在程序运行时,实时切换语言 CultureInfo   CultureInfo类表示有关特定区域性的信息...