Why is it difficult to modify records in a Blockchain?

Blockchain works in a peer to peer network and every new transaction is broadcast to all the nodes so that any one of the nodes could mine it. The process of mining a block involves predicting a nonce value that could satisfy the difficulty level.

What does “difficulty” mean in blockchain?

Difficulty is the relative measure of how difficult it is to find a new block. The difficulty is adjusted periodically as a function of how much hashing power has been deployed by the network of miners.

How is a blockchain validated

  • Every block must satisfy the difficulty criteria (proof of work).
  • Every block must contain the hash value of the previous block and it should match with the previous block’s hash.

An example could better help us understand this

Let’s say we have the blockchain of length 6, where the hashing algorithm used is SHA-256 and a difficulty of 5 (hash beginning with 5 zeros as a proof of work)

Previous Block's hash                                               Timestamp     Nonce      Transaction Data 
5FECEB66FFC86F38D952786C6D696C79C2DBC239DD4E91B46729D73A27FB57E9    1527990931106 0525170    Block 1 
00000F7500C1AACC0A1316BDA465407D15A0177231929C15FCE54DE944B65742    1527990931107 0070121    Block 2 
000001DF83C3C9BA681A89DA3D2F3D346895109E7B4E6E9767E04BA19996BE3F    1527990931107 3632550    Block 3 
000009A057133D6F8DD724B712C31C25EF0703E87C825EACCB01122D4FF1842E    1527990931107 0820089    Block 4 
00000D7EEE3583BA18D68990281069C76381DA9B5475EB41E872796A13FBB384    1527990931107 0660226    Block 5 
000003AA70B03F4F25D468C8A7B13ED8483B419BB6503BE8B25CB14DCC2855F8    1527990931107 0031723    Block 6

let’s try changing the transaction data for the 3rd block from Block 3 to Block 33. Now that the block data has been modified, the chain becomes invalid because when the validation check is performed, the hash generated by this block will not satisfy the difficulty and will not match with the next block's previousHash value.

The following is the method used to calculate the hash

public String getHash() throws NoSuchAlgorithmException { 
  return CryptoHelper.sha256(transactionData + String.valueOf(timestamp) 
    + String.valueOf(previousBlockHash) 
    + String.valueOf(nonce));
}

The hash is calculated by appending transactionData, timestamp, previousBlockHash, nonce and applying SHA-256 on the resultant string

This is the resultant string if we append the data for block 3

Block 331527990931107000001DF83C3C9BA681A89DA3D2F3D346895109E7B4E6E9767E04BA19996BE3F3632550

and the SHA-256 hash for the above string is

BD5370EB390348AA71C25C65E700E36E81BA370C665C6398BAEF7C8843C0A1C2

Obviously it doesn't satisfy the difficulty criteria as it doesn't start with 5 zeros, hence the nonce value needs to be recalculated. I have written this java console application that helps us calculate the nonce by bruteforce.

public class HashBreaker { 
  public static void main(String[] args) throws NoSuchAlgorithmException { 
    var scanner = new Scanner(System.in); 
    System.out.println("Nonce Finder"); 
    System.out.print("Message : "); 
    String message = scanner.nextLine(); 
    System.out.print("Difficulty : "); 
    int d = scanner.nextInt(); 
    System.out.println("\nCalculating..."); 
    long startTime = System.currentTimeMillis(); 
    long nonce = bruteforce(d, message); 
    long endTime = System.currentTimeMillis(); 
    System.out.println("\nValid Nonce : " + nonce); 
    System.out.println("Hash : " + sha256(message + String.valueOf(nonce))); 
    System.out.println("Time taken : " + (endTime - startTime)/1000 + " seconds"); 
    scanner.close(); 
  } 

  public static String sha256(String text) throws NoSuchAlgorithmException { 
    MessageDigest digest = MessageDigest.getInstance("SHA-256"); 
    digest.update(text.getBytes(StandardCharsets.UTF_8)); 
    byte[] hash = digest.digest(); 
    StringBuffer sb = new StringBuffer(); 
    for (int i = 0; i < hash.length; i++) sb.append(Integer.toString((hash[i] & 0xff) + 0x100, 16).substring(1)); 
    return sb.toString().toUpperCase(); 
  } 

  public static long bruteforce(int d, String s) throws NoSuchAlgorithmException { 
    long nonce = 0; 
    String pre = ""; 
    for (; pre.length()<d; pre += "0"); 
    while (!sha256(s + String.valueOf(nonce)).startsWith(pre)){ 
      nonce++; 
    } 
    return nonce; 
  }
}

Note that the message shouldn’t contain the nonce value as that’s what we are trying to calculate. We have found that the nonce value 125107 satisfies the difficulty criteria, great let’s see how our modified chain looks like

$ java HashBreaker 

Nonce Finder 
Message : Block 331527990931107000001DF83C3C9BA681A89DA3D2F3D346895109E7B4E6E9767E04BA19996BE3F 
Difficulty : 5 

Calculating... 

Valid Nonce : 125107 
Hash : 00000277418AFAF4F19430EDE51B573FAE4C3DCB13B20352A43778802DF0E12F 
Time taken : 0.945 seconds

since block 3 has been modified, the previous hash value contained in block 4 000009A057133D6F8DD724B712C31C25EF0703E87C825EACCB01122D4FF1842E doesn't match with the third block's hash 00000277418AFAF4F19430EDE51B573FAE4C3DCB13B20352A43778802DF0E12F.

To correct the chain, the previous hash value in block 4 needs to be set to the current hash of block 3, so it will become

00000277418AFAF4F19430EDE51B573FAE4C3DCB13B20352A43778802DF0E12F 1527990931107 820089 Block 4

and the current hash for block 4 becomes

DAFC46D52C86324421121FC99BEB1E6D7215C6DA288CF0600034F60995477A09

which doesn’t satisfy the difficulty criteria and the nonce value has to be recalculated

$ java HashBreaker 

Nonce Finder 
Message : Block 4152799093110700000277418AFAF4F19430EDE51B573FAE4C3DCB13B20352A43778802DF0E12F 
Difficulty : 5 

Calculating... 

Valid Nonce : 691412 
Hash : 00000FDAD0C18DB1C15980029F94D6C37DE8B316FF531B9E7ACA233EC95545CE 
Time taken : 2.86 seconds

With the new nonce, the 4th block becomes

00000277418AFAF4F19430EDE51B573FAE4C3DCB13B20352A43778802DF0E12F    1527990931107 691412    Block 4

The same happens with the remaining blocks and their nonces should also be recalculated. As we have observed the blockchain is similar in analogy to dominoes where each block can be thought of as a domino, .

once a block is disturbed, all the consecutive blocks also get affected

What’s the big deal?

You might be wondering, what’s the big deal with recalculating hashes. After all, with some recalculations and time you can modify the chain right?

There are a few things to consider

  • The longest proof of work chain will be accepted as the correct chain by the P2P network.
  • For the sake of simplicity, we have used tiny difficulty values and a relatively less complex algorithm, but in actual implementations, the difficulty value is quite huge and also the hashing algorithms are much more complex which makes it much harder and time consuming to recalculate the nonce values.

Graph showing changes in relative difficulty for bitcoin. Source: https://blockchain.info

  • Every second, many transactions are broadcast across the network and the node that calculates the nonce value for a transaction first becomes the node having the longest proof of work chain. In such a competitive environment, tampering with the chain is computationally tedious.

Source code for the sample blockchain can be found here The java source code for bruteforcing nonce values can be found here

No Comments Yet