建议和反馈

请填写你的反馈内容

Java代码如何实现区块链

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

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

简而言之的区块链

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

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

不变性

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

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

// caches Transaction SHA256 hashes
    public Map map = new HashMap();
...

请注意,注入的泛型类型为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 {
public static final int BLOCK_SIZE = 10;
public List> chain = new ArrayList>();

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

...


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

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

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

Block block = new Block();

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

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

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

....
public void addAndValidateBlock(Block block) {

// compare previous block hash, add if valid
Block current = block;
for (int i = chain.size() - 1; i >= 0; i--) {
Block 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 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 merkleTree() {
ArrayList 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 chain1 = new SimpleBlockchain();

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

// get a block in chain
Block 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)
请先登录或注册

请先登陆或注册

相关推荐

如何解释“我篡改了区块链”这个问题

区块链数据“全局一致”、“难以篡改”这两个特性已经广为人知,是区块链营造“信任”的基石。为了达到这两个效果,区块链的共识、同步、校验等技术细节足可大书特书,而本文要从“我篡改了区块链数据”讲起。“我篡......
Moon · 2020-07-03
1280阅读 · 0赞赏 · 0问答

漏洞分析 | 一千种死法之 智能合约函数调用错误

6.18期间正愁”千手观音“还不够剁,如果一觉醒来,突然发现爸妈的账户可以随便用了,前男友的钱因为权限设置错误而面对你以及他所有前女友开放了。不是天上掉馅饼,而是老天可能漏了个洞。我的是我的,你的还是......
Rooney · 2020-06-27
843阅读 · 0赞赏 · 0问答

波卡启动 NPoS,几个知识点了解一下?

Polkadot 今日启动 NPoS(验证人选举),其技术方案也再次引发关注。关于 Polkadot 的几大技术知识点,我们都总结在此了:· Polkadot 网络,中继链、平行链和转接桥· XCMP......
多来A梦 · 2020-06-19
1353阅读 · 0赞赏 · 0问答

区块链 Go并发编程之Channel生产者-消费者模型及单向Channel

生产者与消费者关系在channel中生产者消费者关系可以简单的理解为:生产者和消费者一定是一一配对的状态存在先看一个简单的案例,生产者与消费者关系为1:2package mainimport......
· 2020-06-17
2401阅读 · 0赞赏 · 0问答

区块链 Go并发编程 之 管道 Channel

GO 管道 channel什么是管道管道是Go语言在语言级别上提供的goroutine间的通讯方式,我们可以使用channel在多个goroutine之间传递消息。channel是进程内的通讯方式,是......
Diva · 2020-06-17
2132阅读 · 0赞赏 · 0问答

区块链 GO 并发编程 之 主线程与子线程

基础概念什么是进程?进程:一个正在运行的程序一般是一个进程,一个进程可以包含多个线程 每个进程都有自己的独立的地址空间(内存空间),简单的理解一个运行程序为一个进程什么是线程线程:一条有序的CPU命令......
wind · 2020-06-16
2018阅读 · 0赞赏 · 0问答

16054

LK币

36

粉丝

405

笔记

感谢"区块链社区"

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

  • 0
  • 1
  • 7
  • 8
  • 6
喜欢0

大家好,请问下,我在使用go sdk 创建通道的时候,报这个错,请问怎么解决?

有没有谁研究过Ecert和Tcert的详细生成过程啊,还有审计中心通过Tcert找到派生该Tcert的Ecert的算法过程具体是怎么样的?有没有参考资料推荐一下,谢谢

区块链能不能支持SQL操作??

im钱包,我不小心创建了新钱包,原来的资产归零了,还能找回来吗,我用以太坊浏览器查询原来的地址能看到币还在,跪求帮助

BigchainDB支持.json 文件格式。有什么可能的方法来存储数字资产,例如图像,文档?

我用fabric-sdk 执行代码 resMgmtClient, err := resmgmt.New()的时候总是报错 failed to create resmgmt client due to context error: user not found,请问有大佬遇到过吗

请问我在应用端用mvn test执行fabcar的java的时候,出现下面的错,这个是证书的问题吗?》链接远程fabric的时候,总是很多莫名其妙的错,有哪位大大遇到过?

我实例化链码时,我在挂载目录放的是我自己的go文件,但是实例化的时候貌似显示的是官方提供的go文件,有谁遇到过这个情况吗

我在使用fabric-java-sdk,调用invoke方法的时候,控制台打印成功提交交易,但网络日志显示签名集不符合政策,这个获取签名是在fabric内部解决,还是在应用程序代码里解决,有点摸不着头脑

如何使用PHP / JS为用户生成以太坊钱包(私钥/公钥)?

链客社群 加入

微博进入

商务合作>

广告投放>

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

联系方式:010-67707199

ICP备案号:京ICP备18032136号

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

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

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

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

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