hyperledger / caliper

A blockchain benchmark framework to measure performance of multiple blockchain solutions https://wiki.hyperledger.org/display/caliper
https://hyperledger.github.io/caliper/
Apache License 2.0
650 stars 403 forks source link

withTransactionError: Commit of transaction -2d8738205152fe557d63da9d11ca4d409f6be0470719057a5412535a71a53ed1 failed on peer.org1.example. com with status MVCC_READ_CONFLICT #1482

Open 1234xxh opened 1 year ago

1234xxh commented 1 year ago

Which Caliper version are you using?

v0.4.2

Which Node.JS version are you using?

v14.19.1

Which operating system are you using?

Ubuntu18.0.4

Please provide some context for your error. For example, when did the error occur? What were you trying to achieve, and how?

test smallbank image image

What was the observed incorrect behavior?

if "smallbank/config.yaml" tps is greater than 200, we get this error message smallbank/config.yaml

Please provide the error logs and their surroundings.

2023.02.12-11:29:07.093 error [caliper] [connectors/v2 fabric-gateway] Failed to perform submit transaction [write_ check] using arguments [113, 286971107], with error: TransactionError: Commit of transaction 265a1ac89e698c6486417233c45878d15357708bd230a37bcfe failed on peer peer0. org1. example.com with status MVCC_ READ_ CONFLICT

at Transact ionEventHandler . eventCallback (/ root/ fabric-demo/ caliper-benchma rks / node_ modules/ fabric-network lib/ impl/event/ t ransact ioneventhandler.js1)
at CommitL istenerSession. notifyL istener (/ root/ fabric-demo/ ca liper-benchma rks/ node_ modules/ fab ric-netwo rk/ lib/ imp ไ/ event/ commit listenersession.js:78:1
EventL istener . callback (/ root/ fabr ic-demo/ ca lipe r-benchma rks/ node_ modules/ fabr ic-network/ lib/ imp l/ event/ commit listenersession. js:69:18)
EventListener . onEvent (/ root/ fabr ic-demo/ ca lipe r-benchma rks/node_ modules/ fabr ic- common/ lib/EventListener.js 10 )
at EventService._ ca llT ransactionListener (/ root/ fabr ic-demo/ ca lipe r-benchma rks/ node_ modules/ fabric-common/ ไ ib/ EventService. js:1050:16
at EventService. processTxEvents (/ root/ fabric-demo/ calipe r-benchma rks/node_ modules/ f abric-common/ lib/EventService.js:10051
at ClientDup lexSt reamImp l. <anonymous> (/ root/ fabric-demo/ ca lipe r-benchmarks/ node_ modules/ fabr ic- common/ lib/ EventService. js:480:12)
at ClientDup lexSt reamImpl. emit (events. js:400:28)
at addChunk ( internal/ streams/ readable. js:293:12)
readabl eAddChunk ( internal /st reams/ readable. is: 267:9 )

Please provide your benchmark configuration file content, if possible.

smallbank/config.yaml

test:
  workers:
    number: 4
  rounds:
    - label: load.
      txNumber: 10000
      rateControl:
          type: fixed-rate
          opts:
            tps: 500
      workload:
        module: benchmarks/samples/fabric/smallbank/load.js
        arguments:
          txnPerBatch: 1
    - label: mixed.
      txNumber: 100000
      rateControl:
          type: fixed-rate
          opts:
            tps: 500
      workload:
        module: benchmarks/samples/fabric/smallbank/mixed.js
        arguments:
          queryRatio: 0.1
          txnPerBatch: 1

Please provide your network configuration file content, if possible.

name: Fabric
version: "1.0"
mutual-tls: false
caliper:
  blockchain: fabric
  command:
    start: sleep 1s
    end: rm -rf /tmp/hfc-*
info:
  Version: 2.1.0
  Orderer: solo

clients:
  client0.org1.example.com:
    client:
      organization: Org1
      credentialStore:
        path: /tmp/org1
        cryptoStore:
          path: /tmp/org1
      clientPrivateKey:
        path: '../../testwork/fixtures/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/priv_sk'
      clientSignedCert:
        path: '../../testwork/fixtures/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem'
channels:
  mychannel:
    configBinary: "../../testwork/fixtures/channel-artifacts/mychannel.tx"
    created: false
    # Array of contracts to be installed/instantiated on the named channel and available for use by the workload module
    contracts:
      - id: smallbank
        version: v0
        language: golang
        path: src/fabric/go/smallbank
    orderers:
      - orderer.example.com
    peers:
      peer0.org1.example.com:
        eventSource: true
      peer1.org1.example.com:
        eventSource: true
      peer0.org2.example.com:
        eventSource: true
      peer1.org2.example.com:
        eventSource: true
organizations:
  Org1:
    mspid: Org1MSP
    peers:
      - peer0.org1.example.com
    adminPrivateKey:
      path: '../../testwork/fixtures/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/priv_sk'
    signedCert:
      path: '../../testwork/fixtures/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem'
  Org2:
    mspid: Org2MSP
    peers:
      - peer0.org2.example.com
    adminPrivateKey:
      path: '../../testwork/fixtures/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/priv_sk'
    signedCert:
      path: '../../testwork/fixtures/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/Admin@org2.example.com-cert.pem'
orderers:
  orderer.example.com:
    url: "grpcs://127.0.0.1:7050"
    grpcOptions:
      ssl-target-name-override: orderer.example.com
    tlsCACerts:
      path: "../../testwork/fixtures/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tls/ca.crt"
peers:
  peer0.org1.example.com:
    url: "grpcs://47.101.223.240:7051"
    grpcOptions:
      ssl-target-name-override: peer0.org1.example.com
      grpc.keepalive_time_ms: 600000
    tlsCACerts:
      path: "../../testwork/fixtures/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
  peer1.org1.example.com:
    url: "grpcs://47.100.160.31:7061"
    grpcOptions:
      ssl-target-name-override: peer1.org1.example.com
      grpc.keepalive_time_ms: 600000
    tlsCACerts:
      path: "../../testwork/fixtures/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt"
  peer0.org2.example.com:
    url: "grpcs://139.224.16.249:8051"
    grpcOptions:
      ssl-target-name-override: peer0.org2.example.com
      grpc.keepalive_time_ms: 600000
    tlsCACerts:
      path: "../../testwork/fixtures/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
  peer1.org2.example.com:
    url: "grpcs://47.100.164.186:8061"
    grpcOptions:
      ssl-target-name-override: peer1.org2.example.com
      grpc.keepalive_time_ms: 600000
    tlsCACerts:
            path: "../../testwork/fixtures/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt"

Please provide your workload module content, if possible.

benchmarks/samples/fabric/smallbank/mixed.js

'use strict';

const { WorkloadModuleBase } = require('@hyperledger/caliper-core');

const operation_type = ['transact_savings','deposit_checking','send_payment','write_check', 'amalgamate'];
let prefix;
let account_array = [];
let acc = require('./load.js');
account_array = acc.account_array;

/**
 * Workload module for the benchmark round.
 */
class CreateCarWorkload extends WorkloadModuleBase {
    /**
     * Initializes the workload module instance.
     */
    constructor() {
        super();
        this.txnPerBatch;
        this.queryRatio;

    }

    getAccount() {
        return Math.floor(Math.random()*Math.floor(account_array.length));
    }

    /**
     * Get two accounts
     * @return {Array} index of two accounts
     */
    get2Accounts() {
        let idx1 = this.getAccount();
        let idx2 = this.getAccount();
        if(idx2 === idx1) {
            idx2 = this.getAccount();
        }
        return [idx1, idx2];
    }

    async initializeWorkloadModule(workerIndex, totalWorkers, roundIndex, roundArguments, sutAdapter, sutContext) {
        await super.initializeWorkloadModule(workerIndex, totalWorkers, roundIndex, roundArguments, sutAdapter, sutContext);
        // if (!this.roundArguments.hasOwnProperty('txnPerBatch')) {
        //     return Promise.reject(new Error('ycsb.txn - \'txnPerBatch\' is missed in the arguments'));
        // }
        this.txnPerBatch = this.roundArguments.txnPerBatch;

        // if (!this.roundArguments.hasOwnProperty('readRatio') || !inRange(this.roundArguments.readRatio)) {
        //     return Promise.reject(new Error('ycsb.txn - \'readRatio\' is missed in the arguments or not in the correct range.'));
        // }
        this.queryRatio = this.roundArguments.queryRatio;
    }
    /**
     * Assemble TXs for the round.
     * @return {Promise<TxStatus[]>}
     */
    async submitTransaction() {
        let prob = Math.random();
        if (Math.random() < this.queryRatio) {
            let query_promises = [];
            let acc_num  = account_array[Math.floor(Math.random()*(account_array.length))];
            for (let i=0; i < this.txnPerBatch; ++i) {
                let args = {
                    contractId: 'smallbank',
                    contractVersion: 'v1',
                    contractFunction: 'query',
                    contractArguments: [acc_num],
                    timeout: 30,
                    readOnly: true
                };
                query_promises.push(args);
            }
            await this.sutAdapter.sendRequests(query_promises);
        } else {
            let workload = [];
            for(let j= 0; j<this.txnPerBatch; j++) {
                let op_index =  Math.floor(Math.random() * Math.floor(operation_type.length));
                let acc_index = this.getAccount();
                let random_op = operation_type[op_index];
                let random_acc = account_array[acc_index];
                let amount = Math.floor(Math.random() * 200);
                let op_payload;
                switch(random_op) {
                    case 'transact_savings': {
                        op_payload = {
                            contractId: 'smallbank',
                            contractVersion: 'v1',
                            contractFunction: random_op,
                            contractArguments: [amount, random_acc],
                            timeout: 30
                        };
                        break;
                    }
                    case 'deposit_checking': {
                        op_payload = {
                            contractId: 'smallbank',
                            contractVersion: 'v1',
                            contractFunction: random_op,
                            contractArguments: [amount, random_acc],
                            timeout: 30
                        };
                        break;
                    }
                    case 'send_payment': {
                        let accounts = this.get2Accounts();
                        op_payload = {
                            contractId: 'smallbank',
                            contractVersion: 'v1',
                            contractFunction: random_op,
                            contractArguments: [amount, account_array[accounts[0]],account_array[accounts[1]]],
                            timeout: 30
                        };
                        break;
                    }
                    case 'write_check': {
                        op_payload = {
                            contractId: 'smallbank',
                            contractVersion: 'v1',
                            contractFunction: random_op,
                            contractArguments: [amount, random_acc],
                            timeout: 30
                        };
                        break;
                    }
                    case 'amalgamate': {
                        let accounts = this.get2Accounts();
                        op_payload = {
                            contractId: 'smallbank',
                            contractVersion: 'v1',
                            contractFunction: random_op,
                            contractArguments: [account_array[accounts[0]], account_array[accounts[1]]],
                            timeout: 30
                        };
                        break;
                    }
                    default: {
                        throw new Error('Invalid operation!!!');
                    }
                }
                workload.push(op_payload);
            }
            await this.sutAdapter.sendRequests(workload);
        }
    }
}

/**
 * Create a new instance of the workload module.
 * @return {WorkloadModuleInterface}
 */
function createWorkloadModule() {
    return new CreateCarWorkload();
}

module.exports.createWorkloadModule = createWorkloadModule;

Please provide any additional information you deem relevant to the error.

image image

davidkel commented 1 year ago

In Hyperledger Fabric, MVCC_READ_CONFLICT is an acceptable error response for which the client application needs to deal with see https://github.com/hyperledger/fabric-samples/tree/main/asset-transfer-basic/rest-api-typescript as an example of an application that is coded to handle this. I would suggest investing some time in hyperledger fabric to understand what an MVCC_READ_CONFLICT is but basically it means a key was modified after another transaction endorsed was the previous key value therefore that endorsed transaction cannot be committed. This kind of response is more likely to occur as the load is increased (you can design applications to avoid or reduce the possibility of this). Caliper is just reports any failure to commit as a failure, it could in the future report it as a success or provide the capability for the workload to see this and be coded to retry the transaction. This is not an issue with caliper

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.