The Init function

The Init function is called when the Chaincode is instantiated by the blockchain network for the first time to initialize its internal data. You can think of it as a constructor in other languages (though Go doesn't support constructors).

As we are building Chaincode to manage a food supply chain, we need to start by defining a struct called Food to represent a food asset. The following picture shows the UML representation of a given asset:

As you may guess, OrderId is the order-tracking ID for the entire supply chain. Besides, each entity in the chain will have its unique entity ID and timestamp when it starts processing the transaction. For example, the raw food producer entity has FoodId and RawFoodProcessDate, and retailers have RetailerId and RetailProcessDate. Each step will update the current status, the entity-related ID, and the process date in the food supply chain.

By querying orderId, we can easily track the current transaction information and status. In the final step, the blockchain will update deliverDate and mark the status as completed once the consumer has received the order.

Here is the equivalent food struct code in our chaincode:

type FoodContract struct {} 
type food struct {
OrderId string
FoodId string
ConsumerId string
ManufactureId string
WholesalerId string
RetailerId string
LogisticsId string
status string
RawFoodProcessDate string
ManufactureProcessDate string
WholesaleProcessDate string
ShippingProcessDate string
RetailProcessDate string
OrderPrice int
ShippingPrice int
DeliveryDate string
}

We then define our Init function as follows:

func (t *FoodContract) Init(stub shim.ChaincodeStubInterface) pb.Response {                
return setupFoodSupplyChainOrder(stub)
}

As you may notice, the Init function takes a ChaincodeStubInterface stub as an argument and calls setupFoodSupplyChainOrder for initializing the object attributes. The best practice when writing Chaincode is to have the initialization process in a separate function:

func setupFoodSupplyChainOrder(stub shim.ChaincodeStubInterface) pb.Response {               
_, args := stub.GetFunctionAndParameters()
orderId := args[0]
consumerId := args[1]
orderPrice, _ := strconv.Atoi(args[2])
shippingPrice, _ := strconv.Atoi(args[3])
foodContract := food{
OrderId: orderId,
ConsumerId: consumerId,
OrderPrice: orderPrice,
ShippingPrice: shippingPrice,
Status: "order initiated"
}
foodBytes, _ := json.Marshal(foodContract)
stub.PutState(foodContract.OrderId, foodBytes)
return shim.Success(nil)
}

ChaincodeStub provides us with the GetFunctionAndParameters() to read the arguments passed to the Chaincode when Init() or Invoke() are called. These arguments can be used to pass the function (defined within the Chaincode) to execute, along with other arguments used to initialize local variables. These parameters are passed when we initialize our foodContract with predefined values from the client application. For instance, when the consumer places an order with the product price and shipment price, the order ID is generated to track the entire order process for the blockchain. The newly generated foodContract data is converted to a byte stream using the json.Marshal method. The contract data is then recorded in the Fabric ledger using the ChaincodeStubInterface.putstate method, with orderId as a key. Finally, the method returns the success status by returning shim.success(nil).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset