- Blockchain Implementation With Java Code
- Originally written by David Pitt
- The Nuggets translation Project
- Permanent link to this article: github.com/xitu/gold-m…
- Translator: Starrier
- Proofread: Sisibeloved
Implement blockchain with Java code
Let’s look at the possibilities of implementing blockchain with Java code. We started with the basics and developed some code to demonstrate how they fit together.
Bitcoin is hot — what an understatement. While the future of digital cryptocurrencies is unclear, blockchain — the technology used to drive Bitcoin — is very popular.
The application field of blockchain is not yet explored. It also has the potential to undermine enterprise automation. There’s a lot of information available about how blockchain works. We have a free white paper for deep blockchain (no registration required).
This article will focus on the blockchain architecture, particularly with simple code examples to demonstrate how an “immutable, append only” distributed ledger works.
As a developer, reading code is easier to understand than reading technical articles. At least for me. So let’s get started!
Brief introduction to blockchain
First let’s briefly summarize blockchain. A block contains some header information and any set of data types or set of transactions. The chain begins with the first (initial) block. As transactions are added/extended, new blocks are created based on how many transactions can be stored in the block.
When the block threshold size is exceeded, a new transaction block is created. The new block is connected to the previous block, so it is called a blockchain.
immutability
Because sha-256 hashes are computed for transactions, the blockchain is immutable. The contents of the blockchain are also hashed to provide a unique identifier. In addition, the hash of the contiguous previous block is hashed and stored in the block header.
That’s why trying to tamper with blocks is basically impossible, at least with current computing power. The following is a partial definition of a Java class that shows block properties.
. public class Block< T extends Tx>; { public long timeStamp; private int index; private List<T> transactions = new ArrayList<T>(); private Stringhash;
private String previousHash;
private String merkleRoot;
private String nonce = "0000"; Public Map<String,T> Map = new HashMap<String,T>(); .Copy the code
Notice that the injected generic type is of type Tx. This allows the transaction data to change. In addition, the previousHash attribute references the hash value of the previous block. The merkleRoot and nonce attributes are described later.
Block hash value
Each block can compute a hash. This is actually a hash of all the block attributes linked together, including the hash of the previous block and the SHA-256 hash computed from it.
Below are the methods defined in the block. Java class to evaluate a hash.
. public voidcomputeHash() { Gson parser = new Gson(); String serializedData = Parser. toJson(transactions);setHash(SHA256.generateHash(timeStamp + index + merkleRoot + serializedData + nonce + previousHash)); }...Copy the code
The transaction is serialized as a JSON string, so it can be appended to a block attribute before being hashed.
chain
Blockchains manage blocks by accepting transactions. When a predetermined threshold is reached, a block is created. Here is a partial implementation of Simpleblockchain.java:
. . public class SimpleBlockchain<T extends Tx> { public static final int BLOCK_SIZE = 10; public List<Block<T>> chain = new ArrayList<Block<T>>(); publicSimpleBlockchain() {// create initial block chain.add(newBlock()); }...Copy the code
Note that the chain property maintains a list of blocks of type Tx. In addition, the no-parameter constructor initializes the “initial” block when the initial list is created. Here is the source code for the newBlock() method.
. 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);
returnblock; }...Copy the code
This method will create a new block instance, generate the appropriate value, allocate the hash of the previous block (which will be the hash of the header), and return the instance.
Before adding blocks to the chain, blocks can be verified by comparing the previous hash of the new block to the last block (head) of the chain to ensure they match. Simpleblockchain.java describes this process.
. Public void addAndValidateBlock(Block<T> Block) {// Compare the previous Block hash, if valid add 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); }...Copy the code
The entire blockchain is verified by cycling through the chain, ensuring that the hash of the block still matches the hash of the previous block.
The following is an implementation of the Simpleblockchain.java Validate () method.
. public booleanvalidate() {
String previousHash = null;
for (Block<T> block : chain) {
String currentHash = block.getHash();
if(! currentHash.equals(previousHash)) {return false;
}
previousHash = currentHash;
}
return true; }...Copy the code
As you can see, trying to fake transaction data or any other attribute in any way is very difficult. And, as the chain grows, it continues to become very, very, very difficult, basically impossible — unless a quantum computer is available!
Add trading
Another important technical aspect of blockchain technology is that it is distributed. The accretive nature of the blockchain helps it replicate well between nodes in the blockchain network. Nodes usually communicate in a peer-to-peer manner, as bitcoin does, but it doesn’t have to be that way. Other blockchain implementations use a decentralized approach, such as using AN API based on the HTTP protocol. That’s all beside the point.
A deal can mean anything. Transactions can contain code to execute (for example, smart contracts) or store and append information about a business transaction.
Smart contract: Computer agreements designed to facilitate, validate, or enforce contract negotiation and performance in digital form.
In the case of Bitcoin, transactions consist of amounts in the owner’s account and amounts in other accounts (for example, transferring bitcoin amounts between accounts). The transaction also includes a public key and an account ID, so the transfer needs to be secure. But that’s unique to Bitcoin.
Transactions are added to the network and pooled; They are not in the block or the chain itself.
This is where the blockchain consensus mechanism comes into play. There are many proven consensus algorithms and patterns, but that is beyond the scope of this article.
Mining is the consensus mechanism used by the Bitcoin blockchain. This is the type of consensus discussed below. The consensus mechanism collects transactions, uses them to build a block, and then adds that block to the chain. The blockchain validates a new transaction block before it is added.
Ms merkel tree
The transaction is hashed and added to the block. Merkle trees are used to compute merkle root hashes. Merkle tree is a balanced binary tree in which the values of the internal nodes are the hashes of the values of two child nodes. Merkelgen is the root of the Merkelgen tree.
This tree is used for validation of block transactions. If you change some information during a transaction, the Merkelroot will become invalid. In addition, they can speed up the transfer of blocks in a distributed manner, as the structure only allows for the addition and validation of a single transaction hash branch required for the entire transaction block.
The following is a method in the block. Java class that creates a Merkle tree from the list of transactions.
. public List<String>merkleTree() { ArrayList<String> tree = new ArrayList<>(); // First, // add the hashes of all transactions to the tree as leaf nodes.for(T t : transactions) { tree.add(t.hash()); } int levelOffset = 0; // The offset in the list currently being processed. // The offset of the first node in the current hierarchy in the entire list. // After each layer of increment, // stop when we reach the root node (levelSize == 1).for(int levelSize = transactions.size(); levelSize > 1; LevelSize = (levelSize + 1) / 2) {// For each pair of nodes on this level:for(int left = 0; left < levelSize; Left += 2) {// If we do not have enough transactions, // right and left nodes // can be the same. 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 levelOffset += levelSize; }returntree; }...Copy the code
This method is used to calculate the Merkel roots of the block. The project is accompanied by a Merkle tree unit test, which attempts to add transactions to a block and verify that the merkle root has changed. Here is the source code for the unit test.
. @Test public voidmerkleTreeTestSimpleBlockchain<Transaction> chain1 = new SimpleBlockchain<Transaction>(); chain1.add(new Transaction("A")).add(new Transaction("B")).add(new Transaction("C")).add(new Transaction("D")); <Transaction> Block = chain1.gethead (); System.out.println("Merkle Hash tree :"+ block.merkleTree()); Transaction tx = block.getTransactions().get(0); // Check if block transactions are valid, they should be block.transasctionsValid(); assertTrue(block.transasctionsValid()); // Change the transaction data tx.setValue("Z"); // Blocks should not be valid when the merkle root of a block does not match the calculated Merkle tree. assertFalse(block.transasctionsValid()); }...Copy the code
This unit test simulates validating a transaction and then changing the transaction in the block by means other than the consensus mechanism, for example if someone tries to change the transaction data.
Remember that blockchains are additive only, and when block chain data structures are shared between nodes, block data structures (including Merkle roots) are hashed and connected to other blocks. All nodes can validate new blocks, and existing blocks can easily be proven valid. Therefore, if a miner wants to add a fake block or node to adjust the original transaction, it is not possible.
Mining and proof of work
In the Bitcoin world, the process of grouping transactions into blocks and submitting them to members of the chain for verification is called “mining.”
More broadly, in blockchain, this is called consensus. There are several proven distributed consensus algorithms, depending on whether you have a public or private blockchain. Our white paper describes this in more depth, but this article focuses on the principles of blockchain, so in this example we will use a proof-of-work (POW) consensus mechanism.
Thus, the mining node will listen for transactions executed by the blockchain and perform a simple mathematical task. The task is to generate a block hash with a string of values starting with 0 using a random one-time number (nonce) that keeps changing until a default hash value is found.
The Java sample project has a Miner. Java class with the “proofOfWork” (Block Block) method implementation shown below.
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;
}
Copy the code
Again, this is simplified, but once a certain amount of transactions are received, the mining algorithm computes a proof-of-work hash for the block. The algorithm simply loops and creates a sha-256 hash of the block until a leading numeric hash is generated.
This can take a lot of time, which is why specific GPU microprocessors have been implemented to execute and solve this problem as quickly as possible.
Unit testing
You can see JUnit tests that combine these concepts with Java examples on GitHub.
Run it and see how this simple blockchain works.
Also, if you’re a C# programmer, there are examples written in C# (I won’t tell anyone). Below is an example of a C# blockchain implementation.
Final thoughts
Hopefully this article will give you some understanding of blockchain technology and enough interest to continue your research.
All of the examples presented in this article are used in our deep blockchain white paper (no registration required to read). These examples are explained in greater detail in the white paper.
Also, if you want to see the full blockchain implementation in Java, here’s a link to the open source project BitcoinJ. You can see the above concepts in practice.
If so, I recommend that you look at an open source blockchain framework that is closer to production. A good example is HyperLedger Fabric, which will be the subject of my next post – stay tuned!
The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.