本文目录:
本文目录:
1、区块链技术常见架构 2、基于java的区块链系统开发 (1)开发环境 (2)区块链模型构建 (3)共识机制实现 (4)P2P网络开发 (5)系统测试 3、源代码与参考文献 (1)本文完整源代码地址 (2)参考书籍 (3)参考资料
1、区块链技术常见架构
目前主流的区块链技术架构主要分为五层:
数据层是最底层的技术,主要实现了数据存储、账户信息、交易信息等模块,数据存储主要基于Merkle树,通过区块的方式和链式结构实现,而账户和交易基于数字签名、哈希函数和非对称加密技术等多种密码学算法和技术,来保证区块链中数据的安全性。
网络层主要实现网络节点的连接和通讯,又称点对点技术,各个区块链节点通过网络进行通信。共识层是通过共识算法,让网络中的各个节点对全网所有的区块数据真实性正确性达成一致,防止出现拜占庭攻击、51攻击等区块链共识算法攻击。
激励层主要是实现区块链代币的发行和分配机制,是公有链的范畴,我们不做分析。应用层一般把区块链系统作为一个平台,在平台之上实现一些去中心化的应用程序或者智能合约,平台提供运行这些应用的虚拟机。
接下来我们基于Java语言来开发一套小型的区块链系统,来实现数据层、网络层、共识层的一些功能,用简单的代码来直观抽象的概念,以便加深对区块链技术基础理论的理解。
2、基于java的区块链系统开发
(1)开发环境
开发工具 | VSCode |
---|---|
开发语言 | Java |
JDK版本 | JDK1.8或者OpenJDK11 |
开发框架 | SpringBoot2.2.1 |
工程管理 | Maven3.6 |
测试工具 | Postman |
(2)区块链模型构建
区块是区块链系统的最小单元,第一步我们先实现最简单的区块结构,新建Block.java类,主要包含以下几个字段:Block.java
/**
* 区块结构
*
* @author Jared Jia
*
*/
public class Block implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 区块索引号(区块高度)
*/
private int index;
/**
* 当前区块的hash值,区块唯一标识
*/
private String hash;
/**
* 前一个区块的hash值
*/
private String previousHash;
/**
* 生成区块的时间戳
*/
private long timestamp;
/**
* 工作量证明,计算正确hash值的次数
*/
private int nonce;
/**
* 当前区块存储的业务数据集合(例如转账交易信息、票据信息、合同信息等)
*/
private List<Transaction> transactions;
/*** 省略get set方法****/
}
第二步,创建一个链式结构对象,按照先后顺序来保存区块对象,从来形成一个有序的区块链表,考虑到线程安全问题,采用CopyOnWriteArrayList来实现,为了方便测试,暂且把区块链结构保存在本地缓存中,实际的区块链网络最终会实现持久层的功能,把区块链数据保存至数据库中:BlockCache.java
public class BlockCache {
/**
* 当前节点的区块链结构
*/
private List<Block> blockChain = new CopyOnWriteArrayList<Block>();
public List<Block> getBlockChain() {
return blockChain;
}
public void setBlockChain(List<Block> blockChain) {
this.blockChain = blockChain;
}
}
第三步,有了区块链结构后,需要新增向区块链中添加区块的方法,同时区块链中必须有个创世区块,我们直接通过硬编码实现:BlockService.java
/**
* 区块链核心服务
*
* @author Jared Jia
*
*/
@Service
public class BlockService {
@Autowired
BlockCache blockCache;
/**
* 创建创世区块
* @return
*/
public String createGenesisBlock() {
Block genesisBlock = new Block();
//设置创世区块高度为1
genesisBlock.setIndex(1);
genesisBlock.setTimestamp(System.currentTimeMillis());
genesisBlock.setNonce(1);
//封装业务数据
List<Transaction> tsaList = new ArrayList<Transaction>();
Transaction tsa = new Transaction();
tsa.setId("1");
tsa.setBusinessInfo("这是创世区块");
tsaList.add(tsa);
Transaction tsa2 = new Transaction();
tsa2.setId("2");
tsa2.setBusinessInfo("区块链高度为:1");
tsaList.add(tsa2);
genesisBlock.setTransactions(tsaList);
//设置创世区块的hash值
genesisBlock.setHash(calculateHash("",tsaList,1));
//添加到已打包保存的业务数据集合中
blockCache.getPackedTransactions().addAll(tsaList);
//添加到区块链中
blockCache.getBlockChain().add(genesisBlock);
return JSON.toJSONString(genesisBlock);
}
}
以上关键代码实现之后,我们就构建了一个非常简单的区块链模型,包含一个基本的区块模型和一个区块链模型,并且能够生成新的区块并添加到区块链中。
(3)共识机制实现
共识机制有很多种,各有各的优势与缺点,接下来我们就用java代码来模拟实现我们最为熟知的一种机制:工作量证明(Proof of Work),顾名思义就是对工作量的证明,计算的过程一般被形象地称为“挖矿”。
BTC网络PoW使用的Hashcash算法,大致逻辑如下:
获取某种公开可知的数据data(BTC网络中,指的是区块头);
添加一个计数器nonce,初始值设置为0;
计算data与nonce拼接字符串的哈希值;
检查上一步的哈希值是否满足某个条件,满足则停止计算,不满足则nonce加1,然后重复第3步和第4步,直到满足这个特定的条件为止。
接下来我们用Java代码实现这个算法,设定满足的特定条件为,Hash值前4位都是0,则计算成功。
第一步,我们新建一个共识机制服务类,添加一个“挖矿”方法,计算成功后,获取记账权,调用添加区块的方法,把区块添加到区块链中:PowService.java
/**
* 共识机制
* 采用POW即工作量证明实现共识
* @author Administrator
*
*/
@Service
public class PowService {
@Autowired
BlockCache blockCache;
@Autowired
BlockService blockService;
/**
* 通过“挖矿”进行工作量证明,实现节点间的共识
*
* @return
*/
public Block mine(){
// 封装业务数据集合,记录区块产生的节点信息,临时硬编码实现
List<Transaction> tsaList = new ArrayList<Transaction>();
Transaction tsa1 = new Transaction();
tsa1.setId("1");
tsa1.setBusinessInfo("这是IP为:"+CommonUtil.getLocalIp()+",端口号为:"+blockCache.getP2pport()+"的节点挖矿生成的区块");
tsaList.add(tsa1);
Transaction tsa2 = new Transaction();
tsa2.setId("2");
tsa2.setBusinessInfo("区块链高度为:"+(blockCache.getLatestBlock().getIndex()+1));
tsaList.add(tsa2);
// 定义每次哈希函数的结果
String newBlockHash = "";
int nonce = 0;
long start = System.currentTimeMillis();
System.out.println("开始挖矿");
while (true) {
// 计算新区块hash值
newBlockHash = blockService.calculateHash(blockCache.getLatestBlock().getHash(), tsaList, nonce);
// 校验hash值
if (blockService.isValidHash(newBlockHash)) {
System.out.println("挖矿完成,正确的hash值:" + newBlockHash);
System.out.println("挖矿耗费时间:" + (System.currentTimeMillis() - start) + "ms");
break;
}
System.out.println("第"+(nonce+1)+"次尝试计算的hash值:" + newBlockHash);
nonce++;
}
// 创建新的区块
Block block = blockService.createNewBlock(nonce, blockCache.getLatestBlock().getHash(), newBlockHash, tsaList);
return block;
}
}
第二步,编写测试共识机制服务的Controller类方法:BlockController.java
/**
* 工作量证明PoW
* 挖矿生成新的区块
*/
@GetMapping("/mine")
@ResponseBody
public String createNewBlock() {
powService.mine();
return JSON.toJSONString(blockCache.getBlockChain());
}
第三步,启动系统,进行测试。首先执行http://localhost:8080/create方法,生成创世区块。其次调用http://localhost:8080/mine方法进行工作量计算证明,生成新的区块,并添加到本地区块链中:
我们来看一下,系统后台计算的过程,此次计算共花费1048ms计算出满足条件的Hash值,共计算4850次:
至此,我们实现了一个简单的工作量证明机制,并在当前区块链系统节点上运行,完成了正确结果的计算,生成了一个新的区块。
(4)P2P网络开发
前几步中区块链节点的维护都是基于单节点的运行,实际的区块链是有多个节点同时运行的分布式网络系统,所有节点同时计算抢夺记账权,共同维护一条完整的区块链。
接下来我们基于Java的WebSocket实现一个Peer-to-Peer网络,实现多个节点间的相互通信,通过本章节,我们将要实现以下功能:
- 创建一个基于java的p2p网络
- 运行多个节点,且多个节点通过p2p网络自动同步区块信息
- 一个节点挖矿生成新的区块后,自动广播给其他所有节点