华为云用户手册

  • 响应示例 状态码: 200 Success { "transaction_summary" : { "block_number" : 29, "transaction_id" : "6d704b217e17e16de71029b70f17a1ced35c055279f655dfd096bebf978a0546", "channelName" : "channel", "creator_msp" : "282f3c713ea1cec646aa7c640defca9c4f64bd88MSP", "type" : "ENDORSER_TRANSACTION", "chaincode_name" : "kvtest", "chaincode_version" : "1.0", "timestamp" : "2021-01-20T19:30:28+08:00", "organization_name" : "organization" }, "validation_code" : "VALID", "endorser_organizations" : [ "282f3c713ea1cec646aa7c640defca9c4f64bd88MSP" ], "proposal_hash" : "k1h2ewweWGrWNmmcu7UvzJ8Aw2G190SQzV+lBAAl4gw=", "read_set" : { "kvtest" : null, "lscc" : [ { "key" : "kvtest", "version" : { "block_num" : 2 } } ] }, "write_set" : { "kvtest" : [ { "key" : "a1", "is_delete" : false, "value" : "1" } ], "lscc" : [ ] }} 状态码: 400 Bad Request { "error_code" : "BCS.4000013", "error_message" : "request body is too large"}
  • 请求示例 { "orgID" : "4f1439758ebb41f7411b5f684b67713c08b89198", "channelID" : "mychannel", "cryptoMethod" : "SW", "cert" : "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----", "sk" : "------BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY-----", "timestamp" : "2020-10-27T17:28:16+08:00", "did" : "did:example:ebfeb1f712ebc6f1c276e12ec21"}
  • 响应示例 状态码: 200 分布式身份文档结构体 { "context" : "https://www.w3.org/ns/did/v1", "id" : "did:example:ebfeb1f712ebc6f1c276e12ec21", "publicKey" : [ { "id" : "string", "type" : "string", "controller" : "string", "publicKeyPem" : "string" } ], "authentication" : [ "did:example:ebfeb1f712ebc6f1c276e12ec21#key-0" ], "recovery" : "string", "service" : [ { "id" : "did:example:ebfeb1f712ebc6f1c276e12ec21#xdi", "type" : "XdiService", "serviceEndpoint" : "https://xdi.example.com/8377464", "credentialApplySchema" : { "type" : "LegalCitizen", "name" : "LegalCitizen", "description" : "Certified Chinese citizens", "attributes" : [ { "name" : "name", "type" : "someType", "description" : "Identity number" } ] } } ], "proof" : { "creator" : "did:example:ebfeb1f712ebc6f1c276e12ec21", "type" : "RsaSignature2018", "created" : "1606720551", "signatureValue" : "eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0I PAYuNzVBAh4vGHSrQyHUdBBPM" }, "created" : "1588921521", "updated" : "", "status" : "active"} 状态码: 500 失败响应 { "errorCode" : "BCS.5002034", "errorMsg" : "request timed out or been cancelled"}
  • 响应参数 状态码: 200 表2 响应Body参数 参数 参数类型 描述 context String context id String 分布式身份标识 publicKey Array of DocPublicKey objects 公钥列表 authentication Array of strings did主公钥标识 recovery String 备用公钥标识,可用于修改主密钥 service Array of Service objects 服务列表 proof Proof object 证明结构,可为空 created String 创建时间 updated String 更新时间 status String 状态 表3 DocPublicKey 参数 参数类型 描述 id String 公钥标识 type String 公钥类型 controller String 公钥的控制者标识 publicKeyPem String 公钥证书 表4 Service 参数 参数类型 描述 id String 服务标识 type String 服务类型 serviceEndpoint String 服务介绍网址 credentialApplySchema CredentialApplySchema object 申请凭证所需数据的Schema 表5 CredentialApplySchema 参数 参数类型 描述 type String 类型 name String 名称 description String 描述信息 attributes Array of Attribute objects 属性列表 表6 Attribute 参数 参数类型 描述 name String 名称 type String 类型 description String 描述信息 表7 Proof 参数 参数类型 描述 creator String 创建者身份标识 type String 签名类型 created String 签名创建时间 signatureValue String 签名值 状态码: 500 表8 响应Body参数 参数 参数类型 描述 errorCode String 错误码 最小长度:8 最大长度:36 errorMsg String 错误描述 最小长度:2 最大长度:512
  • 请求参数 表1 请求Body参数 参数 是否必选 参数类型 描述 orgID 是 String 组织id channelID 是 String 通道id cryptoMethod 是 String 加密方法,目前固定为SW cert 是 String 用户证书,每行末尾均需要增加显式换行符\n sk 是 String 用户私钥,每行末尾均需要增加显式换行符\n timestamp 是 String 时间戳 did 是 String 分布式身份标识
  • 请求示例 { "orgID" : "ce0ac69b0c8648cd25b44a551780409767c8890b", "channelID" : "mychannel", "cryptoMethod" : "SW", "cert" : "-----BEGIN CERTIFICATE-----\\n...\\n-----END CERTIFICATE-----", "sk" : "-----BEGIN PRIVATE KEY-----\\n...\\n-----END PRIVATE KEY-----", "timestamp" : "2020-10-27T17:28:16+08:00", "provider" : "did:example:DHkJjyD5wZwya6sd6BNBnG", "providerName" : "huawei", "productName" : "prodname", "productID" : "product2", "sampleUrl" : "http://hwcloud.com/sample.com/prodname2", "sampleSize" : "10KB", "sampleType" : "csv", "sampleName" : "data_sub1", "fileType" : "csv", "dataUrl" : "http://hwcloud.com/prodname2", "dataHash" : "2282ba7a1a2ef5700609214a997d3d4237a03bfd3632c6d089e57e7b6f467969", "dataSize" : "100MB", "dataName" : "mydata1", "description" : "this is my second prod", "plainData" : "base64 encoding string", "consumer" : "did:example:3TMWx8owKHARgNwbj4ywmG", "orderSeq" : "1", "watermarkType" : "string", "file" : "string", "productIDKeywords" : "[{\"value\":\"taiyuan\"},{\"value\":\"renmin_hospital\"},{\"value\":\"medicine\"}]", "onChainStore" : "string", "consumerName" : "string"}
  • 响应示例 状态码: 200 订单信息 { "consumer" : "did:example:3TMWx8owKHARgNwbj4ywmG", "consumerName" : "Tyler", "orderSeq" : "1", "provider" : "did:example:DHkJjyD5wZwya6sd6BNBnG", "providerName" : "hw", "productID" : "product1", "productName" : "prodname1", "price" : "0", "applyTime" : "1607332359", "encryptedAesKey" : "BNGhPwjaTgpM+V7czzw1i4mH21KKN+XLKXHLqVsRIfybUCncqZNfomkRfzX4WEHj+oty1X9oCd4h6xMnRvs8BWE5Tvg6BJ6QTW/km9EO/FSYqzJf2GqQzAleAcLJrTBZ3LRbPaF87CgJ114ae7R+VK9VvfXQ8exuH2KMRD305dXieGpM4VPVv9u1BbL15Jpd/g==", "status" : "ready", "reason" : "I want product1", "lockProof" : "", "encryptData" : "base64 encoding string"} 状态码: 500 失败响应 { "errorCode" : "BCS.5002046", "errorMsg" : "Incorrect number of arguments"}
  • 响应参数 状态码: 200 表6 响应Body参数 参数 参数类型 描述 consumer String 订单消费者身份标识 consumerName String 订单消费者名称 orderSeq String 订单序列号 provider String 订单提供者身份标识 providerName String 订单提供者名称 productID String 数据集产品id productName String 数据集产品名称 price String 订单价钱 applyTime String 订单申请时间 encryptedAesKey String 密钥 status String 订单状态 reason String 订单申请原因 lockProof String 订单锁定证明 creatorDID String 流程创建者DID,如果没有加入任何流程,为“” processID String 当前订单所属流程ID,如果没有加入任何流程,为“” encryptData String base64编码的数据密文 状态码: 500 表7 响应Body参数 参数 参数类型 描述 errorCode String 错误码 errorMsg String 错误描述
  • 调用合约 Main.go是一个简单的客户端应用示例程序,主要是为了方便用户熟悉客户端开发的流程,主要包含以下步骤: //1.导入相关包:Sdk包中提供了一些API,以便用户的应用程序能够访问链代码。import ( "fmt" "github.com/hyperledger/fabric-sdk-go/pkg/client/channel" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" ……)//2.创建文件配置:这部分封装了应用开发必要的一些公共配置,包括sdk配置文件路径、组织名var ( configFile = "/root/fabric-go-demo/config/go-sdk-demo-channel-sdk-config.yaml" org = "9103f17cb6b4f69d75982eb48bececcc51aa3125" ……)//3.加载配置文件loadConfig()//4. 初始化sdkinitializeSdk()//5. 执行链代码,将数据写入账本,key = "testuser",value= "100"insert("insert",[][]byte{ []byte("testuser"), []byte("100"),})//6.查询链代码,输出查询结果,key = "testuser" query("query",[][]byte{[]byte("testuser"),}) 表1 调用函数介绍 函数名 说明 getOptsToInitializeSDK 解析配置文件,创建并返回fabsdk.Option对象。 GetDefaultChaincodeId 解析配置文件,返回chaincodeID。 GetDefaultChannel 解析配置文件,返回channelID。 UserIdentityWithOrgAndName 用户身份验证,输入为组织名和用户名,返回为验证结果。 ChannelClient 创建*channel.Client对象,输入为组织名、用户名以及通道ID,返回*channel.Client对象。 insert 将数据写入账本,输入参数为链码的对应方法名称以及要插入的键值对,返回为写入的结果。 query 查询链上信息,输入参数为链码的对应方法名称以及要查询的数据,返回为查询的结果。
  • 下载SDK和证书 登录区块链服务管理控制台。 在“实例管理”页面,选择“Hyperledger Fabric增强版”页签,单击对应实例卡片上的“获取客户端配置”。 在新打开的页面,勾选“SDK文件”,SDK配置参数如下: 参数 值 链代码名称 chaincode 说明: 链代码名称需要和链代码安装&实例化时的一致。 证书存放路径 /root/gosdkdemo/config 通道名称 channel 组织&Peer节点 保持系统默认 勾选“共识节点证书”。 勾选“Peer节点证书”,指定节点组织选择organization,勾选“管理员证书”。 单击“下载”。下载SDK配置文件、orderer组织的管理员证书和organization组织的管理员证书。
  • 常用API接口 Fabric-sdk-go的主要入口是FabricSDK类,这个可以通过NewSDK()方法分别可以生成。 Fabric-sdk-go的常用操作基本都可以用这四个client实现:FabricClient,ChannelClient,ChannelMgmtClient,ResourceMgmtClient。 FabricSDK FabricSDK在pkg\fabsdk\fabsdk.go中,通过New ()方法生成object。New ()方法支持可变参数Option,以下是生成FabricSDK的例子: var opts []fabsdk.Option opts = append(opts, fabsdk.WithOrgid(org)) opts = append(opts, fabsdk.WithUserName("Admin")) sdk, err = fabsdk.New(config.FromFile(configFile), opts...) configFile是SDK配置文件的路径。OrgId是SDK配置文件中的组织id。 FabricSDK在def/fabapi/fabapi.go中,通过NewSDK()方法生成object。NewSDK()方法有一个Options参数,以下是生成Options参数的例子: deffab.Options{ConfigFile: configFile, LoggerFalogging.LoggerProvider(), UserName: sysadmin} ConfigFile是SDK配置文件的路径。LoggerFactory是可选的,不提供的话default会log到console。 FabricClient FabricClient主要有以下常用的接口。 接口名称 描述 参数值 返回值 CreateChannel 创建Channel的接口,用于创建channel。 request CreateChannelRequest txn.TransactionID, error QueryChannelInfo 查询Channel的接口,用于查询Channel的信息。 name string, peers []Peer Channel, error InstallChaincode 安装链码的接口,安装链码到区块链中。 request InstallChaincodeRequest []*txn.TransactionPropos lResponse, string, error InstallChaincode 安装链码的接口,安装链码到区块链中。 request InstallChaincodeRequest []*txn.TransactionPropos lResponse, string, error QueryChannels 查询channel的接口,查询区块链中已创建的通道。 peer Peer *pb.ChannelQueryResponse, error QueryInstalledChaincodes 查询已安装链码的接口,查询区块链中已安装的链码。 peer Peer *pb.ChaincodeQueryResponse, error ChannelClient ChannelClient主要包括链码查询和链码调用两类接口。 接口名称 描述 参数值 返回值 Query 链码查询接口,调用链码进行查询。 request QueryRequest []byte, error QueryWithOpts 带options的链码查询接口,与Query类似,但是可以通过QueryOpts指定notifier, peers,和timeout。 request QueryRequest, opt QueryOpts []byte, error ExecuteTx 链码调用接口,用于链码的调用。 request ExecuteTxRequest TransactionID, error ExecuteTxWithOpts 带options的链码调用接口,与ExecuteTx类似,但是可以通过ExecuteTxOpts指定notifier, peers,和timeout。 request ExecuteTxRequestopt ExecuteTxOpts TransactionID, error ChannelMgmtCLient ChannelMgmtClient 只有两个接口SaveChannel(req SaveChannelRequest) error 和SaveChannelWithOpts(req SaveChannelRequest, opts SaveChannelOpts) error 这两个接口是用于创建channel用的,这两个接口里面具体实现会调用到FabricClient里createChannel()接口。 ResourceMgmtClient ResourceMgmtClient主要就是与链码生命周期相关的接口和一个peer加入通道的接口。 链码的删除接口为BCS增加的接口,目前只实现了删除链码安装包的功能。 接口名称 描述 参数值 返回值 InstallCC 安装链码,用于安装链码。 reqInstallCCRequest []InstallCCResponse, error InstallCCWithOpts 带options的链码安装,与InstallCC类似,但是可以通过InstallCCOpts指定peers。 reqInstallCCRequest,opts InstallCCOpts []InstallCCResponse, error InstantiateCC 实例化链码接口,用于实例化链码。 channelID string,reqInstantiateCCRequest error InstantiateCCWithOpts 带options的链码实例化,与InstantiateCC类似,但是可以通过InstantiateCCOpts指定peers和timeout。 channelID string,reqInstantiateCCRequest, optsInstantiateCCOpts error UpgradeCC 升级链码,用于链码的升级。 channelID string,reqUpgradeCCRequest error UpgradeCCWithOpts 带options的链码升级,与UpgradeCC类似,但是可以通过UpgradeCCOpts指定peers和timeout。 channelID string,reqUpgradeCCRequest, optsUpgradeCCOpts error DeleteCC 删除链码,用于链码的删除,目前只有删除安装包的功能。 channelID string,reqDeleteCCRequest error DeleteCCWithOpts 带options的链码删除,与DeleteCC类似,但是可以通过DeleteCCWithOpts指定peers和timeout。 channelID string,reqDeleteCCRequest,opts DeleteCCOpts error JoinChannel Peers加入Channel的接口,用于peers加入Channel。 channelID string error JoinChannelWithOpts 带options的Peers加入Channel的接口,与JoinChannel类似,但是可以通过JoinChannelOpts指定peers。 channelID string,optsJoinChannelOpts error 带options的接口都可以指定peers,peers可通过def/fabapi/pkgfactory.go 里的NewPeer(userName string, orgName string, url string, certificate string, serverHostOverride string, config config.Config) (fab.Peer, error) 生成。这个method比原生的NewPeer多两个参数userName, orgName, 这两个参数用于peer双向tls找到对应的tls证书。
  • 通过内存传入私钥 如果用户需要对私钥文件进行加密,并在demo中解密后传入FabricSDK。 对于TLS私钥 在main.go文件的initializeSdk函数中,按如下方式调用函数: encryptedtlsKey,err := GetTlsCryptoKey(org) //从配置文件指定路径下读取加密过的TLS私钥//用户按照自行规定的加解密方法对encryptedtlsKey进行解密得到decryptedTlsKey字符串SetClientTlsKey(decryptedTlsKey) //将解密后的TLS私钥传入Fabric-SDK,实现通过内存传入TLSKey 对于MSP私钥 在main.go文件的insert函数中,按如下方式调用函数: encryptedbytekey,_:= GetPrivateKeyBytes(org) //从配置文件指定路径下读取加密过的MSP私钥//用户按照自行规定的加解密方法对encryptedbytekey进行解密得到decryptedKey字符串SetPrivateKey(decryptedKey) //将解密后的MSP私钥赋值给全局变量privateKey并通过该变量传入
  • 请求示例 { "orgID" : "4f1439758ebb41f7411b5f684b67713c08b89198", "channelID" : "mychannel", "cryptoMethod" : "SW", "cert" : "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----", "sk" : "------BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY-----", "timestamp" : "2020-10-27T17:28:16+08:00", "orderIndex" : 1}
  • 响应示例 状态码: 200 VCOrder Information { "applyer" : "string", "orderSeq" : "string", "applyTime" : "string", "price" : "string", "status" : "string", "service" : "string", "reason" : "string", "dataUri" : "string", "encryptedAesKey" : "string", "uriType" : "string", "dataHash" : "string", "lockProof" : "string", "vcIndex" : "string"} 状态码: 500 失败响应 { "errorCode" : "stringst", "errorMsg" : "string"}
  • 响应参数 状态码: 200 表2 响应Body参数 参数 参数类型 描述 applyer String 申请者身份标识 orderSeq String 订单序列号 applyTime String 申请时间 price String 价格 status String 状态 service String 服务 reason String 理由信息 dataUri String 凭证数据URI encryptedAesKey String 加密的AES密钥 uriType String URI类型 dataHash String 数据的hash lockProof String 锁定证明 vcIndex String 凭证索引 状态码: 500 表3 响应Body参数 参数 参数类型 描述 errorCode String 错误码 最小长度:8 最大长度:36 errorMsg String 错误描述 最小长度:2 最大长度:512
  • 链代码示例(1.4风格) Fabric架构版本的区块链实例: 如下是一个账户转账的链代码示例(1.4风格)仅供安装实例化,若您需要调测请参考Fabric官方示例中的链代码。 package main import ( "fmt" "strconv" "github.com/hyperledger/fabric/core/chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer" )type SimpleChaincode struct {}// 初始化数据状态,实例化/升级链代码时被自动调用func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {// println函数的输出信息会出现在链代码容器的日志中fmt.Println("ex02 Init")// 获取用户传递给调用链代码的所需参数_, args := stub.GetFunctionAndParameters()var A, B string // 两个账户var Aval, Bval int // 两个账户的余额var err error// 检查合法性, 检查参数数量是否为4个, 如果不是, 则返回错误信息if len(args) != 4 {return shim.Error("Incorrect number of arguments. Expecting 4")}A = args[0] // 账户A用户名Aval, err = strconv.Atoi(args[1]) // 账户A余额if err != nil {return shim.Error("Expecting integer value for asset holding")}B = args[2] // 账户B用户名Bval, err = strconv.Atoi(args[3]) // 账户B余额if err != nil {return shim.Error("Expecting integer value for asset holding")}fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)// 将账户A的状态写入账本中err = stub.PutState(A, []byte(strconv.Itoa(Aval)))if err != nil {return shim.Error(err.Error())}// 将账户B的状态写入账本中err = stub.PutState(B, []byte(strconv.Itoa(Bval)))if err != nil {return shim.Error(err.Error())}return shim.Success(nil)}// 对账本数据进行操作时(query, invoke)被自动调用func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {fmt.Println("ex02 Invoke")// 获取用户传递给调用链代码的函数名称及参数function, args := stub.GetFunctionAndParameters()// 对获取到的函数名称进行判断if function == "invoke" {// 调用 invoke 函数实现转账操作return t.invoke(stub, args)} else if function == "delete" {// 调用 delete 函数实现账户注销return t.delete(stub, args)} else if function == "query" {// 调用 query 实现账户查询操作return t.query(stub, args)}// 传递的函数名出错,返回 shim.Error()return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"")}// 账户间转钱func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {var A, B string // 账户A和Bvar Aval, Bval int // 账户余额var X int // 转账金额var err errorif len(args) != 3 {return shim.Error("Incorrect number of arguments. Expecting 3")}A = args[0] // 账户A用户名B = args[1] // 账户B用户名// 从账本中获取A的余额Avalbytes, err := stub.GetState(A)if err != nil {return shim.Error("Failed to get state")}if Avalbytes == nil {return shim.Error("Entity not found")}Aval, _ = strconv.Atoi(string(Avalbytes))// 从账本中获取B的余额Bvalbytes, err := stub.GetState(B)if err != nil {return shim.Error("Failed to get state")}if Bvalbytes == nil {return shim.Error("Entity not found")}Bval, _ = strconv.Atoi(string(Bvalbytes))// X为转账金额X, err = strconv.Atoi(args[2])if err != nil {return shim.Error("Invalid transaction amount, expecting a integer value")}// 转账Aval = Aval - XBval = Bval + Xfmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)// 更新转账后账本中A余额err = stub.PutState(A, []byte(strconv.Itoa(Aval)))if err != nil {return shim.Error(err.Error())}// 更新转账后账本中B余额err = stub.PutState(B, []byte(strconv.Itoa(Bval)))if err != nil {return shim.Error(err.Error())}return shim.Success(nil)}// 账户注销func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {if len(args) != 1 {return shim.Error("Incorrect number of arguments. Expecting 1")}A := args[0] // 账户用户名// 从账本中删除该账户状态err := stub.DelState(A)if err != nil {return shim.Error("Failed to delete state")}return shim.Success(nil)}// 账户查询func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {var A stringvar err errorif len(args) != 1 {return shim.Error("Incorrect number of arguments. Expecting name of the person to query")}A = args[0] // 账户用户名// 从账本中获取该账户余额Avalbytes, err := stub.GetState(A)if err != nil {jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"return shim.Error(jsonResp)}if Avalbytes == nil {jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"return shim.Error(jsonResp)}jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"fmt.Printf("Query Response:%s\n", jsonResp)// 返回转账金额return shim.Success(Avalbytes)}func main() {err := shim.Start(new(SimpleChaincode))if err != nil {fmt.Printf("Error starting Simple chaincode: %s", err)}} 父主题: Go语言链代码开发
  • 请求参数 表1 请求Body参数 参数 是否必选 参数类型 描述 orgID 是 String 组织id channelID 是 String 通道id cryptoMethod 是 String 加密方法,目前固定为SW cert 是 String 用户证书,每行末尾均需要增加显式换行符\n sk 是 String 用户私钥,每行末尾均需要增加显式换行符\n timestamp 是 String 时间戳 orderIndex 是 String 订单索引
  • 配置应用 在“实例管理”界面,在实例卡片中,单击“获取客户端配置”。 勾选“Peer节点证书”,指定节点组织选择organization,勾选“用户证书”并下载。 下载Demo项目工程:fabric-restapi-demo.zip,并将Demo项目代码工程包下载解压到本地并使用IDE打开。 本Demo是一个golang编写的REST客户端,通过RESTAPI服务来调用链代码,实现链代码a给b转账的功能,请用GoLand等个人喜欢的IDE打开。项目的内容如下图所示: 将下载的用户证书解压到项目的usercrypto目录下。如图所示: 修改参数配置。 修改config目录下conf.yaml中的各项参数,参考如下截图及表格。 修改src/restapi目录下的main.go文件,参考如下截图及表格。 针对需要参与背书的每个peer节点,对其构造一个OrgPeer结构体,将组织ID和peer节点的域名传入,并将该结构体添加进OrgPeer类型的数组中,经json.Marshal()方法转换为字节数组,最后会转换成字符串类型传入。其中OrgPeer结构体定义如下: type OrgPeer struct { OrgId string `json:"orgId"` PeerDomainName string `json:"peerDomainName"` } 表4 参数表 参数 说明 Endpoint RESTAPI服务的访问IP和端口。具体获取方法如下: 在已购买区块链实例卡片中,单击“容器集群”名称,进入云容器引擎CCE页面。 单击实例所在集群名称,进入集群信息页面。在左侧导航栏,单击“工作负载”。 在“无状态负载”页签,单击baas-restapi工作负载名称,进入详情页面,然后单击实例所在节点跳转至节点管理页面获取节点的弹性公网ip,该弹性公网ip为RESTAPI服务访问IP,端口固定为32621。 Path RESTAPI服务的访问路径,保持不变。 CryptoMethod 加密算法,如果是ECDSA算法填写“SW”。 SignCert 用户下载的证书中的签名证书路径。 PrvKey 用户下载证书中的签名私钥。 InvokeReq 请求body的参数,请按照部署的链码实际情况填写,可参考如下InvokeReq参数表。 QueryReq 与InvokeReq类似,按照部署链码的实际情况填写。 表5 InvokeReq参数表 参数 说明 范例 SignGzipSwitch Sign是否选择Gzip压缩。0表示否,1表示是。 "1" ChannelId 区块链通道名称。 "channel" ChaincodeId 链代码名称。 "testcode" ChaincodeVersion 链代码版本。 "1.0" UserId 由组织CA签发的用户ID,目前区块链实例默认生成的都为User1。 "User1" OrgId 区块链组织ID。 说明: 在“通道管理”页面中,单击通道名称后的“查看节点”,查看“MSP标识”,去掉MSP即为区块链组织ID。例如:MSP标识为"1232b2032faafee152b58cd82cecf52e49a22a38MSP",区块链组织ID为"1232b2032faafee152b58cd82cecf52e49a22a38”。 "1232b2032faafee152b58cd82cecf52e49a22a38" OrgPeers 各个Peer节点的组织ID和域名。 "[{OrgId:" 1232b2032faafee152b58cd82cecf52e49a22a38", PeerDomainName:"peer-1232b2032faafee152b58cd82cecf52e49a22a38-0 .peer-1232b2032faafee152b58cd82cecf52e49a22a38.default.svc.cluster.local "}]" Opmethod 区块链链码调用类型,目前只有两类:invoke和query。 "invoke" Args 链码调用参数。 '["invoke","a","b","100"]' (第一个参数为invoke的调用函数,可以是其他值如:move,query等等) 配置完成后,构建并运行main()来运行该Demo项目。 代码中将读取conf.yaml以及main.go中的参数QueryReq和InvokeReq请求,并调用RESTAPI的接口"/v1/chaincode/operation"来调用链代码,实现a给b转账功能。运行结果如下: 本Demo用一个简单的REST客户端调用RESTAPI服务实现了调用链代码,返回的invoke结果为一个base64加密的TransactionID,query结果为base64加密的数据值。代码仅供参考,可以通过该项目代码理解如何调用RESTAPI服务。
  • 创建区块链实例 登录区块链服务管理控制台。 单击Hyperledger Fabric增强版卡片上的“购买”。 根据界面提示,配置区块链基本信息,参数如表1所示。 为了保证示例Demo成功运行,请在参数配置时按照表格中的参数值填写。 表1 基本信息配置 参数 参数值 计费模式 按需计费 区域 使用默认区域 企业项目 default 区块链实例名称 demo 版本类型 基础版 区块链类型 私有链 Hyperledger Fabric增强版内核 v2.2 共识策略 Raft(CFT) 资源初始密码 请自行设置 资源初始密码确认 请自行设置 单击“下一步:资源配置”,进行资源配置,参数如表2所示。 表2 资源配置 参数 示例 环境资源 选择“自定义环境”。 集群 创建新的CCE集群 可用区 请自行选择 云主机规格 4核/8GB 云主机个数 1 高可用 否 虚拟私有云 系统自动创建VPC 所在子网 系统自动创建子网 云主机登录方式 密码 root密码 如果填写该项,则以填写值为准,如果不填写,则以资源初始密码为准。 确认密码 - 是否使用CCE集群节点弹性IP 是 弹性IP计费方式 使用默认规格 弹性IP带宽 5 Mbit/s 单击“下一步:区块链配置”,进行区块链配置,参数如表3所示。 表3 区块链配置 参数 示例 区块链配置 选择“自定义配置”。 区块链管理初始密码 如果填写该项,则以填写值为准,如果不填写,则以资源初始密码为准。 区块链管理确认密码 - 存储卷类型 极速文件存储卷 节点组织存储容量 (GB) 使用默认规格。 账本数据存储方式 选择“文件数据库(GoLevelDB)” peer节点组织 系统已默认创建1个节点组织,名称为organization,将节点数量修改为1。 通道配置 organization节点组织已默认添加进至通道中,保持默认即可。 共识节点数量 使用默认值。 安全机制 ECDSA 须知: 安全机制仅支持选择ECDSA。 区块生成配置 否 添加RESTful API支持 请选择“是”。若您选择了“否”,则需要在实例创建完毕后,执行以下步骤安装RESTful API: 左侧导航栏选择“插件管理”。 在“插件仓库”页签下,鼠标移至baas-restapi插件卡片右上角。 单击“安装”,选择已购买的区块链实例,安装baas-restapi插件。 单击“下一步:确认订单”。 确认配置信息无误后,根据界面提示购买区块链实例。 请等待数分钟,安装页面提示安装成功,查看实例状态变为“正常”后,表示区块链实例部署完成。
  • 安装及实例化链代码 登录区块链服务管理控制台。 在新创建的实例卡片中,单击“区块链管理”,登录链代码管理页面。 在登录页面输入用户名、密码,单击“登录”。 用户名为admin,密码为您在创建区块链实例时设置的区块链管理初始密码,如果没有设置区块链管理初始密码,则以资源初始密码为准。 在链代码管理页面,单击页面左上角的。 安装参数如下: 参数 值 链代码名称 bcsysq 链代码版本 1.0 账本数据存储方式 文件数据库(goleveldb) 选择全部Peer节点 勾选 组织&Peer节点 peer-0 链代码语言 Golang 链代码文件 下载示例链代码文件:chaincode_example02.zip。 链代码描述 根据需要填写相关描述。 代码安全检查 链代码语言选择Golang,该功能才会显示。选择是否开启链代码安全检查。 单击“安装”完成链代码安装。 链代码安装完成后,在链代码列表的“操作”列,单击“实例化”。 实例化参数如下: 参数 值 实例化通道 channel 链代码版本 1.0 初始化函数 init 链代码参数 a,200,b,250 背书策略 任意组织背书 背书组织列表 organization 隐私保护配置 否
  • 链代码相关的API Fabric源码包中的shim包提供了如下几种类型的接口,您可以参考使用: 参数解析API:调用链代码时需要给被调用的目标函数/方法传递参数,该API提供解析这些参数的方法。 账本状态数据操作API:该API提供了对账本数据状态进行操作的方法,包括对状态数据的查询及事务处理等。 交易信息获取API:获取提交的交易信息的相关API。 其他API:其他的API,包括事件设置、调用其他链代码操作。 父主题: Java语言链代码开发
  • 响应参数 状态码: 200 表2 响应Body参数 参数 参数类型 描述 creator String 创建者身份标识 title String 名称 identifier String 凭证模板标识 attributes Array of Attribute objects 属性信息 version Integer 版本 表3 Attribute 参数 参数类型 描述 name String 名称 type String 类型 description String 描述信息 状态码: 500 表4 响应Body参数 参数 参数类型 描述 errorCode String 错误码 最小长度:8 最大长度:36 errorMsg String 错误描述 最小长度:2 最大长度:512
  • 响应示例 状态码: 200 CredentialSchema Information { "creator" : "string", "title" : "string", "identifier" : "string", "attributes" : [ { "name" : "name", "type" : "someType", "description" : "Identity number" } ], "version" : 0} 状态码: 500 失败响应 { "errorCode" : "stringst", "errorMsg" : "string"}
  • 请求示例 { "orgID" : "4f1439758ebb41f7411b5f684b67713c08b89198", "channelID" : "mychannel", "cryptoMethod" : "SW", "cert" : "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----", "sk" : "------BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY-----", "timestamp" : "2020-10-27T17:28:16+08:00", "schemaIndex" : "1"}
  • 请求参数 表1 请求Body参数 参数 是否必选 参数类型 描述 orgID 是 String 组织id channelID 是 String 通道id cryptoMethod 是 String 加密方法,目前固定为SW cert 是 String 用户证书,每行末尾均需要增加显式换行符\n sk 是 String 用户私钥,每行末尾均需要增加显式换行符\n timestamp 是 String 时间戳 schemaIndex 是 String schema索引
  • 请求示例 { "orgID" : "ce0ac69b0c8648cd25b44a551780409767c8890b", "channelID" : "mychannel", "cryptoMethod" : "SW", "cert" : "-----BEGIN CERTIFICATE-----\\n...\\n-----END CERTIFICATE-----", "sk" : "-----BEGIN PRIVATE KEY-----\\n...\\n-----END PRIVATE KEY-----", "timestamp" : "2020-10-27T17:28:16+08:00", "owner" : "did:example:8poVETnVCry9ecfHSDeQaR", "secretKeyJson" : "string", "publicKeyJson" : "string"}
  • 响应参数 状态码: 200 表2 响应Body参数 参数 参数类型 描述 oldSecretJson String 旧ABE主私钥 oldPublicKeyJson String 旧ABE主公钥 newSecretJson String 新ABE主私钥 newPublicKeyJson String 新ABE主公钥 状态码: 500 表3 响应Body参数 参数 参数类型 描述 errorCode String 错误码 errorMsg String 错误描述
  • 响应示例 状态码: 200 原有及更新后的ABE主密钥信息 { "oldSecretJson": "{}", "oldPublicKeyJson": "{}", "newSecretJson": "{}", "newPublicKeyJson": "{}"} 状态码: 500 失败响应 { "errorCode" : "BCS.5002046", "errorMsg" : "Incorrect number of arguments"}
  • 请求参数 表1 请求Body参数 参数 是否必选 参数类型 描述 orgID 是 String 组织id channelID 是 String 通道id cryptoMethod 是 String 加密方法,目前固定为SW cert 是 String 证书 sk 是 String 私钥 timestamp 是 String 时间戳 secretKeyJson 否 String json格式的abe主私钥 publicKeyJson 否 String json格式的abe主公钥 owner 是 String 密钥生成者的身份标识
  • 请求参数 表1 请求Body参数 参数 是否必选 参数类型 描述 orgID 是 String 组织id channelID 是 String 通道id cryptoMethod 是 String 加密方法,目前固定为SW cert 是 String 用户证书,每行末尾均需要增加显式换行符\n sk 是 String 用户私钥,每行末尾均需要增加显式换行符\n timestamp 是 String 时间戳 serviceID 否 String 服务的标识符
共100000条