0.4.0 • Published 2 years ago

blockchain-verifier v0.4.0

Weekly downloads
46
License
Apache-2.0
Repository
-
Last release
2 years ago

Blockchain Verifier

Overview

The goal of this tool is to verify the integrity of blockchain blocks and transactions.

Supported Blockchain Platforms

  • Hyperledger Fabric v1.4 (to be deprecated)
  • Hyperledger Fabric v2.2, v2.3 & v2.4

Prerequisites

  • Node.js >= v10.15

Install

$ npm install blockchain-verifier

Usage

$ npx bcverifier -n (Network plugin) -c (Network config) -o (Result file) (Command)

Run with -h for the full list of the options.

Options

OptionDescription
-n (plugin)Specify the name of the network plugin to use
-c (config)Configuration passed to the network plugin. See the description for the network plugins for detail
-o (file)Save the result JSON in the specified file
-k (checkers)Specify the modules to use as application-specific checkers
-x (checkers)Disable the checkers with specified names
-s (checkpoint)Save the checkpoint into a JSON file after the checks are completed
-r (checkpoint)Resume checks from the checkpoint
-iSkip key-value processing even if a checkpoint is to be saved (i.e. the -s option is specified)
-e (block)Stop checks at the specified block number

Commands

CommandDescription
startStart verification and save the result if -o is specified

Example

$ npx bcverifier -n fabric-block -c /tmp/block/blockfile_000000 -o result.json start

Runs verification against a Hyperledger Fabric ledger file /tmp/block/blockfile_000000 using the fabric-block plugin.

Network plugins

NameSupported PlatformDescriptionConfig value (-c option)
fabric-blockHyperledger Fabric v1.4/2.xVerify a ledger file and private DBPath to the ledger file or config JSON
fabric-queryHyperledger Fabric v1.4Verify blocks by querying to a peerPath to the query config file
fabric-query2Hyperledger Fabric v2.xVerify blocks by querying to a peer (v2.x)Path to the query config file (v2)

fabric-block

This plugin checks a ledger file for a channel in Hyperledger Fabric network. The file can be usually found in /var/lib/hyperledger/production/ledgersData/chains/chains/(channel name) in a peer. It also supports checking of the private data (SideDB) against the ledger if the private data is available.

The configuration is either a path to a ledger file or to a configuration JSON. If you want to check private data, use the latter (JSON). The format for the JSON is an array of objects (only one object is supported though). The keys for the object is as follows:

Key nameTypeDescription
namestringany string name for this ledger source
ledgerStorestringpath to a ledger directory
blockFilestringpath to a ledger file
privateDataStorestringpath to a private DB directory

Among the keys, ledgerStore or blockFile is mandatory. The private DB can be found in /var/lib/hyperledger/production/ledgersData/pvtdataStore in a default configuration. If you want to check private data, please perform check against a copy of the directory. Otherwise (such as using the directory for a running Fabric peer), the tool might affect the Fabric peer.

Example:

[
  {
    "name": "peer0.org1.example.com",
    "ledgerStore": "/tmp/peerLedger/ledgersData/chains/chains/mychannel",
    "privateDataStore": "/tmp/peerLedger/ledgersData/pvtdataStore"
  }
]

Limitation: The ledger may be divided to multiple files when it becomes huge, but the plugin currently only supports a single file. You may try to check the divided files by concatenating the ledger files. Even if the directory is specified with the JSON, the plugin uses only the first file(blockfile_000000).

fabric-query2

This plugin checks blocks by obtaining them calling qscc system chaincode in a peer. As this plugin uses v2.x of Fabric SDK, this only supports v2.x peers. For v1.4 peers, the fabric-query plugin should be used.

The configuration value for the plugin should be the file name to a configuration JSON. Note that the structure of the JSON is far different from that for fabric-query.

The format is shown below:

Key nameTypeDescription
peer.urlstringURL to a peer (e.g. grpcs://peer1.org1.example.com:7051)
peer.mspIDstringMSP ID for the organization which the peer belongs to
peer.tlsCACertFilestringCA certificate for TLS with the peer (Required when TLS is enabled)
channelstringChannel name
client.certFilestringCertificate for the client identity to use to connect to the peer
client.keyFilestringPrivate key for the client identity to use to connect to the peer
client.mspIDstringMSP ID for the client identity
client.mutualTLS.certFilestringClient certificate (Required when mutual TLS is enabled)
client.mutualTLS.keyFilestringClient private key (Required when mutual TLS is enabled)

Example:

{
  "peer": {
    "url": "grpcs://localhost:7051",
    "mspID": "Org1MSP",
    "tlsCACertFile": "/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/tlscacerts/tls-localhost-7054-ca-org1.pem"
  },
  "channel": "mychannel",
  "client": {
    "certFile": "/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/cert.pem",
    "keyFile": "/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/e488b2baef3f8121f9122140bd937c7708336f185e1668d66bbfbf5157379e27_sk",
    "mspID": "Org1MSP"
  }
}

fabric-query

To be deprecated: Since Hyperledger Fabric v1.4 is no longer maintained, the support for v1.4 will be deprecated in a future release of Blockchain Verifier. This plugin will be also removed once the support is deprecated.

This plugin checks blocks by obtaining them using query method to a peer.

The configuration value for the plugin should be the file name to the configuration JSON. The format for the JSON is as follows:

Key nameTypeDescription
connectionProfilestringpath to the connection profile
useDiscoverybooleanwhether to use the service discovery
client.mspIDstringMSP ID for the Hyperledger Fabric client
client.peerNamestringpeer name to query
client.channelNamestringchannel name
client.credentials.useAdminbooleanwhether to use the admin credentials described in the profile
client.credentials.mutualTLSbooleanwhether to use mutual TLS
client.credentials.userNamestringuser name (not so meaningful)
client.credentials.certFilestringpath to signed certificate to use for the client
client.credentials.keyFilestringpath to private key to use for the client

Example:

{
  "connectionProfile": "profile.yaml",
  "useDiscovery": true,
  "client": {
    "mspID": "Org1MSP",
    "peerName": "peer0.org1.example.com",
    "channelName": "mychannel",
    "credentials": {
      "useAdmin": false,
      "mutualTLS": false,
      "userName": "user",
      "certFile": "credentials/User1@org1.example.com-cert.pem",
      "keyFile": "credentials/e4af7f90fa89b3e63116da5d278855cfb11e048397261844db89244549918731_sk"
    }
  }
}

Result JSON

The result JSON contains information for each block and transaction, along with checks performed for the block and transaction.

Below is some excerpt from a result JSON:

{
  "blocks": [
    {
      "number": 3,
      "results": [
        {
          "result": "OK",
          "predicate": "EQ",
          "operands": [
            "Block(3).PreviousHash",
            "HashForPrev(Block(2))"
          ]
        },
        {
          "result": "OK",
          "predicate": "EQ",
          "operands": [
            "Block(3).Hash",
            "HashForSelf(Block(3))"
          ]
        },
        ...
      ]
    }
  ],
  "transactions": [
    ...
    {
      "id": "b9f33606fb6b415782a773c50ef1deb67a2e4805536e3ef27f67b9c2086a3d80",
      "blockNumber": 3,
      "results": [
        {
          "result": "OK",
          "predicate": "INVOKE",
          "operands": [
            "VerifySignatureHeader",
            "Block(3).Tx(3:0).SignatureHeader",
            "Block(2).ConfigTx.Config.ApplicationMSP"
          ]
        },
        ...
    }
    ...
  }
}

The part above shows that the block 3's previous hash entry is checked against the actual hash value for the block 2, and the block 3's hash entry is also checked against the actual hash value for block 3. It also shows that the signature header (certificate) for the transaction b9f336.. is checked against the CA certificate for the configuration.

The results for these checks are all "OK," which means that the integrity of the blockchain is verified.

Comparison of multiple ledgers

When multiple ledgers are specified, Blockchain Verifier checks the hash value of each block in a ledger with the hash values of the block in the other ledgers. Currently, the "fabric-block" and "fabric-query2" plugins support this feature. The first ledger in the configuration is considered to be "preferred," and the other ledgers are used only in this check.

Platform Checkers

Blockchain Verifier has several checkers to perform platform-level checks, independent of applications, as described in the table below.

Checker nameTarget platformChecks to be performed
generic-block(Generic)The hash values of the blocks
fabric-blockHyperledger FabricThe signature in the metadata of the blocks
fabric-transactionHyperledger FabricThe signature in the transactions, the hash values of the private data
multiple-ledgers(Generic)The hash values of the blocks from different nodes

Application Specific Check

You can write application specific check programs that are called from Blockchain Verifier. The check program should export a class that implements AppStateCheckLogic and/or AppTransactionCheckLogic (as defined in check/index.ts)

For detail, please refer to the application checker reference.

Checkpoints

v0.4.0 introduces a checkpoint feature for Blockchain Verifier. A checkpoint is a file which contains what are required for Blockchain Verifier to resume checks from the last block in the future, such as block hashes, state database etc.

A checkpoint is saved when the -s option is specified. When a checkpoint is specified with the -r option, Blockchain Verifier resumes checks from the next block of the last block saved in the checkpoint. A user may save a checkpoint after executing Blockchain Verifier for the ledger with 100 blocks; they can continue checks using the checkpoint from the 101st block, skipping the first 100 blocks as they are considered "verified" with the checkpoint.

Caveat (for key-value ledgers)

Starting v0.3.1, Blockchain Verifier does not process the key-value pairs in transaction unless any application checker is specified. When it is directed to save a checkpoint, it DOES process key-value pairs and save the state information into the checkpoint because the information might be needed in future execution. If you really want to suppress the key-value processing, use the --skip-key-value (-i) option along with the -s option.

Please also notice that application checkers will not be able to obtain history for key-value pairs before the checkpoint.

TODO

  • Documents (API reference, Data specification)
  • Unit tests
  • Support for more plugins and platforms

Changes

v0.4.0 (Sep. 9, 2022)

  • Add the checkpoint feature

v0.3.1 (Aug. 31, 2021)

  • Add an option to skip certain checkers
  • Add integration tests (with Hyperledger Fabric v2.2/2.3)

v0.3.0 (Feb. 25, 2021)

  • Fix an error when verifying Hyperledger Fabric v2.3 blocks
  • Add a check that compares the hash values of each block in multiple ledgers

v0.2.2 (Oct. 8, 2020)

  • Add "fabric-query2" plugin to support querying blocks from v2.x peers

v0.2.1 (Oct. 1, 2020)

  • Most of the Fabric-related plugins are switched to use fabric-sdk-node v2.2

v0.2.0 (Feb. 13, 2020)

  • Support application specific check plugins

v0.1.3 (Aug. 6, 2019)

  • Fix check logic for signatures in the metadata

License

Apache-2.0 (See LICENSE)