javascriptblockchainhyperledger-fabrichyperledgerhyperledger-chaincode

Previous hash and data_hash not matching in hyper ledger fabric


I am working on the fabric test network trying to fetch blocks by number and check the block hash, and i use fabric 2.5 with the new fabric gateway api. I insert a data and check the transaction for the consicutive transaction to check weather i get the data hash on the next block previous hash. but they both are always different when i check with the api.

   {
    "Block Number": "10",
    "Previous Hash": "KSDy3jiB5Y15AT3W4PRqQWUTOarT50oKE8S100na0Ys=",
    "Data Hash": "VBZBIkTTggb23aBuC2xs7+bfCk1EYeKhMPfvQNCL0ZI="
}

{
    "Block Number": "11",
    "Previous Hash": "Zf8YhOJlgTcrWbqm+8up4kGcrNffHMgDFnF++gnI3Dk=",
    "Data Hash": "hY1pO7ljvlsNklmZBKksmTFreLRKNRX18dbvFk+5Y1g="
}

The above are the result returned after each transaction.

I have also directly queried from the cli using the command:

peer channel getinfo -c mychannel

where i got different value for data hash but my previous hash was similar in both the case

2024-12-27 11:43:47.409 IST 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
Blockchain info: {"height":11,"currentBlockHash":"Zf8YhOJlgTcrWbqm+8up4kGcrNffHMgDFnF++gnI3Dk=","previousBlockHash":"KSDy3jiB5Y15AT3W4PRqQWUTOarT50oKE8S100na0Ys="}

2024-12-27 11:49:19.022 IST 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
Blockchain info: {"height":12,"currentBlockHash":"1lbnSQSEWoJok327h6me1b7a5vgSdY8TGXA/uRUQDYo=","previousBlockHash":"Zf8YhOJlgTcrWbqm+8up4kGcrNffHMgDFnF++gnI3Dk="}

SDK and protos version:

"@hyperledger/fabric-gateway": "^1.7.1"
"@hyperledger/fabric-protos": "^0.2.2"

Iam using the fabric sample network and modifying the asset transfer basic gateway code.

app.get("/getBlockByNumber/:blockNumber", async (req, res) => {
  try {
    let { blockNumber } = req.params;
    blockNumber = blockNumber.replace(/"/g, "");
    blockNumber = blockNumber.replace(/\s+/g, " ").trim();

    const network = gateway.getNetwork("mychannel");
    const blockBytes = await network
      .getContract("qscc")
      .evaluateTransaction("GetBlockByNumber", network.getName(), blockNumber);

    console.log(
      `Got block for block number ${blockNumber} with length ${String(
        blockBytes.length
      )}`
    );
    const protos = require("fabric-protos");

    // Deserialize the block
    const block = protos.common.Block.decode(blockBytes);

    // Access block details
    const data = {
      "Block Number": block.header.number.toString(),
      "Previous Hash": Buffer.from(block.header.previous_hash).toString(
        "base64"
      ),
      "Data Hash": Buffer.from(block.header.data_hash).toString("base64"),
    };


    res.send(data);
  } catch (error) {
    console.error("Error in getBlockByNumber:", error);
    res.status(500).send("Failed to fetch block by block number");
  }
});

Solution

  • Data hash and block hash are different things, which is why you are seeing different values.

    The data hash is the hash of the BlockData (which contains all the transaction envelopes within the block), by MerkleTree.

    A block hash is calculated by hashing over the concatenated ASN.1 encoded bytes of: the block number, previous block hash, and current block data hash. See this answer for a JavaScript implementation of block hash calculation.