我正在使用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函数,但我不知道为什么。