image.png

区块

你可以看到,我们的基础 Block 类包含一个 String hash,它代表了数字签名。previousHash 变量为前一个区块的 hash 值,它和 String data 组成了这个区块的数据。

有很多加密算法可供我们选择,当然 SHA256 算法正好适合我们这个例子,使用这个算法来生成数字签名

  1. import java.util.Date;
  2. public class Block {
  3. public String hash;
  4. public String previousHash;
  5. private String data; //我们的数据是一条简单的消息
  6. private long timeStamp; //从 1/1/1970 起至现在的总毫秒数.
  7. //Block 类的构造方法.
  8. public Block(String data,String previousHash ) {
  9. this.data = data;
  10. this.previousHash = previousHash;
  11. this.timeStamp = new Date().getTime();
  12. }
  13. }

计算hash

  1. public String calculateHash() {
  2. String calculatedhash = StringUtil.applySha256(
  3. previousHash +
  4. Long.toString(timeStamp) +
  5. data
  6. );
  7. return calculatedhash;
  8. }

第一个区块被命名为起始区块,由于它前面没有区块,所以我们用 “0” 作为其前一个区块的 hash 值。

  1. public class NoobChain {
  2. public static void main(String[] args) {
  3. Block genesisBlock = new Block("Hi im the first block", "0");
  4. System.out.println("Hash for block 1 : " + genesisBlock.hash);
  5. Block secondBlock = new Block("Yo im the second block",genesisBlock.hash);
  6. System.out.println("Hash for block 2 : " + secondBlock.hash);
  7. Block thirdBlock = new Block("Hey im the third block",secondBlock.hash);
  8. System.out.println("Hash for block 3 : " + thirdBlock.hash);
  9. }
  10. }

检查区块链的完整合法性

循环链中所有的区块并比较其 hash 值

如何阻止某人篡改旧区块中的数据?

区块高度

区块高度(Block height)是指一个区块的高度是指在区块链中它和创世区块之间的块数

  1. public void mineBlock(int difficulty) {
  2. String target = new String(new char[difficulty]).replace('\0', '0'); //创建一个用 difficulty * "0" 组成的字符串
  3. while(!hash.substring( 0, difficulty).equals(target)) {
  4. nonce ++;
  5. hash = calculateHash();
  6. }
  7. System.out.println("Block Mined!!! : " + hash);
  8. }

完整代码

  1. import java.util.Date;
  2. public class Block {
  3. public String hash;
  4. public String previousHash;
  5. private String data; //我们的数据是一条简单的消息
  6. private long timeStamp; //从 1/1/1970 起至现在的总毫秒数.
  7. private int nonce;
  8. //Block 类构造方法.
  9. public Block(String data,String previousHash ) {
  10. this.data = data;
  11. this.previousHash = previousHash;
  12. this.timeStamp = new Date().getTime();
  13. this.hash = calculateHash(); //Making sure we do this after we set the other values.
  14. }
  15. //根据区块内容计算其新 hash 值
  16. public String calculateHash() {
  17. String calculatedhash = StringUtil.applySha256(
  18. previousHash +
  19. Long.toString(timeStamp) +
  20. Integer.toString(nonce) +
  21. data
  22. );
  23. return calculatedhash;
  24. }
  25. public void mineBlock(int difficulty) {
  26. String target = new String(new char[difficulty]).replace('\0', '0'); //创建一个用 difficulty * "0" 组成的字符串
  27. while(!hash.substring( 0, difficulty).equals(target)) {
  28. nonce ++;
  29. hash = calculateHash();
  30. }
  31. System.out.println("Block Mined!!! : " + hash);
  32. }
  33. }

运行

  1. import java.util.ArrayList;
  2. import com.google.gson.GsonBuilder;
  3. public class NoobChain {
  4. public static ArrayList<Block> blockchain = new ArrayList<Block>();
  5. public static int difficulty = 5;
  6. public static void main(String[] args) {
  7. //将我们的区块添加至区块链 ArrayList 中:
  8. blockchain.add(new Block("Hi im the first block", "0"));
  9. System.out.println("Trying to Mine block 1... ");
  10. blockchain.get(0).mineBlock(difficulty);
  11. blockchain.add(new Block("Yo im the second block",blockchain.get(blockchain.size()-1).hash));
  12. System.out.println("Trying to Mine block 2... ");
  13. blockchain.get(1).mineBlock(difficulty);
  14. blockchain.add(new Block("Hey im the third block",blockchain.get(blockchain.size()-1).hash));
  15. System.out.println("Trying to Mine block 3... ");
  16. blockchain.get(2).mineBlock(difficulty);
  17. System.out.println("\nBlockchain is Valid: " + isChainValid());
  18. String blockchainJson = new GsonBuilder().setPrettyPrinting().create().toJson(blockchain);
  19. System.out.println("\nThe block chain: ");
  20. System.out.println(blockchainJson);
  21. }
  22. public static Boolean isChainValid() {
  23. Block currentBlock;
  24. Block previousBlock;
  25. String hashTarget = new String(new char[difficulty]).replace('\0', '0');
  26. //循环区块链来检查 hash 值的合法性:
  27. for(int i=1; i < blockchain.size(); i++) {
  28. currentBlock = blockchain.get(i);
  29. previousBlock = blockchain.get(i-1);
  30. //比较当前区块存储的 hash 值和计算出来的 hash 值:
  31. if(!currentBlock.hash.equals(currentBlock.calculateHash()) ){
  32. System.out.println("Current Hashes not equal");
  33. return false;
  34. }
  35. //比较前一个区块存储的 hash 值和当前区块存储的 previousHash 值:
  36. if(!previousBlock.hash.equals(currentBlock.previousHash) ) {
  37. System.out.println("Previous Hashes not equal");
  38. return false;
  39. }
  40. //检查 hash 值是否已经存在
  41. if(!currentBlock.hash.substring( 0, difficulty).equals(hashTarget)) {
  42. System.out.println("This block hasn't been mined");
  43. return false;
  44. }
  45. }
  46. return true;
  47. }
  48. }

基本概念

应用层面,区块链是一个分布式的共享账本和数据库

从技术层面来看,区块链是由包含交易信息的区块按照时间顺序从后向前有序链接起来的数据结构。

image.png

区块中的交易集合记录的是一些特定的信息,在BTC网络中主要记录的是交易信息,

在其他区块链网络中可以按照业务逻辑来保存相应的业务数据,如审计信息、版权信息、票据信息等,这也是区块链经常用来当做共享账本的原因。

网络

区块链系统由多个区块链节点组成

每个节点都运行着相同一套区块链主干网络的副本

各个节点间通过P2P网络进行交互

当某一个区块链节点产生新的区块时,会通过广播的方式告诉其他节点,其他节点通过网络接收到该区块信息时,会对这个区块信息进行验证,当有一定数量的节点都验证通过后,各个节点会把该区块更新到各自现有的区块链上,最终使得整个区块链网络中的各个节点信息保持一致,这也是区块链去中心化、可信任特性的体现

image.png

分类

  • 公有链
  • 联盟链
    • 在权限管理、数据安全、监管方面更有优势
    • 由某个群体内部指定多个预选的节点为记账人
    • 其他接入节点可以参与交易,但有权限限制
    • 企业区块链技术解决方案
    • 主流的联盟链技术框架
  • 私有链

共识算法

较为主流的共识算法有PoW、PoS、DPoS、PBFT等

智能合约

从技术层面讲,智能合约是一段部署在在区块链上的程序代码,当满足程序设定的条件时,它便会在区块链上运行,并得到相应的结果。这种情况有点类似于微信的小程序,区块链提供虚拟机和脚本语言,用户根据脚本语言的语法开发带有一定业务逻辑的程序,部署在区块链上,当满足执行的条件时,智能合约便会被区块链虚拟机解释并运行。

典型的应用便是以太坊平台的智能合约,在这个平台里可以支持用户通过简单的几行代码就能实现他们想要的合约,实现无需人为监督的、不可篡改、自动化运行的合约,买卖房子不需要再找中介、借钱不需要再找公证人……人们可以随时随地根据自身需求发起合约,它的执行不依赖某个人和组织,所有的信任完全基于以太坊区块链平台本身。

技术架构

image.png
数据层
数据层是最底层的技术,主要实现了数据存储、账户信息、交易信息等模块

网络层
主要实现网络节点的连接和通讯,又称点对点技术,各个区块链节点通过网络进行通信。

共识层
是通过共识算法,让网络中的各个节点对全网所有的区块数据真实性正确性达成一致,防止出现拜占庭攻击、51攻击等区块链共识算法攻击

共识机制实现

每个节点通过网络交互,实时同步保存着同样的整条区块链数据,那么我们生成的区块,如何才能被其他节点认可,并同步添加到其他所有节点上呢,这个时候我们就需要一套规则,让所有网络节点的参与者达成能够达成共识,接纳并保存新的区块,也就是所谓的“共识机制”

工作量证明(Proof of Work),顾名思义就是对工作量的证明,在基于POW机制构建的区块链网络中,节点通过计算随机哈希散列的数值争夺记账权,求得正确的数值并生成区块的能力是节点算力的具体表现,计算的过程一般被形象地称为“挖矿”。

简单来说就是,区块链系统设定一套计算规则或者说是一套计算题,在新区块生成前,各个节点都投入到这道题的求解计算中,哪个节点先计算出结果,并得到其它节点的验证和认可,这个节点就会获得新区块的记账权,并获得系统相应的奖励,共识结束。

典型的PoW共识机制应用就是BTC网络,在BTC网络中,共识计算的目标是找到满足某个特定要求的区块Hash(哈希值)。这个区块哈希值就是工作结果的一个证明,计算工作的目的就是为了寻找到这个证明值

  1. [
  2. {
  3. "hash": "25931395e736653212f0258824df4222ae739ec2d5897310258b0857d4d3870c",
  4. "index": 1,
  5. "nonce": 1,
  6. "timestamp": 1580970554734,
  7. "transactions": [
  8. {
  9. "businessInfo": "这是创世区块",
  10. "id": "1"
  11. }
  12. ]
  13. }
  14. ]

BTC网络PoW使用的Hashcash算法,大致逻辑如下:

  1. 获取某种公开可知的数据data(BTC网络中,指的是区块头);
  2. 添加一个计数器nonce,初始值设置为0;
  3. 计算data与nonce拼接字符串的哈希值;
  4. 检查上一步的哈希值是否满足某个条件,满足则停止计算,不满足则nonce加1,然后重复第3步和第4步,直到满足这个特定的条件为止。

P2P网络

当一个节点挖矿完成后,通过P2P网络广播给其他节点,其他节点验证通过后,会把新产生的区块添加到自己的区块链上,进而保证整个区块链网络所有节点的数据一致性。

  • 创建一个基于java的p2p网络 - 运行多个节点,且多个节点通过p2p网络自动同步区块信息
    - 一个节点挖矿生成新的区块后,自动广播给其他所有节点
    - 每个节点在接收到其他节点发送的区块内容后,进行验证,验证通过添加到本地区块链上
    - 在自我节点查看整个区块链内容

验证
当一个节点收到广播内容后,对接收到的新区块进行验证,验证通过后添加到本地区块链上,验证的首要条件是新区块的高度必须比本地的区块链高度要高

参考

https://www.codenong.com/cs106604338/

https://github.com/hyperledger/fabric

https://gitee.com/luckytuan/dce-blockchain

https://gitee.com/tianyalei/md_blockchain