如何更新Hyperledger Composer中的现有资产?添加Provider失败求助
看起来你在Hyperledger Composer里遇到了资产数组更新的棘手问题——没法给目标资产的provider数组添加新的Provider对象。我结合你提供的代码片段,帮你一步步拆解可能的问题点和解决办法。
1. 先梳理你的核心代码片段
模型文件(CTO)片段
namespace org.example.network asset Asset identified by assetId { o String assetId --> Provider[] providers // 重点关注这里的数组定义语法 } participant Provider identified by providerId { o String providerId o String name } transaction AddProviderToAsset { --> Asset targetAsset --> Provider newProvider }
交易处理器(JavaScript)代码片段
/** * Add a provider to an asset's provider list * @param {org.example.network.AddProviderToAsset} tx * @transaction */ async function addProviderToAsset(tx) { // 获取目标资产 const assetRegistry = await getAssetRegistry('org.example.network.Asset'); const asset = tx.targetAsset; // 尝试添加新Provider asset.providers.push(tx.newProvider); // 更新资产注册表 await assetRegistry.update(asset); }
典型错误信息示例
TypeError: Cannot read property 'push' of undefined
或
Error: Attempting to update asset org.example.network.Asset#asset123 which has not been retrieved from the registry
或
Error: Invalid update: asset providers is not an array
2. 逐一排查问题点与修复方案
问题1:资产的providers数组未初始化
如果资产创建时providers字段默认是undefined,直接调用push会触发Cannot read property 'push' of undefined错误。
修复代码:
在交易逻辑里先检查并初始化数组:
async function addProviderToAsset(tx) { const assetRegistry = await getAssetRegistry('org.example.network.Asset'); const asset = tx.targetAsset; // 初始化数组(为空时创建新数组) if (!asset.providers) { asset.providers = []; } asset.providers.push(tx.newProvider); await assetRegistry.update(asset); }
问题2:模型中的数组定义语法错误
如果模型里providers字段不是数组类型(比如写成了--> Provider provider),自然没法执行添加数组元素的操作。
检查修正模型:
确保资产字段是数组类型的关联:
asset Asset identified by assetId { o String assetId --> Provider[] providers // 必须加上[]表示数组 }
问题3:未从资产注册表获取最新资产状态
直接使用tx.targetAsset可能拿到的不是最新的资产数据,或者未正确绑定到注册表,导致更新失败。
修复代码:
从注册表重新获取最新资产:
async function addProviderToAsset(tx) { const assetRegistry = await getAssetRegistry('org.example.network.Asset'); // 从注册表拉取最新的资产数据 const asset = await assetRegistry.get(tx.targetAsset.assetId); if (!asset.providers) { asset.providers = []; } asset.providers.push(tx.newProvider); await assetRegistry.update(asset); }
问题4:交易参与者权限不足
如果执行交易的参与者没有该资产的UPDATE权限,Composer会直接拒绝更新操作。
检查权限规则(permissions.acl):
确保参与者拥有更新资产的权限:
rule AllowAssetUpdate { description: "Allow authorized participants to update assets" participant: "org.example.network.YourParticipantType" operation: UPDATE resource: "org.example.network.Asset" condition: (true) }
问题5:新Provider未注册到参与者注册表
如果你的newProvider是新创建的参与者,必须先将其注册到参与者注册表,才能关联到资产上。
补充注册逻辑:
async function addProviderToAsset(tx) { // 先注册新Provider(如果是首次创建) const providerRegistry = await getParticipantRegistry('org.example.network.Provider'); await providerRegistry.add(tx.newProvider); // 再更新资产 const assetRegistry = await getAssetRegistry('org.example.network.Asset'); const asset = await assetRegistry.get(tx.targetAsset.assetId); if (!asset.providers) { asset.providers = []; } asset.providers.push(tx.newProvider); await assetRegistry.update(asset); }
你可以按照这个顺序逐一排查,先从模型定义和数组初始化这两个最常见的坑入手,应该能解决问题。
内容的提问来源于stack exchange,提问作者Yorman Rivero

