更新Fabric通道添加管理员时遇DeltaSet策略缺失错误求助
尝试更新appchannel通道添加新管理员(原管理员证书即将过期),执行附带的交易信封时触发以下错误:
error authorizing update: error validating DeltaSet: unexpected missing policy for item [Group] /Channel
附带的交易信封payload内容:
{"payload": {"header": {"channel_header": {"channel_id": "appchannel","type": 2}},"data": {"config_update": {"channel_id": "appchannel","isolated_data": {},"read_set": {"groups": {},"mod_policy": "","policies": {},"values": {},"version": "0"},"write_set": {"groups": {"Application": {"groups": {"appMSP": {"groups": {},"mod_policy": "Admins","policies": {"Admins": {"mod_policy": "Admins","policy": {"type": 1,"value": {"identities": [{"principal": {"msp_identifier": "appMSP","role": "ADMIN"},"principal_classification": "ROLE"}],"rule": {"n_out_of": {"n": 1,"rules": [{"signed_by": 0}]}},"version": 0}},"version": "1"},"Readers": {"mod_policy": "Admins","policy": {"type": 1,"value": {"identities": [{"principal": {"msp_identifier": "appMSP","role": "MEMBER"},"principal_classification": "ROLE"}],"rule": {"n_out_of": {"n": 1,"rules": [{"signed_by": 0}]}},"version": 0}},"version": "1"},"Writers": {"mod_policy": "Admins","policy": {"type": 1,"value": {"identities": [{"principal": {"msp_identifier": "appMSP","role": "MEMBER"},"principal_classification": "ROLE"}],"rule": {"n_out_of": {"n": 1,"rules": [{"signed_by": 0}]}},"version": 0}},"version": "1"}},"values": {"MSP": {"mod_policy": "Admins","value": {"config": {"admins": ["admincert1","admincert2"],"crypto_config": {"identity_identifier_hash_function": "SHA256","signature_hash_family": "SHA2"},"fabric_node_ous": null,"intermediate_certs": [],"name": "appMSP","organizational_unit_identifiers": [],"revocation_list": [],"root_certs": ["rootcert"],"signing_identity": null,"tls_intermediate_certs": [],"tls_root_certs": ["tlsrootcert"]},"type": 0},"version": "1"}},"version": "1"}},"mod_policy": "Admins","policies": {"Admins": {"mod_policy": "Admins","policy": {"type": 3,"value": {"rule": "ANY","sub_policy": "Admins"}},"version": "1"},"Readers": {"mod_policy": "Admins","policy": {"type": 3,"value": {"rule": "ANY","sub_policy": "Readers"}},"version": "1"},"Writers": {"mod_policy": "Admins","policy": {"type": 3,"value": {"rule": "ANY","sub_policy": "Writers"}},"version": "1"}},"values": {},"version": "1"},"Orderer": {"groups": {"appMSP": {"groups": {},"mod_policy": "Admins","policies": {"Admins": {"mod_policy": "Admins","policy": {"type": 1,"value": {"identities": [{"principal": {"msp_identifier": "appMSP","role": "ADMIN"},"principal_classification": "ROLE"}],"rule": {"n_out_of": {"n": 1,"rules": [{"signed_by": 0}]}},"version": 0}},"version": "1"},"Readers": {"mod_policy": "Admins","policy": {"type": 1,"value": {"identities": [{"principal": {"msp_identifier": "appMSP","role": "MEMBER"},"principal_classification": "ROLE"}],"rule": {"n_out_of": {"n": 1,"rules": [{"signed_by": 0}]}},"version": 0}},"version": "1"},"Writers": {"mod_policy": "Admins","policy": {"type": 1,"value": {"identities": [{"principal": {"msp_identifier": "appMSP","role": "MEMBER"},"principal_classification": "ROLE"}],"rule": {"n_out_of": {"n": 1,"rules": [{"signed_by": 0}]}},"version": 0}},"version": "1"}},"values": {"MSP": {"mod_policy": "Admins","value": {"config": {"admins": ["admincert1","admincert2"],"crypto_config": {"identity_identifier_hash_function": "SHA256","signature_hash_family": "SHA2"},"fabric_node_ous": null,"intermediate_certs": [],"name": "appMSP","organizational_unit_identifiers": [],"revocation_list": [],"root_certs": ["rootcert"],"signing_identity": null,"tls_intermediate_certs": [],"tls_root_certs": ["tlsrootcert"]},"type": 0},"version": "1"}},"version": "1"}},"mod_policy": "Admins","policies": {"Admins": {"mod_policy": "Admins","policy": {"type": 3,"value": {"rule": "MAJORITY","sub_policy": "Admins"}},"version": "1"},"BlockValidation": {"mod_policy": "Admins","policy": {"type": 3,"value": {"rule": "ANY","sub_policy": "Writers"}},"version": "1"},"Readers": {"mod_policy": "Admins","policy": {"type": 3,"value": {"rule": "ANY","sub_policy": "Readers"}},"version": "1"},"Writers": {"mod_policy": "Admins","policy": {"type": 3,"value": {"rule": "ANY","sub_policy": "Writers"}},"version": "1"}},"values": {"BatchSize": {"mod_policy": "Admins","value": {"absolute_max_bytes": 103809024,"max_message_count": 10,"preferred_max_bytes": 524288},"version": "1"},"BatchTimeout": {"mod_policy": "Admins","value": {"timeout": "300ms"},"version": "1"},"ChannelRestrictions": {"mod_policy": "Admins","value": null,"version": "1"},"ConsensusType": {"mod_policy": "Admins","value": {"metadata": {"consenters": [{"client_tls_cert": "cert","host": "172.31.7.199","port": 7050,"server_tls_cert": "cert"},{"client_tls_cert": "cert","host": "172.31.15.15","port": 7050,"server_tls_cert": "cert"},{"client_tls_cert": "cert","host": "172.31.8.195","port": 7050,"server_tls_cert": "cert"}],"options": {"election_tick": 10,"heartbeat_tick": 1,"max_inflight_blocks": 5,"snapshot_interval_size": 20971520,"tick_interval": "500ms"}},"state": "STATE_NORMAL","type": "etcdraft"},"version": "1"}},"version": "1"}},"mod_policy": "Admins","policies": {"Admins": {"mod_policy": "Admins","policy": {"type": 3,"value": {"rule": "ANY","sub_policy": "Admins"}},"version": "1"},"Readers": {"mod_policy": "Admins","policy": {"type": 3,"value": {"rule": "ANY","sub_policy": "Readers"}},"version": "1"},"Writers": {"mod_policy": "Admins","policy": {"type": 3,"value": {"rule": "ANY","sub_policy": "Writers"}},"version": "1"}},"values": {"BlockDataHashingStructure": {"mod_policy": "Admins","value": {"width": 4294967295},"version": "1"},"Consortium": {"mod_policy": "Admins","value": {"name": "appConsortium"},"version": "1"},"HashingAlgorithm": {"mod_policy": "Admins","value": {"name": "SHA256"},"version": "1"},"OrdererAddresses": {"mod_policy": "/Channel/Orderer/Admins","value": {"addresses": ["172.31.7.199:7050","172.31.15.15:7050","172.31.8.195:7050"]},"version": "1"}},"version": "1"}}}}
从提供的config_update内容来看,read_set完全为空(groups、policies、values都是空对象,mod_policy为空字符串)。Fabric的配置更新机制要求read_set必须包含当前通道配置中与更新内容相关的部分,用来验证更新的合法性——系统需要对比当前配置和要写入的配置,确认更新符合通道的策略规则。
当read_set为空时,系统无法获取/Channel组的现有策略信息,因此触发unexpected missing policy for item [Group] /Channel错误。
获取当前通道的完整配置
先拉取通道配置块,再导出为JSON格式:peer channel fetch config config_block.pb -c appchannel -o <orderer-address> configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json修改配置添加新管理员
复制config.json为modified_config.json,找到/Channel/Application/appMSP/values/MSP/config/admins字段,将新管理员证书内容添加到数组中。生成合法的config_update
使用configtxlator计算配置差异,生成包含合法read_set的更新文件:# 将配置转为proto格式 configtxlator proto_encode --input config.json --type common.Config --output config.pb configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb # 计算配置更新差异 configtxlator compute_update --channel_id appchannel --original config.pb --updated modified_config.pb --output config_update.pb # 转回JSON格式 configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate | jq . > config_update.json封装交易信封并提交
将配置更新封装为可提交的交易信封,由现有管理员签名后提交:# 封装为Envelope格式 echo '{"payload":{"header":{"channel_header":{"channel_id":"appchannel","type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb # 提交更新 peer channel update -f config_update_in_envelope.pb -c appchannel -o <orderer-address>
内容的提问来源于stack exchange,提问作者Bentipe

