1. 概述
本文中,我们将学习区块链技术的基本概念。也将根据概念使用 Java 来实现一个基本的应用程序。
进一步,我们将讨论一些先进的概念以及该技术的实际应用。
因此,让我们首先了解到底什么是区块链...
它的起源可以追溯到2008年 Satoshi Nakamoto 在比特币上发布的白皮书。
区块链是一个分散的信息分类账。它由通过使用密码学连接的数据块组成。它属于通过公共网络连接的节点网络。当我们稍后尝试构建一个基本教程时,我们会更好地理解这一点。
有一些我们必须要明白的重要属性,所以让我们来看看它们:
现在,让我们了解区块链如何工作。
区块链的基本单位是块。一个块能封装多个事务或者其它有价值的数据:
我们用哈希值表示一个块。生成块的哈希值叫做“挖掘”块。挖掘块通常在计算上很昂贵,因为它可以作为“工作证明”。
块的哈希值通常由以下数据组成:
网络中的多个节点可以同时对数据块进行挖掘。除了生成哈希外,节点还必须验证添加到块中的事务是否合法。先挖一个街区,就赢了比赛!
当挖掘一个块在计算上很昂贵时,验证块是否合法相对来说十分简单。所有在网络上的节点都参与验证新挖掘的块。
因此,在节点协商一致时将新挖掘的块添加到区块链中。
现在,我们可以使用几种共识协议进行验证。网络中的节点使用相同的协议来检测链的恶意分支。因此,即使引入了恶意分支,大多数节点也会很快拒绝它。
现在我们已经有了足够的上下文来开始用 Java 构建一个基本的应用程序。
我们这里的简单示例将演示我们刚才看到的基本概念。生产级应用程序包含许多超出本教程范围的考虑因素。不过,我们稍后将讨论一些高级主题。
首先,我们需要定义一个简单的 POJO 来保存块数据:
public class Block { 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(); } // standard getters and setters}
让我们来看看我们在这里打包了什么:
现在,我们如何计算块的哈希?我们使用方法 calculateBlockHash ,但是还没有看到实现。在实现这个方法之前,值得花时间了解一下哈希是什么。
哈希是哈希函数的输出。哈希函数将任意大小的输入数据映射到固定大小的输出数据。哈希对输入数据中的任何更改都非常敏感,不管这些更改有多小。
此外,仅从它的哈希中获取输入数据是不可能的。这些属性使得哈希函数在密码学中非常有用。
那么,让我们看看如何在 Java 中生成块的哈希:
public String calculateBlockHash() { String dataToHash = previousHash + Long.toString(timeStamp) + Integer.toString(nonce) + data; MessageDigest digest = null; byte[] bytes = null; try { digest = MessageDigest.getInstance("SHA-256"); bytes = digest.digest(dataToHash.getBytes(UTF_8)); } catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) { logger.log(Level.SEVERE, ex.getMessage()); } StringBuffer buffer = new StringBuffer(); for (byte b : bytes) { buffer.append(String.format("%02x", b)); } return buffer.toString();}
这里发生了很多事情,让我们来详细了解一下:
到目前为止,一切听起来都很简单和优雅,除了我们还没有挖掘过块。那么究竟需要挖掘一个块,这已经吸引了开发人员一段时间的幻想!
因此,挖掘一个块意味着为块解决一个计算上复杂的任务。虽然计算块的哈希值比较简单,但是找到以5个0开头的哈希值就不那么简单了。更复杂的是找到一个以10个0开头的哈希,我们得到了一个大致的概念。
那么,我们到底该怎么做呢?老实说,这个解决方案没有想象中的那么好!我们是用蛮力来达到这个目标的。我们在这里使用 nonce:
public String mineBlock(int prefix) { String prefixString = new String(new char[prefix]).replace('\0', '0'); while (!hash.substring(0, prefix).equals(prefixString)) { nonce++; hash = calculateBlockHash(); } return hash;}
让我们看看我们要做的是:
我们从 nonce 的默认值开始,并将其递增1。但是,在实际应用程序中,有更多复杂的策略来启动和增加 nonce。此外,我们没有验证我们的数据,这通常是一个重要的部分。
现在我们已经定义了块及其函数,我们可以使用它来创建一个简单的区块链。我们将它存储在一个 ArrayList 中:
List<Block> blockchain = new ArrayList<>();int prefix = 4;String prefixString = new String(new char[prefix]).replace('\0', '0');
此外,我们定义了一个前缀为4,这实际上意味着我们希望哈希以4个零开始。
让我们看看如何在这里添加一个块:
@Testpublic void givenBlockchain_whenNewBlockAdded_thenSuccess() { Block newBlock = new Block( "The is a New Block.", blockchain.get(blockchain.size() - 1).getHash(), new Date().getTime()); newBlock.mineBlock(prefix); assertTrue(newBlock.getHash().substring(0, prefix).equals(prefixString)); blockchain.add(newBlock);}
节点如何验证区块链是否有效?虽然这可能相当复杂,但让我们考虑一个简单的版本:
@Testpublic void givenBlockchain_whenValidated_thenSuccess() { boolean flag = true; for (int i = 0; i < blockchain.size(); i++) { String previousHash = i==0 ? "0" : blockchain.get(i - 1).getHash(); 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 来实现了基本概念。我们还讨论了一些与之相关的先进概念。
最后,我们总结了区块链的一些实际应用以及可用的工具。
一如既往,代码可以在 GitHub 上找到。