如何在Hyperledger Fabric Go链码中获取指定State的创建者证书
Hyperledger Fabric Go链码获取指定State创建者证书的实现方案
原生Fabric Go链码没有提供直接查询指定State对应创建者证书的内置接口,底层账本存储State时仅保留键、值、版本三个核心字段,不会默认存储创建者身份信息,你需要自行在链码逻辑中实现身份关联存储,具体实现方式如下:
- 方案1:将创建者信息嵌入State结构体
在State首次写入的创建逻辑中,将当前调用者的证书存入State的自定义结构中,后续查询时直接读取即可,示例代码:
// 自定义资产结构体,新增创建者证书字段 type CustomAsset struct { ID string `json:"id"` Content string `json:"content"` CreatorCert []byte `json:"creator_cert"` } // 资产创建方法 func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, assetId string, content string) error { // 获取当前交易提交者(即资产创建者)的身份信息 creator, err := ctx.GetClientIdentity().GetCreator() if err != nil { return fmt.Errorf("failed to get creator identity: %v", err) } asset := CustomAsset{ ID: assetId, Content: content, CreatorCert: creator, } assetJson, err := json.Marshal(asset) if err != nil { return fmt.Errorf("failed to marshal asset: %v", err) } return ctx.GetStub().PutState(assetId, assetJson) } // 自定义GetStateCreator方法 func (s *SmartContract) GetStateCreator(ctx contractapi.TransactionContextInterface, key string) ([]byte, error) { assetJson, err := ctx.GetStub().GetState(key) if err != nil { return nil, fmt.Errorf("failed to get state: %v", err) } if assetJson == nil { return nil, fmt.Errorf("state %s not found", key) } var asset CustomAsset if err = json.Unmarshal(assetJson, &asset); err != nil { return nil, fmt.Errorf("failed to unmarshal asset: %v", err) } return asset.CreatorCert, nil }
- 方案2:通过复合键单独存储State与创建者的映射
如果不希望证书字段占用State的存储体积,可以使用Fabric的复合键单独存映射关系,避免每次查询State都返回冗余的证书信息:
// 创建资产时同步写入映射关系 func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, assetId string, content string) error { // 获取创建者身份 creator, err := ctx.GetClientIdentity().GetCreator() if err != nil { return fmt.Errorf("failed to get creator identity: %v", err) } // 写入资产本身 asset := map[string]string{ "id": assetId, "content": content, } assetJson, err := json.Marshal(asset) if err != nil { return err } if err = ctx.GetStub().PutState(assetId, assetJson); err != nil { return err } // 创建复合键存储创建者映射 creatorMapKey, err := ctx.GetStub().CreateCompositeKey("creatorMapping", []string{assetId}) if err != nil { return err } return ctx.GetStub().PutState(creatorMapKey, creator) } // 自定义GetStateCreator方法 func (s *SmartContract) GetStateCreator(ctx contractapi.TransactionContextInterface, key string) ([]byte, error) { creatorMapKey, err := ctx.GetStub().CreateCompositeKey("creatorMapping", []string{key}) if err != nil { return nil, err } creator, err := ctx.GetStub().GetState(creatorMapKey) if err != nil { return nil, err } if creator == nil { return nil, fmt.Errorf("creator info for state %s not found", key) } return creator, nil }
注意:如果是已经上线且历史State未关联存储创建者信息的场景,无法通过链码接口直接回溯获取创建者身份,仅能通过解析区块交易的读写集来关联State与对应交易的提交者。
内容的提问来源于stack exchange,提问作者Shuhan Mirza
相关产品推荐
相关产品推荐

