Hyperledger Fabric无法异步传输Fabtoken

时间:2019-08-22 23:19:08

标签: node.js hyperledger-fabric hyperledger hyperledger-fabric-sdk-js

我正在使用Hyperledger Fabric的Node.js SDK与区块链进行交互。我想做的是同时为多个用户发布一些Fabtoken,然后将它们异步传输给另一个用户。即使我可以同时成功地发行令牌,但是我仍然无法异步传输这些令牌。

我正在使用fabric-samples存储库(https://github.com/hyperledger/fabric-samples)下的基本网络和fabtoken样本作为设置(它们最近删除了fabtoken)。我用4个用户建立了区块链。

这里(https://fabric-sdk-node.github.io/Client.html)记录了“使用相同的客户端实例切换userContext被认为是一种反模式”,我们应该“为每个经过身份验证的用户使用专用的客户端实例”。因此,我在async function createUsers(n)方法中为每个用户创建了一个新的客户端实例:

Repeat n times:
const userClient = new Fabric_Client();
const user = await userClient.createUser(user_opts_user);

然后,此方法返回一个usersConfig对象,该对象包含两个数组的userClients和大小为n的用户。

let usersConfig = {
    users: users
    userClients: userClients
}

这是我同时发行令牌的方式:

let clientIssueTxs = await waitForClientIssueTxs(operations, blockchainInfo);

当我像这样列出每个用户的令牌时:

for(let user of usersConfig.users) {
    let user_tokens = await list(client, channel, user);
    console.log(user.getName() + " tokens: " + user_tokens[0].id.tx_id);
}

我得到这样的输出,其中包含已发行令牌的交易ID,这是预期的:

user1 tokens: '22d3541fef32f0186524bf7ba63c53d4d76e9efea333c799124a99411de40d3b'
user2 tokens: 'b6694aa43d979d14a17bb567cb64cfea248891c852d14a5359ff912721404701'
user3 tokens: '950d7371aa246bd8f00cb39805fb6e30863493aac6427d64d5f8dcfeee7e2417'
user4 tokens: '13bc21e0081133b2446624af9d86661eb1b28ed11f058aac0348fcfa5ff95006'

然后问题开始了。我正在尝试将这些令牌转让给组织中的另一个用户,但我只能转让其中一个。这就是我调用转移方法的方式:

for (let i = 0; i < usersConfig.users.length; i++) {
    let user = usersConfig.users[i];
    let user_tokens = await list(client, channel, user);
    let tx = user_tokens[0].id.tx_id;
    let userClient = usersConfig.userClients[i];

    let transferQuery = {
        client: userClient,
        channel: blockchainInfo.channel,
        user: user,
        recipient: blockchainInfo.admin,
        args: [
            {
                qty: '1',
                tx_id: tx,
                index: 0
            }
        ]
    }

    transfer(transferQuery, (successResponse) => {
        console.log("SUCCESS: " + successResponse);
    }, (errorResponse) => {
        console.log("ERROR: " + errorResponse));
    });
}

这是我的transfer()方法的外观:

async function transfer(query, successCallback, errorCallback) {
    let client = query.client
    let channel = query.channel
    let user = query.user
    let recipient = query.recipient
    let args = query.args

    await client.setUserContext(user, true);

    const tokenClient = client.newTokenClient(channel, 'localhost:7051');

    // build the request to transfer tokens to the recipient
    const txId = client.newTransactionID();

    let params = [];
    let tokenIds = [];
    args.forEach(function(element) {
        let param = {
            owner: recipient.getIdentity().serialize(),
            quantity: element.qty 
        }
        params.push(param);

        let tokenId = {
            tx_id: element.tx_id,
            index: element.index
        }

        tokenIds.push(tokenId);
    });

    const request =  {
        tokenIds: tokenIds,
        params: params,
        txId: txId,
    };

    let transactionID = txId._transaction_id;

    let event_hub = channel.newChannelEventHub(channel.getChannelPeers()[0]);
    let options = {
        disconnect: true
    }

    // Callback function to receive a notification when the transaction by the given id has been committed into a block
    event_hub.registerTxEvent(
        transactionID,
           (tx, code) => {
            event_hub.unregisterTxEvent(transactionID); 
                successCallback(
                    {
                        tx: tx
                    }
                );
           },
           (err) => {
            event_hub.unregisterTxEvent(transactionID);
                errorCallback(
                    {
                        tx: transactionID,
                        err: err,
                        peerAddress: event_hub.getPeerAddr()
                    }
                );
            },
            options
    ); 

    event_hub.connect();

    await tokenClient.transfer(request);
}

基本上,我只是设置用户上下文,构建传输查询并注册一个回调函数,以便在将具有给定id的事务提交到一个块中时接收通知。

当我在实际转移令牌之前(在上述transfer()方法之后)以setUserContext()方法列出传递的用户的令牌时,它返回另一个用户的令牌,并且出现以下错误:

command response has error: input TokenId (tx_id, index) does not exist or not owned by the user

我可以通过在for循环中的await调用之前添加transfer()关键字(使其同步)来解决此问题。因此,这使我认为我在for循环中调用async transfer()方法的方式打破了函数调用的顺序,并以错误的参数运行了async函数,但我不知道为什么。

0 个答案:

没有答案