草庐IT

仅仅用java就能简单实现区块链(BlockChain)

冶环院 code monkey 2024-01-03 原文

区块链逻辑:根据所需信息创建一个区块,再利用定义的计算hash值方法,不断进行计算,直到达到想要的结果,再通过层层验证,加入到我们的区块链中。

1.设置好成员属性

​
    //区块链
    List<Block> blockchain = new ArrayList<>();
    //哈希值,判断挖矿成功与否
    private String hash;
    //前块哈希值,便于之后验证成功与否
    private String previousHash;
    //所需存储数据
    private String data;
    //时间戳
    private long timeStamp;
    //用于判断”挖矿“成功的密码学数字
    private int nonce;
    //构析方法,得到所需信息
    public Block(String data,String previousHash,long timeStamp){
        this.data = data;
        this.previousHash = previousHash;
        this.timeStamp = timeStamp;
        this.hash = calculateBlockHash();
    }

2.计算hash值方法(“挖矿”方法)

所谓挖矿,就是进行不断地计算,直到“挖到”,而这步算法我们是借助hash算法完成的。

    //得到对应hash字符串
    //hash算法优势:输出格式一致,而且对数的变化十分敏感,对于之后验证挖矿成功与否作用巨大!
    public String calculateBlockHash(){
        //生成独属的字符串,方便之后转换
        String dataToHash = previousHash + Long.toString(timeStamp)
        + Integer.toString(nonce) + data;
        MessageDigest digest = null;
        byte[] bytes = null;
        try {
            //创建一个提供信息摘要算法的对象,初始化为SHA-256算法对象
            digest = MessageDigest.getInstance("SHA-256");
            //用对象调用,信息摘要计算方法,计算后获得字节数组
            //dataToHash.getBytes(UTF_8),将字符串转换为字节数组
            bytes = digest.digest(dataToHash.getBytes(UTF_8));
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        //用缓存字符串
        StringBuffer buffer = new StringBuffer();
        for (byte b : bytes) {
            //延伸字符串
            //String.format("%02x", b),以十六进制输出,2为指定的输出字段的宽度.如果位数小于2,则左端补0
            buffer.append(String.format("%02x", b));
        }
        //返回字符串
        return buffer.toString();
    }

3.设置好挖矿成功的条件

老实说,“挖矿”这件事本身已经很抽象了,但是我们还需要沿着这条路,来考虑一个“挖到了”的情形。在我们“挖矿”实际是计算区块hash值的情形下,而我们的思路是:找到以四个0开头的hash值。

    //定义了一个前缀4,这实际上意味着我们希望哈希以4个零开始。
   
    int prefix = 4;
    String prefixString = new String(new char[prefix]).replace('\0', '0');

4.“挖到”方法

这里就体现了hash算法的价值,仅仅通过给nonce++,就可以显著的改变hash值,让其前缀可能达到“0000”。

而且由于只有nonce值并没有提供任何信息,所以对其进行赋值操作,完全没有问题。

    //开挖
    public String mineBlock(int prefix){
        //创建一个有perfix个的“0”的字符串
        String prefixString = new String(new char[prefix]).replace('\0','0');
        //找到开头有perfix多个0的字符串
        //substring方法是,从字符串几位读到几位
        while(!hash.substring(0,prefix).equals(prefixString)){
            //决定那个块
            nonce++;
            //通过nonce变化,更新hash值
            hash = calculateBlockHash();
        }
        //找到了
        return hash;
    }

5.添加一个区块

    //在区块链里添加一个块
    public void givenBlockchain_whenNewBlockAdded_thenSuccess() {
        //建立一个区块
        Block newBlock = new Block(
                "The is a New Block.",
                blockchain.get(blockchain.size() - 1).getHash(),
                new Date().getTime());
        //找到四个0的区块
        newBlock.mineBlock(prefix);
        //再次检验是否正确
        assertTrue(newBlock.getHash().substring(0, prefix).equals(prefixString));
        //添加一个区块
        blockchain.add(newBlock);
    }

6.区块链验证

为了保证区块的可靠性,我们就进行了多次验证,保证绝对正确。

验证:添加区块的hash值是否等于hash算法所得——》

添加区块的前区块hash值是否等于前区块的值——》

添加区块的hash值是否以“0000”开头

    //区块链验证
    public void givenBlockchain_whenValidated_thenSuccess() {
        boolean flag = true;
        for (int i = 0; i < blockchain.size(); i++) {
            //得到前区块的hash值
            String previousHash = i==0 ? "0" : blockchain.get(i - 1).getHash();
            //进行真伪判断
            //原理:判断hash是否等于计算的hash//判断储存的前区块hash是否等于真正的hash//判断是否满足“挖矿”成功的条件
            flag = blockchain.get(i).getHash().equals(blockchain.get(i).calculateBlockHash())
                    && previousHash.equals(blockchain.get(i).getPreviousHash())
                    && blockchain.get(i).getHash().substring(0, prefix).equals(prefixString);
            //一次不行就直接跳出
            if (!flag) break;
        }
        //进行正确性检验
        assertTrue(flag);
    }

现在已经完成了,开始制作自己的区块链吧,添加一些隐私信息,让别人无从知晓!

有关仅仅用java就能简单实现区块链(BlockChain)的更多相关文章

  1. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  2. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  3. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  4. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  5. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  6. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

  7. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  8. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  9. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

    我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

  10. 区块链之加解密算法&数字证书 - 2

    目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非

随机推荐