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