本系列教程的目的是帮助你了解如何开发区块链技术。在本教程中,我们将:
- 创建你的第一个非常基础的区块链。
- 实施简单的工作量证明系统(采矿)。
- 探讨任何的可能性。
我假设你对面向对象编程有基本的了解。值得注意的是,这不是一个功能齐全的生产区块链。相反,这是一个概念验证实现,可帮助你了解区块链对于未来教程中区块链的作用。
配置
我们将使用Java,但你应该能够使用任何OOP语言。我将使用Eclipse,但你可以使用任何新的花哨的文本编辑器(虽然你会错过很多好的扩展)。
你会需要:
- 安装了Java和JDK。
- Eclipse或其他IDE。
或者你可以通过谷歌获取GSON库。这将允许我们将对象转换为Json。这是一个非常有用的库,我们也将在peer2peer中使用更多的东西,但是可以随意使用替代方法。
在Eclipse中(file> new>)创建一个Java项目。我将把我的项目称为noobchain
,并使用相同的名称创建一个新类NoobChain
。
现在你就可以去试试:)
创建区块链。
区块链只是一个链/列表块。区块链中的每个区块都有自己的数字签名,包含前一个区块的数字签名,并且有一些数据(例如,这些数据可能是交易)。
哈希=数字签名。
每个块不仅包含之前块的哈希值,而且它自己的哈希部分是从前一个哈希计算的。如果前一个块的数据被改变,那么前一个块的哈希将改变(因为它部分地由数据计算),进而影响其后的块的所有哈希。计算和比较哈希值可以让我们看到区块链是否无效。
这是什么意思?...更改此列表中的任何数据,将更改签名并破坏区块链。
所以先让我们创建构成区块链的类Block:
import java.util.Date;
public class Block {
public String hash;
public String previousHash;
private String data; //our data will be a simple message.
private long timeStamp; //as number of milliseconds since 1/1/1970.
//Block Constructor.
public Block(String data,String previousHash ) {
this.data = data;
this.previousHash = previousHash;
this.timeStamp = new Date().getTime();
}
}
正如你所看到的,我们的基本块包含一个String hash
,它将保存我们的数字签名。变量previousHash
用于保存前一个块的哈希和String data
以保存我们的块数据。
接下来我们需要一种生成数字签名的方法,你可以选择许多加密算法,但SHA256
适用于此示例。我们可以import java.security.MessageDigest;
访问SHA256算法。
我们需要稍后使用SHA256
,以便在新的StringUtil
utility
类中创建一个方便的helper方法:
import java.security.MessageDigest;
public class StringUtil {
//Applies Sha256 to a string and returns the result.
public static String applySha256(String input){
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
//Applies sha256 to our input,
byte[] hash = digest.digest(input.getBytes("UTF-8"));
StringBuffer hexString = new StringBuffer(); // This will contain hash as hexidecimal
for (int i = 0; i < hash.length; i++) {
String hex = Integer.toHexString(0xff & hash[i]);
if(hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
catch(Exception e) {
throw new RuntimeException(e);
}
}
}
如果你不理解这个帮助方法的内容,不要太担心,你需要知道的是它需要一个字符串并对其应用SHA256算法,并将生成的签名作为字符串返回。
现在让我们使用我们的applySha256
helper,在Block类的新方法中计算哈希值。我们必须计算我们不想被篡改的块的所有部分的哈希值。因此,对于我们的块,我们将包括previousHash
,data
和timeStamp
。
public String calculateHash() {
String calculatedhash = StringUtil.applySha256(
previousHash +
Long.toString(timeStamp) +
data
);
return calculatedhash;
}
并让我们将此方法添加到Block构造函数中 ...
public Block(String data,String previousHash ) {
this.data = data;
this.previousHash = previousHash;
this.timeStamp = new Date().getTime();
this.hash = calculateHash(); //Making sure we do this after we set the other values.
}
一些测试时间......
在我们的主NoobChain类中,我们可以创建一些块并将哈希值打印到屏幕上,以查看所有内容是否正常工作。
让我们测试一下......第一个块称为genesis
块,因为没有先前的块,我们只需输入“0”作为前一个哈希。
public class NoobChain {
public static void main(String[] args) {
Block genesisBlock = new Block("Hi im the first block", "0");
System.out.println("Hash for block 1 : " + genesisBlock.hash);
Block secondBlock = new Block("Yo im the second block",genesisBlock.hash);
System.out.println("Hash for block 2 : " + secondBlock.hash);
Block thirdBlock = new Block("Hey im the third block",secondBlock.hash);
System.out.println("Hash for block 3 : " + thirdBlock.hash);
}
}
输出应该类似于:
你的值会有所不同,因为你的时间戳会有所不同。
每个块现在都有自己的数字签名,基于其信息和前一个块的签名。
目前它不是一个区块链,所以让我们将块存储在ArrayList
中,并导入gson
以将其视为Json
。(单击此处了解如何导入gson库)
import java.util.ArrayList;
import com.google.gson.GsonBuilder;
public class NoobChain {
public static ArrayList<Block> blockchain = new ArrayList<Block>();
public static void main(String[] args) {
//add our blocks to the blockchain ArrayList:
blockchain.add(new Block("Hi im the first block", "0"));
blockchain.add(new Block("Yo im the second block",blockchain.get(blockchain.size()-1).hash));
blockchain.add(new Block("Hey im the third block",blockchain.get(blockchain.size()-1).hash));
String blockchainJson = new GsonBuilder().setPrettyPrinting().create().toJson(blockchain);
System.out.println(blockchainJson);
}
}
现在我们的输出应该看起来更接近我们对区块链的期望。
现在我们需要一种方法来检查区块链的完整性。
让我们在NoobChain
类中创建一个isChainValid()
的布尔值方法,它将遍历链中的所有块并比较哈希值。此方法需要检查哈希变量实际上是否等于计算的哈希值,并且前一个块的哈希值等于previousHash
变量。
public static Boolean isChainValid() {
Block currentBlock;
Block previousBlock;
//loop through blockchain to check hashes:
for(int i=1; i < blockchain.size(); i++) {
currentBlock = blockchain.get(i);
previousBlock = blockchain.get(i-1);
//compare registered hash and calculated hash:
if(!currentBlock.hash.equals(currentBlock.calculateHash()) ){
System.out.println("Current Hashes not equal");
return false;
}
//compare previous hash and registered previous hash
if(!previousBlock.hash.equals(currentBlock.previousHash) ) {
System.out.println("Previous Hashes not equal");
return false;
}
}
return true;
}
对区块链块的任何更改都将导致此方法返回false
。
在比特币网络节点上共享其区块链,并且网络接受最长的有效链。什么阻止某人篡改旧块中的数据然后创建一个全新的更长的区块链并将其呈现给网络?工作量证明。工作系统的hashcash
证明意味着创建新块需要相当多的时间和计算能力。因此,攻击者需要比其他对等组合更多的计算能力。
让我们开始挖掘块!
我们将要求矿工通过在块中尝试不同的变量值来进行工作量证明,直到其哈希以一定数量的0开始。
让我们在calculateHash()
方法中添加一个名为nonce
的int
,以及非常需要的mineBlock()
方法:
import java.util.Date;
public class Block {
public String hash;
public String previousHash;
private String data; //our data will be a simple message.
private long timeStamp; //as number of milliseconds since 1/1/1970.
private int nonce;
//Block Constructor.
public Block(String data,String previousHash ) {
this.data = data;
this.previousHash = previousHash;
this.timeStamp = new Date().getTime();
this.hash = calculateHash(); //Making sure we do this after we set the other values.
}
//Calculate new hash based on blocks contents
public String calculateHash() {
String calculatedhash = StringUtil.applySha256(
previousHash +
Long.toString(timeStamp) +
Integer.toString(nonce) +
data
);
return calculatedhash;
}
public void mineBlock(int difficulty) {
String target = new String(new char[difficulty]).replace('\0', '0'); //Create a string with difficulty * "0"
while(!hash.substring( 0, difficulty).equals(target)) {
nonce ++;
hash = calculateHash();
}
System.out.println("Block Mined!!! : " + hash);
}
}
实际上,每个矿工将从随机点开始迭代。一些矿工甚至可以尝试随机数来获取随机数。另外值得注意的是,在更难的解决方案可能需要超过integer.MAX_VALUE
,矿工可以尝试更改时间戳。
mineBlock()
方法接受一个名为difficulty
的int
,这中间必须解决的数量为0的问题。在大多数计算机上几乎可以立即解决像1或2这样的低难度问题,我建议在4-6左右进行难度测试。在撰写本文时,Litecoin的难度大约是442,592。
让我们将难度作为静态变量添加到NoobChain
类:
public static int difficulty = 5;
我们应该更新NoobChain
类以触发每个新块的mineBlock()
方法。isChainValid()
布尔值还应检查每个块是否具有已解决(通过挖掘)哈希。
import java.util.ArrayList;
import com.google.gson.GsonBuilder;
public class NoobChain {
public static ArrayList<Block> blockchain = new ArrayList<Block>();
public static int difficulty = 5;
public static void main(String[] args) {
//add our blocks to the blockchain ArrayList:
blockchain.add(new Block("Hi im the first block", "0"));
System.out.println("Trying to Mine block 1... ");
blockchain.get(0).mineBlock(difficulty);
blockchain.add(new Block("Yo im the second block",blockchain.get(blockchain.size()-1).hash));
System.out.println("Trying to Mine block 2... ");
blockchain.get(1).mineBlock(difficulty);
blockchain.add(new Block("Hey im the third block",blockchain.get(blockchain.size()-1).hash));
System.out.println("Trying to Mine block 3... ");
blockchain.get(2).mineBlock(difficulty);
System.out.println("\nBlockchain is Valid: " + isChainValid());
String blockchainJson = new GsonBuilder().setPrettyPrinting().create().toJson(blockchain);
System.out.println("\nThe block chain: ");
System.out.println(blockchainJson);
}
public static Boolean isChainValid() {
Block currentBlock;
Block previousBlock;
String hashTarget = new String(new char[difficulty]).replace('\0', '0');
//loop through blockchain to check hashes:
for(int i=1; i < blockchain.size(); i++) {
currentBlock = blockchain.get(i);
previousBlock = blockchain.get(i-1);
//compare registered hash and calculated hash:
if(!currentBlock.hash.equals(currentBlock.calculateHash()) ){
System.out.println("Current Hashes not equal");
return false;
}
//compare previous hash and registered previous hash
if(!previousBlock.hash.equals(currentBlock.previousHash) ) {
System.out.println("Previous Hashes not equal");
return false;
}
//check if hash is solved
if(!currentBlock.hash.substring( 0, difficulty).equals(hashTarget)) {
System.out.println("This block hasn't been mined");
return false;
}
}
return true;
}
}
请注意,我们还检查并打印isChainValid
。
运行此结果应如下所示:
挖掘每个区块需要一些时间!(大约3秒)你应该弄乱难度值,看看这会影响挖掘每个区块的时间。
如果有人要篡改区块链系统中的数据:
- 他们的区块链无效。
- 他们无法创建更长的区块链。
- 你网络中的诚实区块链将在最长的链条上具有时间优势。
被篡改的区块链将无法赶上更长且有效的链条。
除非它们的计算速度远远超过网络中所有其他节点的总和。未来的量子计算机或其他东西。
你已经完成了基本的区块链!
你的区块链:
- 由存储数据的块组成。
- 具有将你的块链接在一起的数字签名。
- 需要工作挖掘证明来验证新块。
- 可以检查其中的数据是否有效且未更改。
你可以在Github上下载项目文件。
======================================================================
分享一些以太坊、EOS、比特币等区块链相关的交互式在线编程实战教程:
- java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
- python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。
- php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。
- 以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。
- 以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
- C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。
- EOS教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。
- java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。
- php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。
- tendermint区块链开发详解,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。
汇智网原创翻译,转载请标明出处。这里是原文使用Java创建第一个区块链
相关推荐
如何使用web3j为Java应用或Android App增加以太坊区块链支持,教程内容即涉及以太坊中的核心概念,例如账户管理包括账户的创建、钱包创建、交易转账,...以太坊是第一个实现了虚拟机的区块链,因此为智能合约 – Smart
Java-Tron是一个基于Java语言实现的TRON(波场)区块链平台的开源项目。TRON是一种去中心化的数字娱乐生态系统,旨在为全球数字娱乐内容创作者提供一个自由、高效且无成本的分发平台。Java-Tron是TRON白皮书中所描述...
- **计算机的诞生**:1946年,世界上第一台通用计算机——ENIAC诞生,标志着计算机时代的开启,同时也为数据存储技术的发展奠定了基础。 #### 数据库系统的演进 - **人工管理阶段**:在计算机早期,数据主要通过...
DuckCoinCoin 从头开始创建一个区块链生成器。 Paul Sabatier大学的面向对象编程第二年计算机科学学位项目。特征生成具有随机交易的随机区块链通过再次挖掘区块并重新计算merkle根来验证区块链的完整性将生成的...
RipeMD160是一种广泛用于创建数字指纹的哈希函数,尤其在比特币等区块链系统中有着重要应用。Java标准库并不直接支持RipeMD160,而BouncyCastle则填补了这个空白,使得开发者可以在Java项目中轻松使用这种哈希算法。...
- `indexOf()`:返回指定子字符串在字符串中的第一个出现位置。 - `trim()`:删除字符串两端的空白字符。 - `split()`:根据给定的正则表达式将字符串分割成一个数组。 - `getBytes()`:将字符串转换为字节数组...
- `clone()`方法用于创建并返回对象的一个副本,如果对象实现了`Cloneable`接口,否则会抛出`CloneNotSupportedException`。 - `finalize()`方法在垃圾回收之前被调用,用于释放资源,但不推荐直接使用,因为调用...
1. SpringCloudConfig 是一个分布式配置中心,由客户端和服务端构成,它允许在外部存储系统中管理应用的配置,支持多种存储方式如 Git 和 SVN,并非不支持 SVN。 2. Java 中的 File 类代表操作系统中的文件或目录,...
本项目“基于 FISCO-BCOS 的供应链金融 DApp(Java 应用)”就是利用 FISCO-BCOS 平台构建的一个实例,旨在展示如何将区块链技术应用于供应链金融,以提高透明度、降低风险和增强信任。 在供应链金融中,各个参与方...
做为Vapor源码解析系列的第一篇,本文首先对Vapor稍加介绍。Vapor是目前国内主流公链Bytom的高性能侧链,是从Bytom主链中发展出来的一条独立的高性能侧链。Vapor是平台最重要的区块链基础设施之一,目前采用DPoS的...
1. **后端代码**:这部分可能由多个Java源文件组成,实现了服务器端的业务逻辑,如用户认证、订单处理、钱包管理、价格计算等。 2. **数据库脚本**:SQL文件用于创建和初始化数据库结构,可能包括用户表、订单表、...
本主题围绕“程序员职场第一课”展开,涵盖了如何在IT行业中建立职业规划、提升技术能力以及应对职场挑战等多个方面。 首先,Java网络编程是程序员必须掌握的一项关键技术。Java作为一种强大的面向对象的编程语言,...
- `addJavascriptInterface()`: 创建一个Java对象并将其暴露给JavaScript环境,使JavaScript可以通过特定对象调用Android的方法。 - `WebViewClient`的`shouldOverrideUrlLoading()`: 控制页面链接的打开方式,...
第一章:少了点什么。 信任在互联网上被打破 -在互联网上,没有人知道你是一只狗你可以成为任何你想成为的人。 如果你愿意,你可以完全重新定义自己。 你不必担心其他人给你的位置。 他们不会看着你的身体做出假设。...
【标题】"EOS.rar_The First_ds18b20" 暗示了这个压缩包文件可能包含与EOS(可能是EOS.IO,一种基于区块链技术的分布式应用平台)相关的第一个项目,同时涉及到ds18b20传感器的使用。ds18b20是一款常用的数字温度...
PaaS的核心技术是分布式并行计算,例如Google AppEngine,它允许开发者使用Python和Java语言创建应用程序。 3. 软件即服务(SaaS):SaaS通过互联网提供应用程序服务,用户无需安装和维护软件,只需通过订阅模式...
在使用Spring框架进行开发时,Java程序员还可以学习到一些最佳实践,例如如何通过Hazelcast迁移Hibernate的二级缓存到Java 10,以及如何利用以太坊、web3j和SpringBoot体验区块链技术。 总的来说,Spring框架的众多...
这个名为"Create-Verify-Digital-Signatures-master.zip"的压缩包文件显然包含了一个关于如何创建和验证数字签名的项目或代码库。让我们深入探讨数字签名的概念、工作原理以及可能的应用。 数字签名并非传统的手写...
- 快速入门:简单的示例展示如何创建第一个BBoss MVCDemo应用,包括编写控制器、模型和视图。 - 请求处理:讲解BBoss MVCDemo如何处理HTTP请求,包括URL映射、参数绑定和返回值处理。 - 模型层详解:介绍如何定义...
Ethereum是一个开源的、基于区块链的分布式计算平台,其允许开发人员创建和部署去中心化的应用程序(DApps)以及智能合约。Ethereum的智能合约是一种自动执行的协议,它们在区块链上运行,确保了透明度、不可篡改性...