Hi All ,

 

Welcome to all of you in my blog, this post is all about basic blockchain and how it works actually. I came across lots of blogs (not in sap) where people discussed lots about blockchain, the funny one was how i explained blockchain to my grandma’. But i always wonder what it means to developer like me, how can we implement blockchain from scratch no more api’s lets build everything from scratch. Before jumping into code i would like to explain some core technical concept which is very important.

Blockchains

A distributed database that maintains a continuously growing list (Blocks) of ordered which can be read by anyone. Nothing special, but they have an interesting property means to add any block into blockchain block has to satisfy some property: they are immutable. Once a block has been added to the chain, it cannot be changed anymore without invalidating the rest of the chain.

And this is one of the reason why all cryptocurrencies are like Bitcoin ,Ethereum, Litecoin etc are based on blockchain. Because no one want to change their previous transaction which they have already made.

Block Structure

As a blockchain developer first most important task is to decide structure of block. In our example we will keep it very simple and which are most necessary component: index, timestamp, data, hash and previous hash. Now all components are self explanatory . Index is nothing but Block index , Timestamp means committed time for that  particular when it got added to blockchain, hash is SHA256 Hash value for that particular block , Previous hash is SHA256 Hash value for Previous Block.

Hello Block’ Hana Xs Blockchain Proof of Work ApplicationThe hash of the previous block should be present  in the block to form a valid chain or preserve the integrity .

 

Genesis Block

Genesis block is nothing but first block in blockchain , it is basically dummy block to start the blockchain , in Bitcoin Blockchain the value of genesis block is 0. Mostly software developer hard code it to utilize the blockchain.

Block Hash

To keep the integrity of blockchain all Block need to be hashed in SHA256. Those who are not familiar with SHA256 Hash , its encryption function like MD5 and SHA1 and once you encrypt any plain text using this , there is no chance to get it back in normal form.

Adding Block

To add  a block in blockchain we should know the hash of the previous block and create the rest of the required content (= index, hash, data and timestamp). Block data will be provided by end user .

 

‘Talk is cheap. Show me the code.’ -Linus Torvalds

Lets Look at the stuff , which  makes actual sense for developers . I have used Sap Cloud Platform Developer (trial) account and used MDC Hana trial to build whole demo . If you haven’t used MDC hana trial in your Sap Cloud Platform trial account Please have look at MDC trial Setup in SCP. Sap tutorial provides cool guide for that .

Defining Block Structure

First i have defined a schema called ‘HELLOBLOCK’. My design time artifact or schema.hdbschema file look like .

schema_name = "HELLOBLOCK";

Then i have created a column table called Blockchain with all necessary fields . My entity.hdbdd look like .

namespace HelloBlock.DBARTIFACT; @Schema: 'HELLOBLOCK' context entity { @Catalog.tableType: #COLUMN Entity BlockChain{ key index : Integer; data : LargeString; commit_at : UTCTimestamp; previous_hash : LargeString; current_hash: LargeString; };

 

Adding Block in Blockchain

I have created a simple procedure to insert entry in blockchain table which will be called from xsjs based on validation of  block .

procedure code :

PROCEDURE "HELLOBLOCK"."HelloBlock.Procedure::InsertBlock" ( IN block_index Integer, IN block_data Nclob, IN block_commit TIMESTAMP, IN prevblock_hash Nclob, IN Currblock_hash Nclob ) LANGUAGE SQLSCRIPT SQL SECURITY INVOKER AS --DEFAULT SCHEMA  -- READS SQL DATA AS BEGIN /************************************* Write your procedure logic *************************************/ INSERT INTO "HELLOBLOCK"."HelloBlock.DBARTIFACT::entity.BlockChain"("index","data","commit_at","previous_hash","current_hash") VALUES (:block_index,:block_data,:block_commit,:prevblock_hash,:Currblock_hash); END

Hana xsjs service to add block in blockchain .

var acmd = $.request.parameters.get("action"); var BlockData = $.request.parameters.get("data"); var BlockIndex = $.request.parameters.get("index"); var PrevBlockHash = $.request.parameters.get("prevhash"); function DisplayBlockChain() { try { var conn = $.db.getConnection(); var output = { results: [] }; var query = 'select * from "HELLOBLOCK"."HelloBlock.DBARTIFACT::entity.BlockChain"'; var myStatement = conn.prepareStatement(query); var rs = myStatement.executeQuery(); while (rs.next()) { var record = {}; record.Index = rs.getInteger(1); record.Data = rs.getNClob(2); record.CommitedTime = rs.getString(3); record.PrevBlockHash = rs.getNClob(4); record.CurrentHash = rs.getNClob(5); output.results.push(record); } rs.close(); myStatement.close(); conn.close(); } catch (e) { $.response.status = $.net.http.INTERNAL_SERVER_ERROR; $.response.setBody(e.message); return; } var body = JSON.stringify(output); $.response.contentType = 'application/json'; $.response.setBody(body); $.response.status = $.net.http.OK; } function CurrentTImeStamp() { var date = new Date(); var utcout = date.getFullYear() + '-' + ('0' + (date.getMonth() + 1)).slice(-2) + '-' + ('0' + date.getDate()).slice(-2) + 'T' + ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2) + ':' + ('0' + date.getSeconds()).slice(-2); return (utcout); } function CalculateHash(s) { var chrsz = 8; var hexcase = 0; function safe_add(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } function S(X, n) { return (X >>> n) | (X << (32 - n)); } function R(X, n) { return (X >>> n); } function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); } function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); } function Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); } function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); } function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); } function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); } function core_sha256(m, l) { var K = new Array(0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2); var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19); var W = new Array(64); var a, b, c, d, e, f, g, h, i, j; var T1, T2; m[l >> 5] |= 0x80 << (24 - l % 32); m[((l + 64 >> 9) << 4) + 15] = l; for (var i = 0; i < m.length; i += 16) { a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7]; for (var j = 0; j < 64; j++) { if (j < 16) W[j] = m[j + i]; else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]); T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]); T2 = safe_add(Sigma0256(a), Maj(a, b, c)); h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2); } HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]); HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]); } return HASH; } function str2binb(str) { var bin = Array(); var mask = (1 << chrsz) - 1; for (var i = 0; i < str.length * chrsz; i += chrsz) { bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i % 32); } return bin; } function Utf8Encode(string) { string = string.replace(/  /g, "  "); var utftext = ""; for (var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); } else if ((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } return utftext; } function binb2hex(binarray) { var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var str = ""; for (var i = 0; i < binarray.length * 4; i++) { str += hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xF) + hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8)) & 0xF); } return str; } s = Utf8Encode(s); return binb2hex(core_sha256(str2binb(s),