建议和反馈

请填写你的反馈内容

Java代码如何实现区块链

2019-12-03 ·726次阅读 ·读完需要13分钟

让我们看一下使用Java的可能的区块链实现。我们从第一条原则开始构建,并开发一些代码来帮助展示它们如何融合在一起。本文将重点介绍区块链架构。特别是,通过简单的代码示例演示“不变的,仅追加”分布式分类帐如何工作。作为开发人员,与仅阅读技术文章相比,在代码中看到事物对于理解其工作原理可能会更加有用。

简而言之的区块链

首先让我们简要介绍一下区块链。块包含一些头信息以及任何类型的数据的交易集或块。该链从第一个(Genesis)块开始。在添加/添加事务时,将基于一个块中可以存储多少个事务来创建新块。

当超过块阈值大小时,将创建一个新的交易块。新区块链接到前一个区块,因此称为区块链。

不变性

区块链是不可变的,因为为交易计算了SHA-256哈希。块的内容也会被散列,从而提供唯一的标识符。此外,来自链接的先前块的哈希也被存储并哈希在块头中。这就是为什么至少在目前的计算能力下,尝试篡改区块链块基本上是不可能的。这是部分Java类定义,显示了该块的属性。

...
public class Block<T extends Tx> {
public long timeStamp;
private int index;
private List<T> transactions = new ArrayList<T>();
private String hash;
private String previousHash;
private String merkleRoot;
private String nonce = "0000";

// caches Transaction SHA256 hashes
    public Map<String,T> map = new HashMap<String,T>();
...

请注意,注入的泛型类型为Tx这允许交易数据变化。同样,该previousHash属性将引用前一个块的哈希。merkleRootnonce特性将在一个位进行说明。

区块哈希

每个块可以计算一个块哈希。这实际上是所有块属性串联在一起的散列,包括前一个块的散列和从中计算出的SHA-256散列。

这是在Block.java类中定义的用于计算哈希的方法。


...
public void computeHash() {
    Gson parser = new Gson(); // probably should cache this instance
    String serializedData = parser.toJson(transactions);  
    setHash(SHA256.generateHash(timeStamp + index + merkleRoot + serializedData + nonce + previousHash));
    }
...


区块交易被序列化为JSON字符串,因此可以在哈希之前将其附加到区块属性中。

连锁,链条

区块链通过接受交易来管理区块。当达到预定阈值时,则创建一个块。这是SimpleBlockChain.java部分实现:


...
...
public class SimpleBlockchain<T extends Tx> {
public static final int BLOCK_SIZE = 10;
public List<Block<T>> chain = new ArrayList<Block<T>>();

public SimpleBlockchain() {
// create genesis block
chain.add(newBlock());
}

...


请注意,chain属性包含使用类型键入的块列表Tx同样,no arg当创建链时构造函数会创建一个初始的“ genesis”块。这是该newBlock()方法的来源

...
public Block<T> newBlock() {
int count = chain.size();
String previousHash = "root";

if (count > 0)
previousHash = blockChainHash();

Block<T> block = new Block<T>();

block.setTimeStamp(System.currentTimeMillis());
block.setIndex(count);
block.setPreviousHash(previousHash);
return block;
}
...

这个新的块方法将创建一个新的块实例,为适当的值播种,并分配前一个块的哈希(这将是链头的哈希)。然后它将返回该块。

通过将新块的先前哈希与链的最后一个块(头)进行比较以确保它们匹配,可以在将块添加到链之前对其进行验证。这是SimpleBlockchain.java描述此方法的方法。

....
public void addAndValidateBlock(Block<T> block) {

// compare previous block hash, add if valid
Block<T> current = block;
for (int i = chain.size() - 1; i >= 0; i--) {
Block<T> b = chain.get(i);
if (b.getHash().equals(current.getPreviousHash())) {
current = b;
} else {

throw new RuntimeException("Block Invalid");
}

}

this.chain.add(block);
}
...

整个区块链通过链的循环验证,以确保区块的哈希仍与先前区块的哈希匹配。

这是SimpleBlockChain.java validate()方法的实现。

...
public boolean validate() {

String previousHash = null;
for (Block<T> block : chain) {
String currentHash = block.getHash();
if (!currentHash.equals(previousHash)) {
return false;
}

previousHash = currentHash;

}

return true;

}
...

您会发现尝试以任何方式捏造交易数据或任何其他属性非常困难。而且,随着链条的增长,它会变得越来越非常非常非常困难,几乎是不可能的-也就是说,直到量子计算机可用为止!

添加交易

区块链技术的另一个重要技术点是它是分布式的。它们仅是附件的事实有助于在参与区块链网络的节点之间复制区块链。节点通常以点对点的方式进行通信,就像比特币一样,但不一定是这种方式。其他区块链实施使用分散式方法,例如通过HTTP使用API。但是,这是另一篇文章的主题。

交易几乎可以代表任何东西。交易可以包含执行代码(即智能合约)或存储和附加有关某种商业交易的信息的代码。

智能合约:旨在以数字方式促进,验证或加强合同的谈判或履行的计算机协议。

在比特币的情况下,交易包含从所有者账户到其他账户的金额(例如,在账户之间转移比特币的金额)。交易中还包含公钥和帐户ID,因此可以安全地进行传输。但这是比特币特定的。

交易被添加到网络并合并;他们不是一个障碍或链本身。

这就是区块链共识机制发挥作用的地方。有许多行之有效的共识算法和模式,超出了本文的范围。

挖矿是比特币区块链使用的共识机制。这就是本文后面讨论的共识类型。共识机制收集交易,与交易建立一个区块,然后将该区块添加到链中。然后,链将在添加到链之前验证新的交易块。

默克尔树

交易被散列并添加到块中。创建Merkle Tree数据结构以计算Merkle Root哈希。每个块将存储Merkle树的根,该树是哈希的平衡二进制树,其中内部节点是两个子哈希的哈希,一直到根哈希(即Merkle根)。

该树用于验证大宗交易。如果在任何交易中更改了一点信息,则默克尔根将无效。同样,它们可以帮助以分布式方式传输块,因为该结构仅允许添加和验证整个交易块所需的交易哈希的单个分支。

这是Block.java类中的方法,该方法可在事务列表之外创建Merkle树。

...
public List<String> merkleTree() {
ArrayList<String> tree = new ArrayList<>();
// Start by adding all the hashes of the transactions as leaves of the
// tree.
for (T t : transactions) {
tree.add(t.hash());
}
int levelOffset = 0; // Offset in the list where the currently processed
// level starts.
// Step through each level, stopping when we reach the root (levelSize
// == 1).
for (int levelSize = transactions.size(); levelSize > 1; levelSize = (levelSize + 1) / 2) {
// For each pair of nodes on that level:
for (int left = 0; left < levelSize; left += 2) {
// The right hand node can be the same as the left hand, in the
// case where we don't have enough
// transactions.
int right = Math.min(left + 1, levelSize - 1);
String tleft = tree.get(levelOffset + left);
String tright = tree.get(levelOffset + right);
tree.add(SHA256.generateHash(tleft + tright));
}
// Move to the next level.
levelOffset += levelSize;
}
return tree;
}

...

此方法用于计算块的Merkle树根。伴随项目具有Merkle Tree单元测试,该测试试图将事务添加到块中并验证Merkle根是否已更改。这是单元测试的源代码。

...
@Test
public void merkleTreeTest() {

// create chain, add transaction

SimpleBlockchain<Transaction> chain1 = new SimpleBlockchain<Transaction>();

chain1.add(new Transaction("A")).add(new Transaction("B")).add(new Transaction("C")).add(new Transaction("D"));

// get a block in chain
Block<Transaction> block = chain1.getHead();

System.out.println("Merkle Hash tree :" + block.merkleTree());

// get a transaction from block
Transaction tx = block.getTransactions().get(0);

// see if block transactions are valid, they should be
block.transasctionsValid();
assertTrue(block.transasctionsValid());

// mutate the data of a transaction
tx.setValue("Z");

// block should no longer be valid, blocks MerkleRoot does not match computed merkle tree of transactions
assertFalse(block.transasctionsValid());

}

...

该单元测试模拟验证交易,然后在共识机制之外的块中更改交易,例如,如果有人尝试更改交易数据。

请记住,区块链是仅追加的,并且由于区块链数据结构在节点之间共享,因此区块数据结构(包括Merkle Root)被哈希并连接到其他区块。所有节点都可以验证新块,而现有块可以很容易地证明是有效的。因此,在太阳长成超新星并产生所有真正漂亮的棕褐色之前,矿工试图添加假块或试图调整较旧交易的节点实际上是不可能的。

采矿证明

在比特币世界中,将交易组合成一个区块,然后将其提交给链成员进行验证的过程称为“采矿”。

更一般地,用区块链的话来说,这被称为共识。有不同类型的经过验证的分布式共识算法。使用哪种机制取决于您是否拥有公共或许可的区块链。我们的白皮书对此进行了更深入的描述,但是本文重点关注区块链机制,因此本示例将应用工作量证明共识机制。

因此,挖掘节点将侦听由区块链执行的交易,并将执行一个简单的数学难题。这个难题使用随机数值生成带有预定的前导零集的块哈希值,该值在每次迭代中都会更改,直到找到前导零哈希值为止。

例如Java项目Miner.java一类proofOfWork(Block block)方法的实现,如下图所示。

private String proofOfWork(Block block) {

String nonceKey = block.getNonce();
long nonce = 0;
boolean nonceFound = false;
String nonceHash = "";

Gson parser = new Gson();
String serializedData = parser.toJson(transactionPool);
String message = block.getTimeStamp() + block.getIndex() + block.getMerkleRoot() + serializedData
+ block.getPreviousHash();

while (!nonceFound) {

nonceHash = SHA256.generateHash(message + nonce);
nonceFound = nonceHash.substring(0, nonceKey.length()).equals(nonceKey);
nonce++;

}

return nonceHash;

}

同样,这被简化,但是一旦接收到一定数量的交易,矿工实现将对该块执行工作量证明哈希。该算法仅循环并创建该块的SHA-256哈希,直到产生前导数字哈希为止。

这可能要花费很多时间,这就是为什么要使用特定的GPU微处理器来尽快执行和解决此问题的原因。

单元测试

您可以在GitHub上看到所有这些概念以及Java示例项目的JUnit测试。

试一下。它将使您了解这个简单的区块链如何工作。另外,如果您是C#的读者(我们不会告诉任何人),那么我们也有用C#编写的相同示例。这是示例C#区块链实现的链接。


希望这篇文章为您提供了足够的兴趣和见识,可以继续研究区块链技术。


本文介绍的所有示例均在我们的深入区块链白皮书中使用(无需注册即可阅读)。这些相同的示例在白皮书中有更详细的说明。


另外,如果您想在Java中看到完整的区块链实现,请点击此处,链接到开源BitcoinJ项目。您将在实际的生产实现中看到这些概念的实际应用。


如果是这样,下一步建议的学习步骤是检查更多基于生产的开源区块链框架。一个很好的例子是HyperLedger Fabric。这将是我下一篇文章的主题-敬请期待!


评论(0)问答(0)
请先登录或注册

请先登陆或注册

相关推荐

Jenkins系列:Jenkins构建常见错误

Jenkins构建常见问题项目构建失败常见原因iOS项目:检查编译日志。(注:编译日志等同于XCode的编译日志)android项目:检查编译日志。(注:编译日志等同于Android Studio的编......
moondesign · 2019-12-09
193阅读 · 0赞赏 · 0问答

使用Python和Keras的有关命名实体识别(NER)的完整教程

假设您是报纸行业的编辑,每天都会收到数千个故事。您将如何找到与体育,政治等特定领域相关的故事?您会讲完所有这些故事吗?无权利?一个可以帮助您划分为不同类别的系统怎么样?该系统还可以执行复杂的任务,例如......
三地 · 2019-12-09
251阅读 · 0赞赏 · 0问答

C#中的智能合约入门

在上一篇文章NEO区块链简介中,我们讨论了NEO区块链及其用途,在本文中,我们学习了如何使用Visual Studio和C#为NEO区块链智能合约设置开发机器。在下一篇文章中,我将更详细地讨论智能合约......
区块技术花 · 2019-12-07
498阅读 · 0赞赏 · 0问答

如何使用Metamask和Remix在Ropsten TestNet上部署和测试智能合约

想象一下要去一家冰淇淋店,品尝一些口味的冰淇淋,然后再选择要支付的口味。以太坊测试网就是这样。在将智能合约部署到实际花费真实以太币的真实以太坊网络之前,您需要通过将其部署在只是模拟真实以太坊网络的测试......
比特币论坛 · 2019-12-06
544阅读 · 0赞赏 · 0问答

在.NET Core中构建基本区块链

区块链技术是比特币的基础,比特币是世界上最受欢迎的加密货币。随着比特币的流行,区块链也获得了很大的曝光。人们现在也开始在非加密货币类型的应用程序中使用区块链。看看中本聪(Satoshi Nakamot......
btc论坛 · 2019-12-06
579阅读 · 0赞赏 · 0问答

去中心化应用程序堆栈

目前,Intranet处于隔离状态,无法相互通信和共享信息。现在基于区块链的网络也是如此。甚至对所有人开放的公共网络(例如比特币网络)也可以在其他公共网络之间独立运行,而无法在它们之间直接进行通信。在......
开发者小白 · 2019-12-05
503阅读 · 0赞赏 · 0问答

15931

LK币

35

粉丝

391

笔记

感谢"区块链社区"

这篇精彩的笔记,目前已经帮助

  • 0
  • 0
  • 7
  • 2
  • 6
喜欢0
链客社群 加入

微博进入

商务合作>

广告投放>

公司名称:北京链客行科技有限公司

联系方式:010-67707199

ICP备案号:京ICP备18032136号

Copyright:链客区块链技术问答社区 版权所有

感谢您的提问,问题被社区永久收入以便新人查看。一定要记得采纳最佳答案哦!加油!

感谢您的善举,每一次解答会成为新人的灯塔,回答被采纳后获得20算力和相应的LK币奖励

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!