知乎专栏 | 多维度架构 |
借用以太坊思维,将以太坊代币合约搬到 hyperledger 上,一样可以实现代币的功能,这个代币除了不能上交易所,基本满足我们替代积分系统的需求,下面是我写了这样一个合约,在超级账本上实现类似以太坊的代币转账功能。
合约实现代币转账,额度查询,增发代币,冻结账号,锁仓等等服务器,功能与 ERC20 Token 相仿。
合约实例化所有代币打入了 coinbase 账号,分发代币需要使用转账功能从 coinbase 想普通账号转账
普通账号消费可以在将代币转到 coinbase 账号中,这样就完成了代币流通,形成一个闭环。
package main import ( "encoding/json" "fmt" "strconv" "github.com/hyperledger/fabric/core/chaincode/shim" sc "github.com/hyperledger/fabric/protos/peer" ) // Define the Smart Contract structure type SmartContract struct { } type Token struct { Owner string `json:"Owner"` TotalSupply int `json:"TotalSupply"` TokenName string `json:"TokenName"` TokenSymbol string `json:"TokenSymbol"` BalanceOf map[string]int `json:"BalanceOf"` } func (token *Token) initialSupply(){ token.BalanceOf[token.Owner] = token.TotalSupply; } func (token *Token) transfer (_from string, _to string, _value int){ if(token.BalanceOf[_from] >= _value){ token.BalanceOf[_from] -= _value; token.BalanceOf[_to] += _value; } } func (token *Token) balance (_from string) int{ return token.BalanceOf[_from] } func (token *Token) burn(_value int) { if(token.BalanceOf[token.Owner] >= _value){ token.BalanceOf[token.Owner] -= _value; token.TotalSupply -= _value; } } func (token *Token) burnFrom(_from string, _value int) { if(token.BalanceOf[_from] >= _value){ token.BalanceOf[_from] -= _value; token.TotalSupply -= _value; } } func (token *Token) mint(_value int) { token.BalanceOf[token.Owner] += _value; token.TotalSupply += _value; } func (s *SmartContract) Init(stub shim.ChaincodeStubInterface) sc.Response { return shim.Success(nil) } func (s *SmartContract) initLedger(stub shim.ChaincodeStubInterface, args []string) sc.Response { if len(args) != 3 { return shim.Error("Incorrect number of arguments. Expecting 2") } symbol:= args[0] name := args[1] supply,_:= strconv.Atoi(args[2]) token := &Token{ Owner: "coinbase", TotalSupply: supply, TokenName: name, TokenSymbol: symbol, BalanceOf: map[string]int{}} token.initialSupply() tokenAsBytes, _ := json.Marshal(token) err := stub.PutState(symbol, tokenAsBytes) if err != nil { return shim.Error(err.Error()) } fmt.Printf("Init %s \n", string(tokenAsBytes)) return shim.Success(nil) } func (s *SmartContract) transferToken(stub shim.ChaincodeStubInterface, args []string) sc.Response { if len(args) != 4 { return shim.Error("Incorrect number of arguments. Expecting 4") } _from := args[1] _to := args[2] _amount,_ := strconv.Atoi(args[3]) if(_amount <= 0){ return shim.Error("Incorrect number of amount") } tokenAsBytes,err := stub.GetState(args[0]) if err != nil { return shim.Error(err.Error()) } fmt.Printf("transferToken - begin %s \n", string(tokenAsBytes)) token := Token{} json.Unmarshal(tokenAsBytes, &token) token.transfer(_from, _to, _amount) tokenAsBytes, err = json.Marshal(token) if err != nil { return shim.Error(err.Error()) } err = stub.PutState(args[0], tokenAsBytes) if err != nil { return shim.Error(err.Error()) } fmt.Printf("transferToken - end %s \n", string(tokenAsBytes)) return shim.Success(nil) } func (s *SmartContract) balanceToken(stub shim.ChaincodeStubInterface, args []string) sc.Response { if len(args) != 2 { return shim.Error("Incorrect number of arguments. Expecting 2") } tokenAsBytes,err := stub.GetState(args[0]) if err != nil { return shim.Error(err.Error()) } token := Token{} json.Unmarshal(tokenAsBytes, &token) amount := token.balance(args[1]) value := strconv.Itoa(amount) fmt.Printf("%s balance is %s \n", args[1], value) //jsonVal, _ := json.Marshal(string(value)) return shim.Success([]byte(value)) } func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) sc.Response { // Retrieve the requested Smart Contract function and arguments function, args := stub.GetFunctionAndParameters() // Route to the appropriate handler function to interact with the ledger appropriately if function == "balanceToken" { return s.balanceToken(stub, args) } else if function == "initLedger" { return s.initLedger(stub, args) } else if function == "transferToken" { return s.transferToken(stub, args) } return shim.Error("Invalid Smart Contract function name.") } // The main function is only relevant in unit test mode. Only included here for completeness. func main() { // Create a new Smart Contract err := shim.Start(new(SmartContract)) if err != nil { fmt.Printf("Error creating new Smart Contract: %s", err) } }
这个合约用户可以创建多套代币,Args":["Token" 的第一参数 Token就是代币名称
peer chaincode invoke -C myc -n token -c '{"function":"initLedger","Args":["Apple","水果币","1000000"]}' peer chaincode invoke -C myc -n token -c '{"function":"initLedger","Args":["Token","蔬菜币","1000000"]}' peer chaincode invoke -C myc -n token -c '{"function":"initLedger","Args":["Oil","粮油币","1000000"]}'
这个方案仍有不足之处,作者还不清楚如果用户上线是多少,达到临界值后,Hyperledger Fabric 无法在提供服务。
可能 chaincode_example02 做法更靠谱,就是不用 map 保存数据,将每个用户存储在 State 数据上。这里需要创建多套代币,所以使用了一个key 来存储所有账号。如果像 chaincode_example02 那样就需要部署多个 chaincode 在 channel 中。管理起来比较复杂。
[root@localhost fabric-samples]# cd chaincode-docker-devmode/ [root@localhost chaincode-docker-devmode]# docker-compose up -d [root@localhost chaincode-docker-devmode]# docker exec -it cli bash root@765cbcd51fd7:/opt/gopath/src/chaincode# CORE_PEER_ADDRESS=peer:7051 CORE_CHAINCODE_ID_NAME=token:1.0 ./chaincode/chaincode/token/token peer chaincode install -n token -v 1.0 -p chaincodedev/chaincode/chaincode/token peer chaincode instantiate -C myc -n token -v 1.0 -c '{"Args":[""]}' -P "OR ('Org1MSP.member','Org2MSP.member')" peer chaincode instantiate -C myc -n token -v 1.0 -c '{"Args":["init"]}' sleep 10 peer chaincode invoke -C myc -n token -c '{"function":"initLedger","Args":["Token","Netkiller Coin","1000000"]}' peer chaincode invoke -C myc -n token -c '{"function":"transferToken","Args":["Token","coinbase","netkiller","100"]}' peer chaincode invoke -C myc -n token -c '{"function":"balanceToken","Args":["Token","netkiller"]}' peer chaincode invoke -C myc -n token -c '{"function":"transferToken","Args":["Token","netkiller","jerry","100"]}' peer chaincode query -C myc -n token -c '{"function":"balanceToken","Args":["Token","netkiller"]}'
测试不存在账号转账
peer chaincode invoke -C myc -n token -c '{"function":"transferToken","Args":["Token","neo","netkiller","100"]}'
以太坊和超级账本各有优势,虽然超级账本的Token功能无法和以太坊相比,但是使用超级账本实现的Token交易不用矿工费。同事超级账本还有一个优势,就是可以在合约中调用另一个合约,这样一来可以做出很多复杂的需求
例如我们在订票的合约中,就可以直接从Token合约中直接扣款。
我们一般会在合约中定义结构体,然后序列化后存入 state 数据库中。一旦数据结构变化,就需要升级 chaincode。
下面我们只实现了 create, find, update, delete 四个方法,没有数据结构,用户自行提交 json 格式或者其他序列化后的字符串数据。
package main import ( "fmt" "github.com/hyperledger/fabric/core/chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer" ) type SmartContract struct {} func (s *SmartContract) Init(stub shim.ChaincodeStubInterface) pb.Response { return shim.Success(nil) } func (s *SmartContract) Query(stub shim.ChaincodeStubInterface) pb.Response { return shim.Success(nil) } func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) pb.Response { // Retrieve the requested Smart Contract function and arguments function, args := stub.GetFunctionAndParameters() // Route to the appropriate handler function to interact with the ledger appropriately if function == "create" { return s.create(stub, args) } else if function == "find" { return s.find(stub, args) } else if function == "update" { return s.update(stub, args) } else if function == "delete" { return s.delete(stub, args) } return shim.Error("Invalid Smart Contract function name.") } func (s *SmartContract) create(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { return shim.Error("Incorrect number of arguments. Expecting 2") } _key := args[0] _data := args[1] if(_data == ""){ return shim.Error("Incorrect string of data") } existAsBytes,err := stub.GetState(_key) if string(existAsBytes) != "" { fmt.Println("Failed to create account, Duplicate key.") return shim.Error("Failed to create account, Duplicate key.") } err = stub.PutState(_key, []byte(_data)) if err != nil { return shim.Error(err.Error()) } fmt.Printf("create %s %s \n", _key, string(_data)) return shim.Success([]byte(_data)) } func (s *SmartContract) find(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { return shim.Error("Incorrect number of arguments. Expecting 1") } _key := args[0] _data, err := stub.GetState(_key) if err != nil { return shim.Error(err.Error()) } if string(_data) == "" { return shim.Error("The key isn't exist.") }else{ fmt.Printf("query %s %s \n", _key, string(_data)) } return shim.Success(_data) } func (s *SmartContract) update(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { return shim.Error("Incorrect number of arguments. Expecting 2") } _key := args[0] _data := args[1] if(_data == ""){ return shim.Error("Incorrect string of data") } err := stub.PutState(_key, []byte(_data)) if err != nil { return shim.Error(err.Error()) }else{ fmt.Printf("update %s %s \n", _key, string(_data)) } return shim.Success([]byte(_data)) } // Deletes an entity from state func (t *SmartContract) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { return shim.Error("Incorrect number of arguments. Expecting 1") } _key := args[0] // Delete the key from the state in ledger err := stub.DelState(_key) if err != nil { return shim.Error("Failed to delete state") } return shim.Success(nil) } func main() { err := shim.Start(new(SmartContract)) if err != nil { fmt.Printf("Error creating new Smart Contract: %s", err) } }
测试环境 Hyperledger Fabric v1.2.0
[root@localhost ~]# docker exec -it cli bash root@8cb899359aec:/opt/gopath/src/chaincodedev# peer chaincode install -v 1.0 -n art -p chaincodedev/chaincode/art root@8cb899359aec:/opt/gopath/src/chaincodedev# peer chaincode instantiate -C myc -n art -v 1.0 -c '{"Args":["init",""]}' root@8cb899359aec:/opt/gopath/src/chaincodedev# peer chaincode instantiate -C myc -n art -v 1.0 -c '{"Args":[]}'
操作演示
root@8cb899359aec:/opt/gopath/src/chaincodedev# peer chaincode install -v 1.0 -n art -p chaincodedev/chaincode/art 2018-07-20 02:39:48.091 UTC [viperutil] getKeysRecursively -> DEBU 001 Found map[string]interface{} value for peer.BCCSP 2018-07-20 02:39:48.092 UTC [viperutil] unmarshalJSON -> DEBU 002 Unmarshal JSON: value cannot be unmarshalled: invalid character 'S' looking for beginning of value 2018-07-20 02:39:48.092 UTC [viperutil] getKeysRecursively -> DEBU 003 Found real value for peer.BCCSP.Default setting to string SW 2018-07-20 02:39:48.093 UTC [viperutil] getKeysRecursively -> DEBU 004 Found map[string]interface{} value for peer.BCCSP.SW 2018-07-20 02:39:48.093 UTC [viperutil] unmarshalJSON -> DEBU 005 Unmarshal JSON: value cannot be unmarshalled: invalid character 'S' looking for beginning of value 2018-07-20 02:39:48.093 UTC [viperutil] getKeysRecursively -> DEBU 006 Found real value for peer.BCCSP.SW.Hash setting to string SHA2 2018-07-20 02:39:48.094 UTC [viperutil] unmarshalJSON -> DEBU 007 Unmarshal JSON: value is not a string: 256 2018-07-20 02:39:48.094 UTC [viperutil] getKeysRecursively -> DEBU 008 Found real value for peer.BCCSP.SW.Security setting to int 256 2018-07-20 02:39:48.095 UTC [viperutil] getKeysRecursively -> DEBU 009 Found map[string]interface{} value for peer.BCCSP.SW.FileKeyStore 2018-07-20 02:39:48.095 UTC [viperutil] unmarshalJSON -> DEBU 00a Unmarshal JSON: value cannot be unmarshalled: unexpected end of JSON input 2018-07-20 02:39:48.095 UTC [viperutil] getKeysRecursively -> DEBU 00b Found real value for peer.BCCSP.SW.FileKeyStore.KeyStore setting to string 2018-07-20 02:39:48.096 UTC [viperutil] getKeysRecursively -> DEBU 00c Found map[string]interface{} value for peer.BCCSP.PKCS11 2018-07-20 02:39:48.096 UTC [viperutil] getKeysRecursively -> DEBU 00d Found map[string]interface{} value for peer.BCCSP.PKCS11.FileKeyStore 2018-07-20 02:39:48.097 UTC [viperutil] unmarshalJSON -> DEBU 00e Unmarshal JSON: value is not a string: <nil> 2018-07-20 02:39:48.098 UTC [viperutil] getKeysRecursively -> DEBU 00f Found real value for peer.BCCSP.PKCS11.FileKeyStore.KeyStore setting to <nil> <nil> 2018-07-20 02:39:48.098 UTC [viperutil] unmarshalJSON -> DEBU 010 Unmarshal JSON: value is not a string: <nil> 2018-07-20 02:39:48.099 UTC [viperutil] getKeysRecursively -> DEBU 011 Found real value for peer.BCCSP.PKCS11.Library setting to <nil> <nil> 2018-07-20 02:39:48.099 UTC [viperutil] unmarshalJSON -> DEBU 012 Unmarshal JSON: value is not a string: <nil> 2018-07-20 02:39:48.100 UTC [viperutil] getKeysRecursively -> DEBU 013 Found real value for peer.BCCSP.PKCS11.Label setting to <nil> <nil> 2018-07-20 02:39:48.101 UTC [viperutil] unmarshalJSON -> DEBU 014 Unmarshal JSON: value is not a string: <nil> 2018-07-20 02:39:48.101 UTC [viperutil] getKeysRecursively -> DEBU 015 Found real value for peer.BCCSP.PKCS11.Pin setting to <nil> <nil> 2018-07-20 02:39:48.102 UTC [viperutil] unmarshalJSON -> DEBU 016 Unmarshal JSON: value is not a string: <nil> 2018-07-20 02:39:48.103 UTC [viperutil] getKeysRecursively -> DEBU 017 Found real value for peer.BCCSP.PKCS11.Hash setting to <nil> <nil> 2018-07-20 02:39:48.103 UTC [viperutil] unmarshalJSON -> DEBU 018 Unmarshal JSON: value is not a string: <nil> 2018-07-20 02:39:48.104 UTC [viperutil] getKeysRecursively -> DEBU 019 Found real value for peer.BCCSP.PKCS11.Security setting to <nil> <nil> 2018-07-20 02:39:48.104 UTC [viperutil] EnhancedExactUnmarshalKey -> DEBU 01a map[peer.BCCSP:map[Default:SW SW:map[Security:256 FileKeyStore:map[KeyStore:] Hash:SHA2] PKCS11:map[Pin:<nil> Hash:<nil> Security:<nil> FileKeyStore:map[KeyStore:<nil>] Library:<nil> Label:<nil>]]] 2018-07-20 02:39:48.105 UTC [bccsp_sw] openKeyStore -> DEBU 01b KeyStore opened at [/etc/hyperledger/msp/keystore]...done 2018-07-20 02:39:48.105 UTC [bccsp] initBCCSP -> DEBU 01c Initialize BCCSP [SW] 2018-07-20 02:39:48.106 UTC [msp] getPemMaterialFromDir -> DEBU 01d Reading directory /etc/hyperledger/msp/signcerts 2018-07-20 02:39:48.106 UTC [msp] getPemMaterialFromDir -> DEBU 01e Inspecting file /etc/hyperledger/msp/signcerts/peer.pem 2018-07-20 02:39:48.106 UTC [msp] getPemMaterialFromDir -> DEBU 01f Reading directory /etc/hyperledger/msp/cacerts 2018-07-20 02:39:48.106 UTC [msp] getPemMaterialFromDir -> DEBU 020 Inspecting file /etc/hyperledger/msp/cacerts/cacert.pem 2018-07-20 02:39:48.107 UTC [msp] getPemMaterialFromDir -> DEBU 021 Reading directory /etc/hyperledger/msp/admincerts 2018-07-20 02:39:48.107 UTC [msp] getPemMaterialFromDir -> DEBU 022 Inspecting file /etc/hyperledger/msp/admincerts/admincert.pem 2018-07-20 02:39:48.107 UTC [msp] getPemMaterialFromDir -> DEBU 023 Reading directory /etc/hyperledger/msp/intermediatecerts 2018-07-20 02:39:48.107 UTC [msp] getMspConfig -> DEBU 024 Intermediate certs folder not found at [/etc/hyperledger/msp/intermediatecerts]. Skipping. [stat /etc/hyperledger/msp/intermediatecerts: no such file or directory] 2018-07-20 02:39:48.107 UTC [msp] getPemMaterialFromDir -> DEBU 025 Reading directory /etc/hyperledger/msp/tlscacerts 2018-07-20 02:39:48.107 UTC [msp] getPemMaterialFromDir -> DEBU 026 Inspecting file /etc/hyperledger/msp/tlscacerts/tlsroot.pem 2018-07-20 02:39:48.107 UTC [msp] getPemMaterialFromDir -> DEBU 027 Reading directory /etc/hyperledger/msp/tlsintermediatecerts 2018-07-20 02:39:48.108 UTC [msp] getPemMaterialFromDir -> DEBU 028 Inspecting file /etc/hyperledger/msp/tlsintermediatecerts/tlsintermediate.pem 2018-07-20 02:39:48.108 UTC [msp] getPemMaterialFromDir -> DEBU 029 Reading directory /etc/hyperledger/msp/crls 2018-07-20 02:39:48.108 UTC [msp] getMspConfig -> DEBU 02a crls folder not found at [/etc/hyperledger/msp/crls]. Skipping. [stat /etc/hyperledger/msp/crls: no such file or directory] 2018-07-20 02:39:48.108 UTC [msp] getMspConfig -> DEBU 02b MSP configuration file not found at [/etc/hyperledger/msp/config.yaml]: [stat /etc/hyperledger/msp/config.yaml: no such file or directory] 2018-07-20 02:39:48.109 UTC [msp] newBccspMsp -> DEBU 02c Creating BCCSP-based MSP instance 2018-07-20 02:39:48.109 UTC [msp] New -> DEBU 02d Creating Cache-MSP instance 2018-07-20 02:39:48.109 UTC [msp] loadLocaMSP -> DEBU 02e Created new local MSP 2018-07-20 02:39:48.110 UTC [msp] Setup -> DEBU 02f Setting up MSP instance DEFAULT 2018-07-20 02:39:48.111 UTC [msp/identity] newIdentity -> DEBU 030 Creating identity instance for cert -----BEGIN CERTIFICATE----- MIICYjCCAgigAwIBAgIRAL1fEAnz5zp4moJ8MdSb/lYwCgYIKoZIzj0EAwIwgYEx CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4g RnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMQwwCgYDVQQLEwND T1AxHDAaBgNVBAMTE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTcxMTEyMTM0MTEx WhcNMjcxMTEwMTM0MTExWjCBgTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlm b3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhh bXBsZS5jb20xDDAKBgNVBAsTA0NPUDEcMBoGA1UEAxMTY2Eub3JnMS5leGFtcGxl LmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGrsQ6oJpk6hDWf63HU3OSNd bou9KNw/VIee1IngPDI4YJU7O+Xa/XLJuwnFv7BpR8Ytl3f+njC8i/RZP2/svO+j XzBdMA4GA1UdDwEB/wQEAwIBpjAPBgNVHSUECDAGBgRVHSUAMA8GA1UdEwEB/wQF MAMBAf8wKQYDVR0OBCIEIIpzkSIZzxBWVIV5unlgZJuyu2XPEeP8+y1uB6LLA5Qr MAoGCCqGSM49BAMCA0gAMEUCIQDUh/+CC2dAICnYtACXspwUaaEbiyZxYIx+XDvW o8VVcgIgGz5S4iC5+xkxgeaISPfxKTTVy6yzTdYGzCw1vPppjzo= -----END CERTIFICATE----- 2018-07-20 02:39:48.112 UTC [msp/identity] newIdentity -> DEBU 031 Creating identity instance for cert -----BEGIN CERTIFICATE----- MIICNjCCAd2gAwIBAgIRAMnf9/dmV9RvCCVw9pZQUfUwCgYIKoZIzj0EAwIwgYEx CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4g RnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMQwwCgYDVQQLEwND T1AxHDAaBgNVBAMTE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTcxMTEyMTM0MTEx WhcNMjcxMTEwMTM0MTExWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv cm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEMMAoGA1UECxMDQ09QMR8wHQYD VQQDExZwZWVyMC5vcmcxLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D AQcDQgAEZ8S4V71OBJpyMIVZdwYdFXAckItrpvSrCf0HQg40WW9XSoOOO76I+Umf EkmTlIJXP7/AyRRSRU38oI8Ivtu4M6NNMEswDgYDVR0PAQH/BAQDAgeAMAwGA1Ud EwEB/wQCMAAwKwYDVR0jBCQwIoAginORIhnPEFZUhXm6eWBkm7K7Zc8R4/z7LW4H ossDlCswCgYIKoZIzj0EAwIDRwAwRAIgVikIUZzgfuFsGLQHWJUVJCU7pDaETkaz PzFgsCiLxUACICgzJYlW7nvZxP7b6tbeu3t8mrhMXQs956mD4+BoKuNI -----END CERTIFICATE----- 2018-07-20 02:39:48.181 UTC [msp/identity] newIdentity -> DEBU 032 Creating identity instance for cert -----BEGIN CERTIFICATE----- MIICNjCCAd2gAwIBAgIRAMnf9/dmV9RvCCVw9pZQUfUwCgYIKoZIzj0EAwIwgYEx CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4g RnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMQwwCgYDVQQLEwND T1AxHDAaBgNVBAMTE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTcxMTEyMTM0MTEx WhcNMjcxMTEwMTM0MTExWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv cm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEMMAoGA1UECxMDQ09QMR8wHQYD VQQDExZwZWVyMC5vcmcxLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D AQcDQgAEZ8S4V71OBJpyMIVZdwYdFXAckItrpvSrCf0HQg40WW9XSoOOO76I+Umf EkmTlIJXP7/AyRRSRU38oI8Ivtu4M6NNMEswDgYDVR0PAQH/BAQDAgeAMAwGA1Ud EwEB/wQCMAAwKwYDVR0jBCQwIoAginORIhnPEFZUhXm6eWBkm7K7Zc8R4/z7LW4H ossDlCswCgYIKoZIzj0EAwIDRwAwRAIgVikIUZzgfuFsGLQHWJUVJCU7pDaETkaz PzFgsCiLxUACICgzJYlW7nvZxP7b6tbeu3t8mrhMXQs956mD4+BoKuNI -----END CERTIFICATE----- 2018-07-20 02:39:48.183 UTC [msp/identity] newIdentity -> DEBU 033 Creating identity instance for cert -----BEGIN CERTIFICATE----- MIICNjCCAd2gAwIBAgIRAMnf9/dmV9RvCCVw9pZQUfUwCgYIKoZIzj0EAwIwgYEx CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4g RnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMQwwCgYDVQQLEwND T1AxHDAaBgNVBAMTE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTcxMTEyMTM0MTEx WhcNMjcxMTEwMTM0MTExWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv cm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEMMAoGA1UECxMDQ09QMR8wHQYD VQQDExZwZWVyMC5vcmcxLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D AQcDQgAEZ8S4V71OBJpyMIVZdwYdFXAckItrpvSrCf0HQg40WW9XSoOOO76I+Umf EkmTlIJXP7/AyRRSRU38oI8Ivtu4M6NNMEswDgYDVR0PAQH/BAQDAgeAMAwGA1Ud EwEB/wQCMAAwKwYDVR0jBCQwIoAginORIhnPEFZUhXm6eWBkm7K7Zc8R4/z7LW4H ossDlCswCgYIKoZIzj0EAwIDRwAwRAIgVikIUZzgfuFsGLQHWJUVJCU7pDaETkaz PzFgsCiLxUACICgzJYlW7nvZxP7b6tbeu3t8mrhMXQs956mD4+BoKuNI -----END CERTIFICATE----- 2018-07-20 02:39:48.183 UTC [msp] setupSigningIdentity -> DEBU 034 Signing identity expires at 2027-11-10 13:41:11 +0000 UTC 2018-07-20 02:39:48.185 UTC [msp] Validate -> DEBU 035 MSP DEFAULT validating identity 2018-07-20 02:39:48.187 UTC [grpc] Printf -> DEBU 036 parsed scheme: "" 2018-07-20 02:39:48.188 UTC [grpc] Printf -> DEBU 037 scheme "" not registered, fallback to default scheme 2018-07-20 02:39:48.188 UTC [grpc] Printf -> DEBU 038 ccResolverWrapper: sending new addresses to cc: [{peer:7051 0 <nil>}] 2018-07-20 02:39:48.188 UTC [grpc] Printf -> DEBU 039 ClientConn switching balancer to "pick_first" 2018-07-20 02:39:48.188 UTC [grpc] Printf -> DEBU 03a pickfirstBalancer: HandleSubConnStateChange: 0xc4203d7c40, CONNECTING 2018-07-20 02:39:48.190 UTC [grpc] Printf -> DEBU 03b pickfirstBalancer: HandleSubConnStateChange: 0xc4203d7c40, READY 2018-07-20 02:39:48.192 UTC [grpc] Printf -> DEBU 03c parsed scheme: "" 2018-07-20 02:39:48.192 UTC [grpc] Printf -> DEBU 03d scheme "" not registered, fallback to default scheme 2018-07-20 02:39:48.192 UTC [grpc] Printf -> DEBU 03e ccResolverWrapper: sending new addresses to cc: [{peer:7051 0 <nil>}] 2018-07-20 02:39:48.192 UTC [grpc] Printf -> DEBU 03f ClientConn switching balancer to "pick_first" 2018-07-20 02:39:48.192 UTC [grpc] Printf -> DEBU 040 pickfirstBalancer: HandleSubConnStateChange: 0xc420452130, CONNECTING 2018-07-20 02:39:48.194 UTC [grpc] Printf -> DEBU 041 pickfirstBalancer: HandleSubConnStateChange: 0xc420452130, READY 2018-07-20 02:39:48.197 UTC [msp] GetDefaultSigningIdentity -> DEBU 042 Obtaining default signing identity 2018-07-20 02:39:48.197 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 043 Using default escc 2018-07-20 02:39:48.198 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 044 Using default vscc 2018-07-20 02:39:48.198 UTC [chaincodeCmd] getChaincodeSpec -> DEBU 045 java chaincode disabled 2018-07-20 02:39:48.266 UTC [golang-platform] getCodeFromFS -> DEBU 046 getCodeFromFS chaincodedev/chaincode/art 2018-07-20 02:39:49.372 UTC [golang-platform] func1 -> DEBU 047 Discarding GOROOT package fmt 2018-07-20 02:39:49.372 UTC [golang-platform] func1 -> DEBU 048 Discarding provided package github.com/hyperledger/fabric/core/chaincode/shim 2018-07-20 02:39:49.372 UTC [golang-platform] func1 -> DEBU 049 Discarding provided package github.com/hyperledger/fabric/protos/peer 2018-07-20 02:39:49.373 UTC [golang-platform] GetDeploymentPayload -> DEBU 04a done 2018-07-20 02:39:49.373 UTC [container] WriteFileToPackage -> DEBU 04b Writing file to tarball: src/chaincodedev/chaincode/art/art.go 2018-07-20 02:39:49.378 UTC [msp/identity] Sign -> DEBU 04c Sign: plaintext: 0AC4070A5C08031A0C08F596C5DA0510...97DB3F010000FFFFD8DB7F9600140000 2018-07-20 02:39:49.379 UTC [msp/identity] Sign -> DEBU 04d Sign: digest: EFE78D9C254C9A5795FAC35A6AC5A543AAD70322E6F756D1822E9BBEC11AD7E0 2018-07-20 02:39:49.459 UTC [chaincodeCmd] install -> INFO 04e Installed remotely response:<status:200 payload:"OK" >