You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript计算Hyperledger Fabric当前区块哈希及转换Block对象为字节数组

Solution for Converting Decoded Hyperledger Fabric Block to Byte Array (Node.js)

Got it, let's resolve this. The Hyperledger Fabric Java SDK includes utilities for handling block hashes and serialization, but the Node SDK doesn't ship with this out of the box. Below is a complete, production-ready implementation that aligns with Fabric's protobuf specification, allowing you to convert a decoded Block object to a byte array (and compute the block hash for queryBlockByHash()).

Prerequisite

First, install the official Fabric protobuf definitions package (required for correct serialization):

npm install @hyperledger/fabric-protos

1. Function to Convert Decoded Block Object to Byte Array

This function takes your decoded Block JSON object, maps it to Fabric's protobuf structure, and serializes it to a Buffer (byte array) that matches the format peers store:

const { common } = require('@hyperledger/fabric-protos');

function blockObjToByteArray(blockObj) {
    // 1. Build and serialize the BlockHeader
    const header = new common.BlockHeader();
    header.setNumber(BigInt(blockObj.header.number)); // Use BigInt to handle large block numbers
    header.setPreviousHash(Buffer.from(blockObj.header.previous_hash, 'hex'));
    header.setDataHash(Buffer.from(blockObj.header.data_hash, 'hex'));

    // 2. Build and serialize BlockData
    const blockData = new common.BlockData();
    const dataEntries = blockObj.data.data.map(entry => {
        // Adjust based on your blockObj's data format:
        if (typeof entry === 'string') return Buffer.from(entry, 'hex');
        if (Buffer.isBuffer(entry)) return entry;
        // If entry is a decoded Envelope object, re-serialize it:
        const envelope = new common.Envelope();
        envelope.setPayload(Buffer.from(entry.payload, 'hex'));
        envelope.setSignature(Buffer.from(entry.signature, 'hex'));
        return envelope.serializeBinary();
    });
    blockData.setDataList(dataEntries);

    // 3. Build and serialize BlockMetadata
    const blockMetadata = new common.BlockMetadata();
    const metadataEntries = blockObj.metadata.metadata.map(entry => {
        if (typeof entry === 'string') return Buffer.from(entry, 'hex');
        if (Buffer.isBuffer(entry)) return entry;
        // If entry is a decoded metadata object, adjust as needed:
        return Buffer.from(entry.value, 'hex');
    });
    blockMetadata.setMetadataList(metadataEntries);

    // 4. Assemble and serialize the full Block
    const block = new common.Block();
    block.setHeader(header);
    block.setData(blockData);
    block.setMetadata(blockMetadata);

    return block.serializeBinary(); // Returns Buffer (byte array)
}

2. Function to Compute Block Hash (for queryBlockByHash())

If your goal is to get the block hash to pass to queryBlockByHash() (since that method expects the hash, not the full block byte array), use this function (matches Java SDK's ChainUtils.computeBlockHash logic):

const crypto = require('crypto');
const { common } = require('@hyperledger/fabric-protos');

function computeBlockHash(blockObj) {
    // Serialize only the BlockHeader (Fabric computes block hash from the header)
    const header = new common.BlockHeader();
    header.setNumber(BigInt(blockObj.header.number));
    header.setPreviousHash(Buffer.from(blockObj.header.previous_hash, 'hex'));
    header.setDataHash(Buffer.from(blockObj.header.data_hash, 'hex'));
    const headerBytes = header.serializeBinary();

    // Compute SHA256 hash of the header bytes
    return crypto.createHash('sha256').update(headerBytes).digest();
}

Usage Example

Using your sample blockObj:

let blockObj = {
    header: {
        number: '100',
        previous_hash: '99478ca59eb60cc968cec9dde401ce70b1e470aeab4a458ba870f4a717b2e24a',
        data_hash: '1bee34054bc4457f51e3c00bfa552878503deb3220f2d171b55d2a35299afdb0'
    },
    data: { data: [/* Your Envelope entries (hex strings or decoded objects) */] },
    metadata: { metadata: [/* Your metadata entries */] }
};

// Convert to byte array (if needed for other use cases)
const blockByteArray = blockObjToByteArray(blockObj);

// Compute hash for queryBlockByHash()
const blockHash = computeBlockHash(blockObj);

// Use the hash in queryBlockByHash()
channel.queryBlockByHash(blockHash, targetPeer, useAdmin)
    .then(queriedBlock => console.log('Queried Block:', queriedBlock))
    .catch(err => console.error('Query failed:', err));

Key Notes

  • BigInt for Block Numbers: JavaScript's Number type can lose precision for block numbers larger than 2^53, so always use BigInt when setting the block number in the protobuf.
  • Adjust for Your Block Object Structure: If your blockObj has nested decoded protobuf objects (instead of hex strings), update the mapping logic to match the actual structure of your data.
  • Compatibility: Ensure the version of @hyperledger/fabric-protos matches your Fabric Node SDK version to avoid serialization mismatches.

内容的提问来源于stack exchange,提问作者Zach Gollwitzer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:12:08