用java编写第一个区块链(代码片段)

vito-yan vito-yan     2022-11-23     550

关键词:

原文地址:https://www.cnblogs.com/zacky31/p/9057193.html

目标:

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

前提:

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

注意:

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

准备:

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

环境:

  • JDK 8
  • IDEA
  • Maven

开始吧

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

技术分享图片

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

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

import java.util.Date;

public class Block 
    public String hash; //存放数字签名
    public String preHash; //前面块的签名
    private String data;
    private long timeStamp;

    public Block(String data, String preHash) 
        this.data = data;
        this.preHash = preHash;
        this.timeStamp = new Date().getTime();
    

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

 

import java.security.MessageDigest;

public class StringUtil 
    public static String applySha256(String input) 
        try 
            MessageDigest digest = MessageDigest.getInstance("SHA-256");

            byte[] hash = digest.digest(input.getBytes("UTF-8"));
            StringBuilder hexString = new StringBuilder();
            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);
            
            return hexString.toString();
         catch (Exception e) 
            throw new RuntimeException(e);
        
    

 

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

public Block(String data, String preHash) 
        this.data = data;
        this.preHash = preHash;
        this.timeStamp = new Date().getTime();
        this.hash = calculateHash();
    

    public String calculateHash() 
        String calculatedhash = StringUtil.applySha256(preHash + Long.toString(timeStamp) + data);
        return calculatedhash;
    

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

public class Main 

    public static void main(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);
    

技术分享图片

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

import com.google.gson.GsonBuilder;

import java.util.ArrayList;

public class Main 

    public static ArrayList<Block> blockchain = new ArrayList<Block>();

    public static void main(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 = new GsonBuilder().setPrettyPrinting().create().toJson(blockchain);
        System.out.println(blockchainJson);
    

技术分享图片

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

public static Boolean 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;
    

  接下来,尝试一下挖矿!

  技术分享图片

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

import java.util.Date;

public class Block 
    public String hash;
    public String preHash;
    private String data;
    private long timeStamp;
    private int nonce;

    public Block(String data, String preHash) 
        this.data = data;
        this.preHash = preHash;
        this.timeStamp = new Date().getTime();
        this.hash = calculateHash();
    

    public String calculateHash() 
        String calculatedhash = StringUtil.applySha256(preHash + Long.toString(timeStamp) + Integer.toString(nonce) +
                data);
        return calculatedhash;
    

    public void mineBlock(int difficulty) 
        String target = new String(new char[difficulty]).replace(‘‘, ‘0‘);
        while (!hash.substring(0, difficulty).equals(target)) 
            nonce++;
            hash = calculateHash();
        
        System.out.println("Block Mined!!!" + hash);
    

  我们可以在 Main 类中定义个静态变量。尝试在每次创建新块去调用 mineBlock() 方法。

import com.google.gson.GsonBuilder;

import java.util.ArrayList;
import java.util.Date;

public class Main 

    public static ArrayList<Block> blockchain = new ArrayList<Block>();
    public static int difficulty = 5;

    public static void main(String[] args) 
        long beginTime1 = new Date().getTime();
        blockchain.add(new Block("Hi i am the first block", "0"));
        System.out.println("Trying to  mine block 1...");
        blockchain.get(0).mineBlock(difficulty);
        long endTime1 = new Date().getTime();
        System.out.println("Mining block 1 cost " + (endTime1 - beginTime1));


        long beginTime2 = new Date().getTime();
        blockchain.add(new Block("Hi i am the second block", blockchain.get(blockchain.size() - 1).hash));
        System.out.println("Trying to  mine block 2...");
        blockchain.get(1).mineBlock(difficulty);
        long endTime2 = new Date().getTime();
        System.out.println("Mining block 1 cost " + (endTime2 - beginTime2));

        long beginTime3 = new Date().getTime();
        blockchain.add(new Block("Hi i am the third block", blockchain.get(blockchain.size() - 1).hash));
        System.out.println("Trying to  mine block 3...");
        blockchain.get(2).mineBlock(difficulty);
        long endTime3 = new Date().getTime();
        System.out.println("Mining block 1 cost " + (endTime3 - beginTime3));

        System.out.println("
Blockchain is Valid: " + isChainValid());

        String blockchainJson = new GsonBuilder().setPrettyPrinting().create().toJson(blockchain);
        System.out.println(blockchainJson);
    

    public static Boolean isChainValid() 
        Block currentBlock;
        Block previousBlock;
        String hashTarget = new String(new char[difficulty]).replace(‘‘, ‘0‘);

        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;
            

            if (!currentBlock.hash.substring(0, difficulty).equals(hashTarget)) 
                System.out.println("This block hasn‘t been mined");
                return false;
            
        
        return true;
    

  运行发现,挖矿过程还是很费时间的。把计算量改成7,差不多每挖一个需要一分钟。。。

技术分享图片

  如果在此过程中,有人篡改了数据,将会导致:

  • 区块链将会无效
  • 不能够创建一个更长的区块链
  • 网络中的诚实链将会比较长的区块链有时间上的优势

  不过如果篡改数据拥有更强的运算速度,可能成功篡改。

  这样,基本上简单实现了一个区块链了。

用java代码实现区块链技术(代码片段)

...f01;简言之,区块链首先让我们快速总结一下区块链。一个块包含一些标题信息和一组或一块任何类型数据的事务。链从第一个(起源)块开始。在添加/追加事务时,将根据一个块中可以存储的事务数量创建新的... 查看详情

手把手教你区块链java开发智能合约nft-第五篇(铸造第一个nft)(代码片段)

...把手教你区块链java开发智能合约nft-第五篇(铸造第一个NFT)回顾部署NFT721铸造NFT根据tokenId查看NFT链上数据完整代码[NFT721相关智能合约源码下载](https://download.csdn.net/download/huangxuanheng/86260438)手把手教你区块链java开发智能... 查看详情

区块链的简单实现(代码片段)

...区块hash验证块的有效性记录数据从其他节点接收一个块编写测试代码测试结果完整代码什么是区块链一个维护着一个持续增长的有序数据记录列表的这么一个分布式数据库下面我将简单用nodejs实现一个简单的区块链,它具有... 查看详情

我居然用java构建了一个属于我自己的区块链(代码片段)

...#xff0c;区块链的设计是不可变的。在这里,我们将设计一个简单的区块链,它将帮助您理解散列如何使区块链不可变,只需几行Java代码。注:这只是一个演示区块链,真正的区块链涉及很多其他东西,如共... 查看详情

区块链-1了解(代码片段)

...概念区块链技术用区块去记录流水账。(比特币的第一个区块–创世区块)支付宝的相护宝是用了蚂蚁的区块链技术。区块链的优点去中心化,更安全分布式系统通过互联网来维护一个公共的账本,由两个以上节... 查看详情

ctf的区块链入门资料(代码片段)

文章目录编写课件的心路历程第一阶段第二阶段题目列表靶场SecurityInnovationBlockchainCTF合约逆向其他常用平台区块链安全公司相关编写课件的心路历程第一阶段查找半个小时,发现CTF区块链的资料很少,稍微有点慌。在找... 查看详情

zt-----用javascrip写一个区块链(代码片段)

...们背后的技术。在这篇博客中,我将会用JavaScript来创建一个简单的区块链来演示它们的内部究竟是如何工作的。我将会称之为SavjeeCoin!全文分为三个部分: 实现一个基本的区块链实现POW交易与挖矿奖励 实现一个基本的... 查看详情

第一行代码:以太坊-创建自己的私有区块链(代码片段)

本文会利用以太坊客户端(geth)搭建一个私有区块链,并在这个私有区块链上挖矿,通过本文的案例,读者可以更深入理解区块链、以太坊、挖矿的理论。通过阅读本文,您可以:掌握搭建以太坊开发环境的方法掌握geth的基本... 查看详情

第一行代码:以太坊-创建自己的私有区块链(代码片段)

本文会利用以太坊客户端(geth)搭建一个私有区块链,并在这个私有区块链上挖矿,通过本文的案例,读者可以更深入理解区块链、以太坊、挖矿的理论。通过阅读本文,您可以:掌握搭建以太坊开发环境的方法掌握geth的基本... 查看详情

搭建你的第一个区块链网络(代码片段)

前一篇文章:搭建你的第一个区块链网络(一)共识与本地化POW共识共识机制也是区块链系统中不可缺少的一部分,在比特币网络中,使用的是POW共识,概念相对比较简单,所以我们在该项目中使用POW共识机制(后期如果可以的话修... 查看详情

搭建你的第一个区块链网络(代码片段)

前一篇文章:搭建你的第一个区块链网络(一)共识与本地化POW共识共识机制也是区块链系统中不可缺少的一部分,在比特币网络中,使用的是POW共识,概念相对比较简单,所以我们在该项目中使用POW共识机制(后期如果可以的话修... 查看详情

用python构建一个极小的区块链(代码片段)

虽然有些人认为区块链是一个早晚会出现问题的解决方案,但是毫无疑问,这个创新技术是一个计算机技术上的奇迹。那么,究竟什么是区块链呢?区块链以比特币Bitcoin或其它加密货币按时间顺序公开地记录交易的数字账本。... 查看详情

wdk学习笔记第四周_区块链总体简述(代码片段)

...三、以太坊简述四、超级账本简述总结参考摘要区块链是一个单向链式存储结构,区块中存储了前一个区块的hash值,交易数据等,区块间通过区块中存储的“前一个区块的hash值”连接,当链中某个区块数据被删... 查看详情

fiscobcos开发第一个区块链应用--小白实战(代码片段)

官方链接简单的步骤直接跳过了,主要是记录下整个过程中出现问题最多的地方4.创建区块链应用项目第一步.安装环境首先,我们需要安装JDK以及集成开发环境首先,在官网上下载JDK14(JDK1.8至JDK14都支持)并... 查看详情

fiscobcos开发第一个区块链应用(代码片段)

FISCOBCOS开发第一个区块链应用这里只是记录流程、遇到的问题、解决方法以及注意的点详细见开发文档:[https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/tutorial/sdk_application.html]问题:1、Resolvingdependencyconfiguration‘runtime... 查看详情

区块链的简单实现(代码片段)

...区块hash验证块的有效性记录数据从其他节点接收一个块编写测试代码测试结果完整代码什么是区块链一个维护着一个持续增长的有序数据记录列表的这么一个分布式数据库下面我将简单用nodejs实现一个简单的区块链,它具有... 查看详情

创建自己的区块链网络六(代码片段)

目录前言系列文章直通车一、编写生成初始区块命令二、运行start.sh结语前言我们之前修改了几个配置文件,新建了一个start.sh文件并赋予了它权限,那么现在我们就是编写命令来启动网络了。系列文章直通车名称链接创... 查看详情

用go构建一个区块链--part7:网络(代码片段)

...密货币成为可能的,是网络(network)。如果实现的这样一个区块链仅仅运行在单一节点上,有什么用呢?如果只有一个用户,那么这些基于密码学的特性,又有什么用呢?正是由于网络,才使得整个机 查看详情