Hyperledger Fabric链码:如何在CouchDB存储含_executor字段的键值对
在Hyperledger Fabric链码中给CouchDB状态添加自定义字段的实现方法
核心结论
必须修改链码的set方法,Docker调用命令可按需调整(若不想从Key提取字段值,可新增参数),需求完全可行。
问题根源
当前你用stub.PutState直接存储字符串值,CouchDB会将非JSON格式的二进制数据存入_attachments附件中,无法直接添加自定义字段。要实现需求,需将数据与额外字段封装成JSON对象后再存储,这样CouchDB会直接解析为文档字段,而非附件形式。
具体实现方案
方案一:从现有Key中提取_executor值
你的Key格式为[D1]{P1},可直接从中解析出{P1}作为_executor的值,无需修改调用命令。修改后的链码代码如下:
import ( "encoding/json" "fmt" "strings" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/protos/peer" ) func (s *SmartContract) set(stub shim.ChaincodeStubInterface, args []string) peer.Response { if len(args) != 2 { return shim.Error("参数错误:需要传入key和value两个参数") } key := args[0] rawValue := args[1] // 从Key中解析_executor字段值 executor := "" startPos := strings.Index(key, "{") endPos := strings.Index(key, "}") if startPos == -1 || endPos == -1 || endPos <= startPos { return shim.Error("无法从指定Key中解析_executor字段") } executor = key[startPos : endPos+1] // 定义包含自定义字段的资产结构体 type StoredAsset struct { Value string `json:"value"` Executor string `json:"_executor"` } // 初始化结构体并序列化为JSON asset := StoredAsset{ Value: rawValue, Executor: executor, } assetJSON, err := json.Marshal(asset) if err != nil { return shim.Error(fmt.Sprintf("序列化资产数据失败:%v", err)) } // 存储JSON格式的状态数据 err = stub.PutState(key, assetJSON) if err != nil { return shim.Error(fmt.Sprintf("存储资产[%s]失败:%v", key, err)) } return shim.Success(assetJSON) }
方案二:通过调用命令传递_executor参数
如果不想依赖Key解析,可修改set方法接收第三个参数,同时调整Docker调用命令:
修改后的调用命令:
docker exec -t Lane1_Zf4URs_cli peer chaincode invoke -o orderer.Zf4URs.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/Zf4URs.com/orderers/orderer.Zf4URs.com/msp/tlscacerts/tlsca.Zf4URs.com-cert.pem -C mychannel -n 9bc7cca8-1dcd-49b0-a25c-fb639a0403cf -c '{"Args":["set", "[D1]{P1}", "data4", "{P1}"]}'
对应链码修改:
import ( "encoding/json" "fmt" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/protos/peer" ) func (s *SmartContract) set(stub shim.ChaincodeStubInterface, args []string) peer.Response { if len(args) != 3 { return shim.Error("参数错误:需要传入key、value和_executor三个参数") } key := args[0] rawValue := args[1] executor := args[2] type StoredAsset struct { Value string `json:"value"` Executor string `json:"_executor"` } asset := StoredAsset{ Value: rawValue, Executor: executor, } assetJSON, err := json.Marshal(asset) if err != nil { return shim.Error(fmt.Sprintf("序列化资产数据失败:%v", err)) } err = stub.PutState(key, assetJSON) if err != nil { return shim.Error(fmt.Sprintf("存储资产[%s]失败:%v", key, err)) } return shim.Success(assetJSON) }
存储效果
修改后,CouchDB中存储的文档将直接包含自定义字段,格式如下(不再有_attachments):
{
"_id": "[D1]{P1}",
"_rev": "2-a74269cadec50f97d34d165d60235e34",
"~version": "8:0",
"value": "data4",
"_executor": "{P1}"
}
可行性说明
Hyperledger Fabric原生支持存储JSON格式的状态数据,CouchDB作为支持富查询的状态数据库,会自动解析JSON文档并识别自定义字段,该方案完全符合Fabric的设计规范,可正常运行。
内容的提问来源于stack exchange,提问作者sebi
相关产品推荐
相关产品推荐

