Blockchain demystified:

The world's most difficult database to understand
14
May

Blockchain for Java developers: How to build a blockchain in Java

The blockchain hype continues to haunt the world of technology. Meanwhile, numerous banks and software companies have also become aware of this and are trying to place corresponding products on the market. However, anyone who gains a deeper understanding and knowledge of blockchain technology will come to realize its disadvantages. Despite being regarded as a disruptive technology, it may be much more suitable for special applications rather than for the general public.

Juxtaposed to other IT technologies the blockchain is a rather inaccessible one. This is partly due to the complex underlying algorithms, but also because of the many different concepts and technologies incorporated in the blockchain. Nevertheless, the topic has entered the limelight by virtue of its direct relationship to the widespread phenomenon Bitcoin. However, in many discussions with our colleagues an impression was confirmed: the basic ideas of the blockchain were understood (distributed, public and so forth), but the concrete questions regarding the advantages and disadvantages, alternatives and concrete project opportunities could not be answered.

Blockchain’s steep learning curve is the main reason for this. It usually takes a few days on average, which are spent with a rigorous examination of the subject, until someone has roughly understood the blockchain. This lack of knowledge provides – as so often – a breeding ground for high class marketing campaigns. As a result of this, large IT companies are already offering Blockchain-as-a-Service. Banks in particular are interested in the subject and a private blockchain as a result of cooperation projects is at least under discussion. Here, we can observe parallel patterns just like the Big Data subject. This reflects particularly in the inquiries we receive in the line of: “We want to do something with Blockchain”.

First, you should be aware of what blockchain is. Blockchain is a public ledger. This means that it is a public database, in which anyone can join and leave, and also that the system can be read and written by anyone. Furthermore, the system can only be operated if many participants are prepared to invest resources in the form of computer capacities and to generate blocks (mining). That is why an incentive must be created to do so. For Bitcoin, this was a profit distribution. The network can be easily manipulated if there are too few participants on the network. And if a potential villain controls more than half of the network nodes, he is able to place incorrect information in the blockchain and omit the consistency checks in his network nodes. On the other hand, a blockchain that you run together with friends and partners misses the point.

There are enough public sources of information but many did not satisfy us and were either very superficial or too detailed. So to create a deeper understanding for developers, we therefore decided to implement a simple blockchain in Java. This helps to step outside of the conceptual discussion level and makes it possible to demonstrate the basic features of a blockchain with just a few lines of code.

 

JBlockchain: First steps

Our Java-based blockchain was kept simply deliberately and so, from a users point of view, it only has the functions of sending messages and viewing them in the blockchain, quite similar to a public chatroom. You basically have to differentiate between users (who, for example, exchange money on the Bitcoin network) and network participants who provide infrastructure, store data, and also provide communication for between the participants. Different things have to be done, which depends upon what you are: either a user or a participant. If you want to try the implementation sample then all you need to do is to clone the GitHub project and build it with Maven. Since we also need the infrastructure to communicate with other users we have to start up a node. This command here shows how it works:

java -jar node/target/node-0.0.1-SNAPSHOT.jar

You will need a private key and a public key, as well as user name to communicate with the other participants. These are required. The key and the username will provider a unique public address later on, which can identify our messages. This command here creates the pair of keys:

java -jar client/target/client-0.0.1-SNAPSHOT.jar –keypair

There are two files key.priv and key.pub. Next up is the unique public address, which must be generated:

java -jar client/target/client-0.0.1-SNAPSHOT.jar --address –-node "http://localhost:8080" --name "Max Mustermann" --publickey key.pub

This requires the address of a network node, the public key and a freely selectable name. The call returns the unique public address for the user. Check that the resource http://localhost:8080/address to see that they have been created in the system.

In order to send a message to the system these are required: The address, which was created in the previous step, and the private key. Listing 1 shows how the message “Hello World” is sent. Under the resource http://localhost:8080/transaction the message can now be viewed until the network node has written it into the actual blockchain. Fixed messages are then available at the resource under http://localhost:8080/block.

java -jar client/target/client-0.0.1-SNAPSHOT.jar --transaction --node "http://localhost:8080" --sender "Tdz0bKDfca3QjFAe5Ccuj9Noy6ah8n+R8DnZznvjic4=" --message "Hello World" --privatekey key.priv

 

Want more exclusive knowledge? Sign up now!

 

Establishing node communication

The network nodes must communicate with each other so that everyone has the same state of the blockchain. The peer-to-peer approach has established itself to ensure that this works with a large number of participants. With this approach, all network nodes have the same status and communicate with each other without a central control authority. We use a simple communication via HTTP in our example instead of the peer-to-peer approach. As soon as a network node receives new information, such as a new transaction or a new block, it then sends the information to all other network nodes (broadcast all). For example: In listing 2 the AddressController implements a method with which a new address can be added, if it does not exist already. With the optional parameter publish, the node can be instructed to inform all other nodes about the new address.

@RestController()
@RequestMapping("address")
public class AddressController {
  private final AddressService addressService;
  private final NodeService nodeService;
  
  @RequestMapping(method = RequestMethod.PUT)
  void addAddress(@RequestBody Address address, @RequestParam(required = false) Boolean publish, HttpServletResponse response) {
    if (addressService.getByHash(address.getHash()) == null) {
      addressService.add(address);
      if (publish != null && publish) {
        nodeService.broadcastPut("address", address);
      }
      response.setStatus(HttpServletResponse.SC_ACCEPTED);
    } else {
      response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
    }
  }
}

The implementation of the broadcastPut method of NodeService just sends put-requests to all known network nodes in parallel. For the sake of simplicity we deliberately assume that the nodes are always accessible and also process the requests.

public void broadcastPut(String endpoint, Object data) {
  knownNodes.parallelStream().forEach(
    node -> restTemplate.put(node.getAddress() + "/" + endpoint, data));
  }

When a network node is started, the following initial actions are performed to update the local data to the current state of the network:

  • A request from the master network node to download the following data: all nodes that the master node knows, all client addresses, the blockchain (database data) and the complete transaction pool (temporary data that has not yet been written to the blockchain)
  • Broadcast to all nodes that there is a new network node in the system

The node will be ready then and can be addressed by users.

 

Sending and verifying messages

Previously we showed how to send a message with the help of the client. Under the hood, the message is packed in a transaction (listing 3). The attribute hash forms the identifier of the transaction and is formed by hashing all attributes together. This makes it possible to uniquely identify a transaction: If the hash is the same, the content must also be the same. The message is stored in the field text and the senderHash references the unique sender address. The time of transaction creation is selected as the timestamp. The signature created in listing 4 is stored in the signature attribute.

public class Transaction {
  private byte[] hash;
  private String text;
  private byte[] senderHash;
  private long timestamp;
  private byte[] signature;
}

The signature is created from the message text and the sender’s private key. Since the private key is only known to the sender, anyone can then confirm that the message was actually sent from the address behind the senderhash.

byte[] signature = SignatureUtils.sign(text.getBytes(), Files.readAllBytes(privateKey));
Transaction transaction = new Transaction(text, senderHash, signature);

The transaction is then sent to a network node. Listing 5 shows how a transaction is accepted by the node and if it is sufficient for verification, how it enters the transaction pool. The pool is a buffer for transactions that are not yet anchored in the blockchain.

public synchronized boolean add(Transaction transaction) {
  if (verify(transaction)) {
    transactionPool.add(transaction);
    return true;
  }
  return false;
}

The verify-method in listing 6 first checks whether the sender of the transaction is known at all. At the address, the public key is accessible to everyone, so that the authenticity of the message can be confirmed together with the message text (getSignableData) and the signature. Finally, the system checks whether the transmitted hash of the transaction was calculated correctly.

private boolean verify(Transaction transaction) {
  // known address
  Address sender = addressService.getByHash(transaction.getSenderHash());
  if (sender == null) {
    return false;
  }
  // correct signature
  if (!SignatureUtils.verify(transaction.getSignableData(), transaction.getSignature(), sender.getPublicKey())) {
    return false;
  }
  // correct hash
  if (!Arrays.equals(transaction.getHash(), transaction.calculateHash())) {
    return false;
  }
  return true;
}

 

Transaction pool and mining

The messages would be stored in a relational database via an INSERT. Transaction properties (ACID) and transaction level (READ UNCOMMITTED or READ COMMITTED) ensure that parallel write and read accesses meet certain requirements and define how secure they should be. In this way, a transaction is opened before the INSERT and, if no errors occur, written into the database using a COMMIT.

Since the data is not stored centrally in the blockchain, but a copy of all data is stored on any number of network nodes and any number of users want to store data in parallel, we need a different mechanism to obtain transaction security. This is where the transaction pool and mining come in. There are basically two areas in the blockchain in which data resides. On the one hand, this is the transaction pool in which the data still to be written is located, and on the other hand the blockchain itself with the data no longer to be changed (fig. 1). To prevent the network nodes from writing transactions into the blockchain at the same time, we need to overcome a mathematical challenge. You take any freely selectable transactions from the transaction pool and generate a hash from them. This hash must now begin with one, two, or three zeros, depending on the level of difficulty.

 

Fig. 1: The two areas of the blockchain where data resides: the transaction pool and the blockchain itself 

 

The difficulty depends upon how much mining capacity is actually available. Simply put: Few network nodes mean that there is a small number of zeros, many network nodes mean that there is a large number of zeros. Here it is the goal that a suitable hash is only found after a certain amount of time, e.g. every five minutes. Listing 7 shows how a suitable block is searched for by using a brute force method. A new block object is constructed, so long as the miner is active. The miner references the last block, which is already anchored in the blockchain and contains the previously selected transactions. In addition, each block has the attribute tries, which is a freely definable number and which is also used in the calculation of the block hash. If the hash of the newly created block does not have enough leading zeros, then tries is simply increased by one and a new block is created.

long tries = 0;
while (runMiner.get()) { // atomicBoolean for controlling from other threads
  Block block = new Block(previousBlockHash, transactions, tries);
  if (block.getLeadingZerosCount() >= Config.DIFFICULTY) {
    return block;
  }
  tries++;
}

 

Current limitations and expansion options

The JBlockchain implementation is kept very simple, because the understanding of the technology should be the main focus here. Many concepts are missing for a productive usage. Here are some examples:

  • The all-broadcast does not scale for a large number of network nodes. Here we have need for a smarter message distribution.
  • At least some master nodes must exist in the network (for example: statically stored) to which the users can connect.
  • The naive consideration of a distributed system without concurrences, message loss etc. will quickly lead to problems. This could be solved with a framework which is specially tailored for this area, e.g. Atomix.
  • In general, it should be considered whether the peer-to-peer component should be replaced by a framework such as GNUnet.
  • The mathematical challenge grows along with the number of network nodes. This is currently configured statically.
  • The purpose of the application would have to be specified in more detail, because this could result in additional requirements. For example: the transactions may not be combined into a block, but certain transactions are of higher priority (e.g. according to date of receipt).

 

Conclusion

The blockchain is a highly interesting and exciting technology which will be with us for a long time. However, we dare to doubt that it will change the world. At least, not in its current form. It is much more likely that certain parts will be reused in other forms or used for marketing purposes. A decision maker would also have a lot to put up with when it comes to the subject of concrete projects: Little control over the number of participants, high fluctuation of participants, complex programming model, difficult connection of external interfaces as well as incentives and marketing must be created for the system. These points make a realistic assessment of a project very difficult, as most companies expect reliable figures and a concrete result. If you are prepared to accept these challenges, you get the advantages of a highly available, scalable database without a central control point and thus without your own hardware costs.


STAY TUNED!

BEHIND THE TRACKS

Blockchain Advanced Development

Advanced step-by-step technical guide: Sharing the know-how

Blockchain Impact & Strategy

Experimenting with blockchain technology: Real-world inspiring use cases

Blockchain Technology 101

Principles, tools–frameworks & libraries–and implementation