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  }