更新时间:2022-09-16 GMT+08:00

应用示例

为了说明同态加密库的具体使用方法,提供一个应用示例代码和对应的链码示例代码。该应用的主要功能是实现用户间相互转账,同时使用同态加密库保护用户的转账交易信息。

该应用的使用包括三个步骤:注册用户(同时会初始化用户余额),用户间转账,查询用户余额。

应用使用命令行的方式进行业务操作,具体过程如下。

注意事项

在下载的sdk.yaml文件中查询orderer和peer的域名信息,将EIP+orderer域名和EIP+peer域名补充进“/etc/hosts”文件中。使用Fabric1.1版本时,peer域名中的EIP需要配置为公网IP,使用Fabric1.4版本时,peer域名中的EIP需要配置为私网IP,否则网络不通将会导致交易验证失败。

在“/etc/hosts”文件中增加orderer节点和peer节点的域名映射时,操作方法如下:

X.X.X.X orderer-e5ad7831affbe8e6e2e7984b098f92406930a688-0.orderer-e5ad7831affbe8e6e2e7984b098f92406930a688.default.svc.cluster.local
X.X.X.X peer-d524b0817aaed85490368776cb88042a149a56b5-0.peer-d524b0817aaed85490368776cb88042a149a56b5.default.svc.cluster.local
X.X.X.X peer-d524b0817aaed85490368776cb88042a149a56b5-1.peer-d524b0817aaed85490368776cb88042a149a56b5.default.svc.cluster.local

X.X.X.X为示例EIP,请替换为实际EIP。

注册

Usage:
  appdemo register [flags]
Flags:
  -C, --channel string       channel id (default "mychannel")
  -c, --config string        configuration file path (default "./config_test.yaml")
  -I, --idcc string          idendity chaincode name (default "IDChaincode")
  -i, --initbalance string   init initbalance
  -o, --orgid string         organization id (default "org1")
  -p, --protectpwd string    protect pwd
  -T, --txcc string          transaction chaincode name (default "TxChaincode")
  -u, --userid string        user id 
./appdemo register -u A -p test -i 100 

部分参数不配置时使用的为默认值,见Flags中的描述。如果用户配置的与默认值不同,需要在参数中显示指定。

  • 为用户生成一对同态公私钥

这里假设有个用户表示userid,用于区分用户,新用户注册的时候为这个用户生成一对公私钥,这里demo为每个用户将密钥对写到了本地的${userid}.data文件。

privKeyStr, pubKeyStr, err := pswapi_sdk.GenerateKey(propwd)
check(err)
fmt.Println("key is nil")
userdata.PubKey = pubKeyStr
userdata.PriKey = privKeyStr
  • 注册公钥

使用fabric SDK的接口向IDChaincode 注册,参数为生成的公钥。

注册公钥是为了使大家的同态公钥共享,这里利用了区块链本身链码特性完成该功能。主要作用是在转账的时候,使用转账者的公钥加密交易信息,保护交易隐私,只有私钥持有者才可以解密交易内容。

res, err := sdk_client.Invoke(setup, "Register", [][]byte{[]byte(userdata.PubKey), []byte(senderAddr)})  
if err != nil {
     fmt.Println("Fail to register user pk ", err.Error())  
} else {
     addrByte := res[0].ProposalResponse.GetResponse().Payload
     fmt.Println("Register addr: ", string(addrByte))
  }
  • 注册初始余额
    1. 使用sdk.InitBalance来初始余额,进行加密生成初始化balanceinfo。
    2. 发送balanceinfo到交易Chaincode。
balanceInfo, err := pswapi_sdk.InitBalance(initbalance, userdata.PubKey) check(err)
setup.ChainCodeID = txchaincode
_, err = sdk_client.Invoke(setup, "init", [][]byte{[]byte(userdata.PubKey), []byte(balanceInfo)})
 if err != nil {
    fmt.Println("Initbalance error for user: ", senderAddr, err.Error())
 } else {
    fmt.Println("init balance successfully: ", senderAddr)
 }
 check(err)

交易

Usage:
  appdemo transaction [flags]
Flags:
  -b, --AddrB string        B' addr
  -t, --Tx string           Transaction Num
  -C, --channel string      channel id (default "mychannel")
  -c, --config string       configuration file path (default "./config_test.yaml")
  -I, --idcc string         idendity chaincode name (default "IDChaincode")
  -o, --orgid string        organization id (default "org1")
  -p, --protectpwd string   protect pwd
  -T, --txcc string         transaction chaincode name (default "TxChaincode")
  -u, --userid string       user id 
./appdemo transaction -u A -p test -b a0760184f7ed24e0d86f5b2df40a973a9e1b5da9a1ae886532ac9cd634b59d59 -t 10
//说明:其中-b后的字符串为B的账户地址(B注册成功时回显的地址)。

查询

Usage:
  appdemo querybalance [flags]
Flags:
  -C, --channel string      channel id (default "mychannel")
  -c, --config string       configuration file path (default "./config_test.yaml")
  -I, --idcc string         idendity chaincode name (default "IDChaincode")
  -o, --orgid string        organization id (default "org1")
  -p, --protectpwd string   protect pwd
  -T, --txcc string         transaction chaincode name (default "TxChaincode")
  -u, --userid string       user id
./appdemo querybalance -p test -u A

查询代码:

  1. 调用sdk提供的InitBalance接口初始化余额。
  2. 调用fabirc sdk发送交易。
    get balance
     setup.ChainCodeID = txchaincode
     transRec := sdk_client.TransRecord{}
    
     fmt.Println("query balance")
    
     resps, err := sdk_client.Query(setup, "QueryBalance", [][]byte{[]byte(addrA)})
     if err != nil {
      fmt.Println("Fail to query balance :", err.Error())
      return err
     }
    
     err = json.Unmarshal(resps[0].ProposalResponse.GetResponse().Payload, &transRec)
     if err != nil {
      fmt.Println("unmarshal query result error: ", err.Error())
      return err
     }

    decrypt balance
    
     curbalance, err := pswapi_sdk.Decrypt(transRec.Balance, userdata.PriKey, propwd)
     if err != nil {
      fmt.Println("sdk Decrypt error: ", err.Error())
      return err
     }
    
     fmt.Println("current balance:" + curbalance.String())