Hyperledger Fabric

Hyperledger : Customising hyperledger explorer

Hyperledger is an open source blockchain solution that you can use for setting up private blockchains. The product is becoming more useful in providing blockchain solutions to industries. There is plenty of room to introduce more documentation on customising hyperledger.

Hyperledger Fabric
Hyperledger

Instructions for setting up hyperledger can be found here and Instructions for setting up blockchain explorer are available here .

Hyperledger Block Explorer

We will focus now searching though the blockchain with details saved in a specific transaction in hyperledger. Blockchain explorer for hyperleder makes use of a postgres database. By default the blockchain explorer can search through the blockchain using transaction hash, block hash and channel names. It is however not configured to search through information specific to a transaction. This information is saved in the column write_set of the table transactions in the postgres database. The datatype of the column is json.

The blockchain explorer has APIs which which can be extend to make your own APIs so that you can use them to search through the blockchain.

The goal is to create your own customised query to search through transactions.
You will need to update the file blockexplorer/blockchain-explorer/app/persistence/postgreSQL/CRUDService.js

In this file you will find the following piece of code. This will be your guide to creating a new function with your custom query.

getTxList(channel_genesis_hash, blockNum, txid, from, to, orgs) {

let orgsSql = '';

if (orgs && orgs != '') {

orgsSql = `and t.creator_msp_id in (${orgs})`;

}
let sqlTxList = ` select t.creator_msp_id,t.txhash,t.type,t.chaincodename,t.createdt,channel.name as channelName from transactions as t  inner join channel on t.channel_genesis_hash=channel.channel_genesis_hash where t.blockid >= ${blockNum} and t.id >= ${txid} ${orgsSql} and

t.channel_genesis_hash = '${channel_genesis_hash}' and t.createdt between '${from}' and '${to}' order by t.id desc`;

return sql.getRowsBySQlQuery(sqlTxList);

}
It will search through the transactions and provide you a list of results. As a result we can create our own function that can search through the data. This can find data matching the information that was part of the transaction.For instance an example of how such a function can look like is as below.
getTxListWithOtherInfo(channel_genesis_hash, blockNum, txid, from, to, orgs,otherInfoToSearch) {
let orgsSql = '';
if (orgs && orgs != '') {
orgsSql = `and t.creator_msp_id in (${orgs})`;
}
let sqlTxList = ` select t.creator_msp_id,t.txhash,t.type,t.chaincodename,t.createdt,channel.name as channelName from transactions as t
inner join channel on t.channel_genesis_hash=channel.channel_genesis_hash where t.blockid >= ${blockNum} and t.id >= ${txid} ${orgsSql} and
t.channel_genesis_hash = '${channel_genesis_hash}' and t.createdt between '${from}' and '${to}' and t.write_set::json->>0 LIKE '%${otherInfoToSearch}%' order by t.id desc`;
return sql.getRowsBySQlQuery(sqlTxList);
}

Take note of this part of code here

and t.write_set::json->>0 LIKE ‘%${otherInfoToSearch}%’


This is the part the searches through the json datatype column and converting the data to a string using ->> and looking for a match with the resultant string text.

Common problem

A common problem encountered is that of the search failing because of invalid values caused by \u0000 which is imported as part of the data by the explorer which its building the database and filling it with data from the blockchain. A solution for this is to remove this as data is being imported so that it is not saved in the database and this can be archived by updating the file
blockexplorer/blockchain-explorer/app/persistence/postgreSQL/db/pgservice.js

In this file We update the function saveRow and update it to this.

function saveRow(tablename, columnValues) {
return new Promise(function(resolve, reject) {
var addSqlParams = [];
var updatesqlcolumn = [];
var updatesqlflag = [];
var i = 1;
Object.keys(columnValues).forEach(k => {
let v = columnValues[k];
console.log(v);
if(tablename==="transactions"){
if(v && (k==="read_set" || k==="write_set")){
v = v.replace(/\\u0000/gi, "");
}
}
addSqlParams.push(v);
updatesqlcolumn.push(JSON.stringify(k));
updatesqlflag.push('$' + i);
i = i + 1;
});
var updatesqlparmstr = updatesqlcolumn.join(',').replace(/\\u0000/gi, "");
var updatesqlflagstr = updatesqlflag.join(',');
var addSql = `INSERT INTO ${tablename} ( ${updatesqlparmstr} ) VALUES( ${updatesqlflagstr} ) RETURNING *;`;
logger.debug(`Insert sql is ${addSql}`);
client.query(addSql, addSqlParams, (err, res) => {
if (err) {
logger.error('[INSERT ERROR] - ', err.message);
console.log(err.stack);
reject(err);
}
resolve(res.rows[0].id);
});
});
}

The main focus for this change is on this section:

if(tablename==="transactions"){
if(v && (k==="read_set" || k==="write_set")){
v = v.replace(/\\u0000/gi, "");
}
}

With these changes you should be able to do a lot more like creating custom APIs to search through you hyperledger blockchain

Checkout other blockchain related articles

bmukorera

Passionate software engineer with keen interest in solving world problems using technology.He has vast experience in developing enterprise solutions from Telecommunications ,Media,Banking and Consultancy.

You May Also Like

An Introduction to cryptocurrency

An Introduction to Cryptocurrency-1

BigchainDB Java Spring boot

Leave a Reply

Your email address will not be published. Required fields are marked *