github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/examples/chaincode/go/asset_management02/asset_management02.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "encoding/base64" 21 "encoding/binary" 22 "strconv" 23 "strings" 24 25 "github.com/hyperledger/fabric/core/chaincode/shim" 26 pb "github.com/hyperledger/fabric/protos/peer" 27 "github.com/op/go-logging" 28 ) 29 30 var myLogger = logging.MustGetLogger("asset_mgm") 31 32 var cHandler = NewCertHandler() 33 var dHandler = NewDepositoryHandler() 34 35 //AssetManagementChaincode APIs exposed to chaincode callers 36 type AssetManagementChaincode struct { 37 } 38 39 // assignOwnership assigns assets to a given account ID, only entities with the "issuer" are allowed to call this function 40 // Note: this issuer can only allocate balance to one account ID at a time 41 // args[0]: investor's TCert 42 // args[1]: attribute name inside the investor's TCert that contains investor's account ID 43 // args[2]: amount to be assigned to this investor's account ID 44 func (t *AssetManagementChaincode) assignOwnership(stub shim.ChaincodeStubInterface, args []string) pb.Response { 45 myLogger.Debugf("+++++++++++++++++++++++++++++++++++assignOwnership+++++++++++++++++++++++++++++++++") 46 47 if len(args) != 3 { 48 return shim.Error("Incorrect number of arguments. Expecting 0") 49 } 50 51 //check is invoker has the correct role, only invokers with the "issuer" role is allowed to 52 //assign asset to owners 53 isAuthorized, err := cHandler.isAuthorized(stub, "issuer") 54 if !isAuthorized { 55 myLogger.Errorf("system error %v", err) 56 return shim.Error("user is not aurthorized to assign assets") 57 } 58 59 owner, err := base64.StdEncoding.DecodeString(args[0]) 60 if err != nil { 61 myLogger.Errorf("system error %v", err) 62 return shim.Error("Failed decoding owner") 63 } 64 accountAttribute := args[1] 65 66 amount, err := strconv.ParseUint(args[2], 10, 64) 67 if err != nil { 68 myLogger.Errorf("system error %v", err) 69 return shim.Error("Unable to parse amount" + args[2]) 70 } 71 72 //retrieve account IDs from investor's TCert 73 accountIDs, err := cHandler.getAccountIDsFromAttribute(owner, []string{accountAttribute}) 74 if err != nil { 75 myLogger.Errorf("system error %v", err) 76 return shim.Error("Unable to retrieve account Ids from user certificate " + args[1]) 77 } 78 79 //retreive investors' contact info (e.g. phone number, email, home address) 80 //from investors' TCert. Ideally, this information shall be encrypted with issuer's pub key or KA key 81 //between investor and issuer, so that only issuer can view such information 82 contactInfo, err := cHandler.getContactInfo(owner) 83 if err != nil { 84 return shim.Error("Unable to retrieve contact info from user certificate " + args[1]) 85 } 86 87 //call DeposistoryHandler.assign function to put the "amount" and "contact info" under this account ID 88 err = dHandler.assign(stub, accountIDs[0], contactInfo, amount) 89 if err != nil { 90 return shim.Error(err.Error()) 91 } 92 93 return shim.Success(nil) 94 } 95 96 // transferOwnership moves x number of assets from account A to account B 97 // args[0]: Investor TCert that has account IDs which will their balances deducted 98 // args[1]: attribute names inside TCert (arg[0]) that countain the account IDs 99 // args[2]: Investor TCert that has account IDs which will have their balances increased 100 // args[3]: attribute names inside TCert (arg[2]) that countain the account IDs 101 func (t *AssetManagementChaincode) transferOwnership(stub shim.ChaincodeStubInterface, args []string) pb.Response { 102 myLogger.Debugf("+++++++++++++++++++++++++++++++++++transferOwnership+++++++++++++++++++++++++++++++++") 103 104 if len(args) != 5 { 105 return shim.Error("Incorrect number of arguments. Expecting 0") 106 } 107 108 fromOwner, err := base64.StdEncoding.DecodeString(args[0]) 109 if err != nil { 110 myLogger.Errorf("system error %v", err) 111 return shim.Error("Failed decoding fromOwner") 112 } 113 fromAccountAttributes := strings.Split(args[1], ",") 114 115 toOwner, err := base64.StdEncoding.DecodeString(args[2]) 116 if err != nil { 117 myLogger.Errorf("system error %v", err) 118 return shim.Error("Failed decoding owner") 119 } 120 toAccountAttributes := strings.Split(args[3], ",") 121 122 amount, err := strconv.ParseUint(args[4], 10, 64) 123 if err != nil { 124 myLogger.Errorf("system error %v", err) 125 return shim.Error("Unable to parse amount" + args[4]) 126 } 127 128 // retrieve account IDs from "transfer from" TCert 129 fromAccountIds, err := cHandler.getAccountIDsFromAttribute(fromOwner, fromAccountAttributes) 130 if err != nil { 131 myLogger.Errorf("system error %v", err) 132 return shim.Error("Unable to retrieve contact info from user certificate" + args[1]) 133 } 134 135 // retrieve account IDs from "transfer to" TCert 136 toAccountIds, err := cHandler.getAccountIDsFromAttribute(toOwner, toAccountAttributes) 137 if err != nil { 138 myLogger.Errorf("system error %v", err) 139 return shim.Error("Unable to retrieve contact info from user certificate" + args[3]) 140 } 141 142 // retrieve contact info from "transfer to" TCert 143 contactInfo, err := cHandler.getContactInfo(toOwner) 144 if err != nil { 145 myLogger.Errorf("system error %v received", err) 146 return shim.Error("Unable to retrieve contact info from user certificate" + args[4]) 147 } 148 149 // call dHandler.transfer to transfer to transfer "amount" from "from account" IDs to "to account" IDs 150 err = dHandler.transfer(stub, fromAccountIds, toAccountIds[0], contactInfo, amount) 151 if err != nil { 152 return shim.Error(err.Error()) 153 } 154 155 return shim.Success(nil) 156 } 157 158 // getOwnerContactInformation retrieves the contact information of the investor that owns a particular account ID 159 // Note: user contact information shall be encrypted with issuer's pub key or KA key 160 // between investor and issuer, so that only issuer can decrypt such information 161 // args[0]: one of the many account IDs owned by "some" investor 162 func (t *AssetManagementChaincode) getOwnerContactInformation(stub shim.ChaincodeStubInterface, args []string) pb.Response { 163 myLogger.Debugf("+++++++++++++++++++++++++++++++++++getOwnerContactInformation+++++++++++++++++++++++++++++++++") 164 165 if len(args) != 1 { 166 return shim.Error("Incorrect number of arguments. Expecting 0") 167 } 168 169 accountID := args[0] 170 171 email, err := dHandler.queryContactInfo(stub, accountID) 172 if err != nil { 173 return shim.Error(err.Error()) 174 } 175 176 return shim.Success([]byte(email)) 177 } 178 179 // getBalance retrieves the account balance information of the investor that owns a particular account ID 180 // args[0]: one of the many account IDs owned by "some" investor 181 func (t *AssetManagementChaincode) getBalance(stub shim.ChaincodeStubInterface, args []string) pb.Response { 182 myLogger.Debugf("+++++++++++++++++++++++++++++++++++getBalance+++++++++++++++++++++++++++++++++") 183 184 if len(args) != 1 { 185 return shim.Error("Incorrect number of arguments. Expecting 0") 186 } 187 188 accountID := args[0] 189 190 balance, err := dHandler.queryBalance(stub, accountID) 191 if err != nil { 192 return shim.Error(err.Error()) 193 } 194 195 //convert balance (uint64) to []byte (Big Endian) 196 ret := make([]byte, 8) 197 binary.BigEndian.PutUint64(ret, balance) 198 199 return shim.Success(ret) 200 } 201 202 // Init initialization, this method will create asset despository in the chaincode state 203 func (t *AssetManagementChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { 204 _, args := stub.GetFunctionAndParameters() 205 myLogger.Debugf("********************************Init****************************************") 206 207 myLogger.Info("[AssetManagementChaincode] Init") 208 if len(args) != 0 { 209 return shim.Error("Incorrect number of arguments. Expecting 0") 210 } 211 212 return shim.Success(nil) 213 } 214 215 // Invoke method is the interceptor of all invocation transactions, its job is to direct 216 // invocation transactions to intended APIs 217 func (t *AssetManagementChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { 218 function, args := stub.GetFunctionAndParameters() 219 myLogger.Debugf("********************************Invoke****************************************") 220 221 // Handle different functions 222 if function == "assignOwnership" { 223 // Assign ownership 224 return t.assignOwnership(stub, args) 225 } else if function == "transferOwnership" { 226 // Transfer ownership 227 return t.transferOwnership(stub, args) 228 } else if function == "getOwnerContactInformation" { 229 return t.getOwnerContactInformation(stub, args) 230 } else if function == "getBalance" { 231 return t.getBalance(stub, args) 232 } 233 234 return shim.Error("Received unknown function invocation") 235 } 236 237 func main() { 238 239 // primitives.SetSecurityLevel("SHA3", 256) 240 err := shim.Start(new(AssetManagementChaincode)) 241 if err != nil { 242 myLogger.Debugf("Error starting AssetManagementChaincode: %s", err) 243 } 244 245 }