Gang Zhao
Gang Zhao

Reputation: 136

How to send transactions async or batch send in Hyperledger Fabric using fabric-sdk-go

I want to make many txs on fabric chaincode, how to call it async or in batch?
While I only found channelClient.Execute channelClient.Query method, it send txs one by one and wait until tx is committed in block.

Upvotes: 1

Views: 931

Answers (1)

myeongkil kim
myeongkil kim

Reputation: 2576

In a single client, in code, the transactions appear to be committed one by one, but not when you look at the network topology broadly.

I will explain according to the transaction flow of the fabric.

  1. Multiple clients simultaneously request endorsing for a transaction from multiple peers, and the endorsed results are returned.
  2. Endorsed transaction, that is, endorsement is transmitted to the orderer simultaneously, and the orderer determines the order of the transaction, performs block packaging, and commits it to the peer.
  3. In other words, transactions are collected in the orderer and stored in block. In fact, transactions are contained within the block body.
  • This process can be easily observed by increasing the batch time of the block.
  • BatchTimeout can be defined under the Orderer item as the setting value for the channel in the configtx.yaml file. fabric/sampleconfig/configtx.yaml

If your question is to request multiple transactions from a single client at once, you can easily implement it as below through asynchronous request in javascript. The code has partially modified fabric-samples/fabcar/invoke.js.

using Promise.all()

/*
 * Copyright IBM Corp. All Rights Reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

'use strict';

const { Gateway, Wallets } = require('fabric-network');
const fs = require('fs');
const path = require('path');

async function main(tx_params) {
    try {
        // load the network configuration
        const ccpPath = path.resolve(__dirname, '..', '..', 'test-network', 'organizations', 'peerOrganizations', 'org1.example.com', 'connection-org1.json');
        let ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));

        // Create a new file system based wallet for managing identities.
        const walletPath = path.join(process.cwd(), 'wallet');
        const wallet = await Wallets.newFileSystemWallet(walletPath);
        console.log(`Wallet path: ${walletPath}`);

        // Check to see if we've already enrolled the user.
        const identity = await wallet.get('appUser');
        if (!identity) {
            console.log('An identity for the user "appUser" does not exist in the wallet');
            console.log('Run the registerUser.js application before retrying');
            return;
        }

        // Create a new gateway for connecting to our peer node.
        const gateway = new Gateway();
        await gateway.connect(ccp, { wallet, identity: 'appUser', discovery: { enabled: true, asLocalhost: true } });

        // Get the network (channel) our contract is deployed to.
        const network = await gateway.getNetwork('mychannel');

        // Get the contract from the network.
        const contract = network.getContract('fabcar');

        // Submit the specified transaction.
        // createCar transaction - requires 5 argument, ex: ('createCar', 'CAR12', 'Honda', 'Accord', 'Black', 'Tom')
        // changeCarOwner transaction - requires 2 args , ex: ('changeCarOwner', 'CAR12', 'Dave')
        await contract.submitTransaction(...tx_params);

        console.log(tx_params + ' Transaction has been submitted');

        // Disconnect from the gateway.
        await gateway.disconnect();

    } catch (error) {
        console.error(`Failed to submit transaction: ${error}`);
        process.exit(1);
    }
}

const tx1_params = ['createCar', 'CAR12', 'Honda', 'Accord', 'Black', 'Tom'];
const tx2_params = ['createCar', 'CAR13', 'Hyundai', 'Genesis', 'Gray', 'Myeongkil'];
const tx3_params = ['createCar', 'CAR14', 'Porsche', 'Macan', 'Blue', 'Dave'];

main(tx1_params);
main(tx2_params);
main(tx3_params);
  • result : stdout
Wallet path: /Users/kmk/Project/src/github.com/hyperledger/fabric-samples/fabcar/javascript/wallet
Wallet path: /Users/kmk/Project/src/github.com/hyperledger/fabric-samples/fabcar/javascript/wallet
Wallet path: /Users/kmk/Project/src/github.com/hyperledger/fabric-samples/fabcar/javascript/wallet
createCar,CAR13,Hyundai,Genesis,Gray,Myeongkil Transaction has been submitted
createCar,CAR12,Honda,Accord,Black,Tom Transaction has been submitted
createCar,CAR14,Porsche,Macan,Blue,Dave Transaction has been submitted
  • orderer logs
# 3 endorsments
# -> into 1 block
2020-12-30 02:15:08.948 UTC [comm.grpc.server] 1 -> INFO 096 streaming call completed grpc.service=orderer.AtomicBroadcast grpc.method=Broadcast grpc.peer_address=172.30.0.1:49302 grpc.peer_subject="CN=fabric-common" grpc.code=OK grpc.call_duration=7.792537ms
2020-12-30 02:15:08.953 UTC [comm.grpc.server] 1 -> INFO 097 streaming call completed grpc.service=orderer.AtomicBroadcast grpc.method=Broadcast grpc.peer_address=172.30.0.1:49304 grpc.peer_subject="CN=fabric-common" grpc.code=OK grpc.call_duration=6.326148ms
2020-12-30 02:15:08.967 UTC [comm.grpc.server] 1 -> INFO 098 streaming call completed grpc.service=orderer.AtomicBroadcast grpc.method=Broadcast grpc.peer_address=172.30.0.1:49306 grpc.peer_subject="CN=fabric-common" grpc.code=OK grpc.call_duration=2.909602ms
2020-12-30 02:15:10.943 UTC [orderer.consensus.etcdraft] propose -> INFO 099 Created block [20], there are 0 blocks in flight channel=mychannel node=1
2020-12-30 02:15:10.946 UTC [orderer.consensus.etcdraft] writeBlock -> INFO 09a Writing block [20] (Raft index: 22) to ledger channel=mychannel node=1

Upvotes: -1

Related Questions