Created
March 9, 2020 14:09
-
-
Save alexroan/c51e4a8c31bf691ff25a83901133e6b2 to your computer and use it in GitHub Desktop.
Fabcar.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the | |
* "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, | |
* software distributed under the License is distributed on an | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
* KIND, either express or implied. See the License for the | |
* specific language governing permissions and limitations | |
* under the License. | |
*/ | |
/* | |
* The sample smart contract for documentation topic: | |
* Writing Your First Blockchain Application | |
*/ | |
package main | |
/* Imports | |
* 4 utility libraries for formatting, handling bytes, reading and writing JSON, and string manipulation | |
* 2 specific Hyperledger Fabric specific libraries for Smart Contracts | |
*/ | |
import ( | |
"bytes" | |
"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 { | |
} | |
// Define the car structure, with 4 properties. Structure tags are used by encoding/json library | |
type Car struct { | |
Make string `json:"make"` | |
Model string `json:"model"` | |
Colour string `json:"colour"` | |
Owner string `json:"owner"` | |
} | |
/* | |
* The Init method is called when the Smart Contract "fabcar" is instantiated by the blockchain network | |
* Best practice is to have any Ledger initialization in separate function -- see initLedger() | |
*/ | |
func (s *SmartContract) Init(APIstub shim.ChaincodeStubInterface) sc.Response { | |
return shim.Success(nil) | |
} | |
/* | |
* The Invoke method is called as a result of an application request to run the Smart Contract "fabcar" | |
* The calling application program has also specified the particular smart contract function to be called, with arguments | |
*/ | |
func (s *SmartContract) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response { | |
// Retrieve the requested Smart Contract function and arguments | |
function, args := APIstub.GetFunctionAndParameters() | |
// Route to the appropriate handler function to interact with the ledger appropriately | |
if function == "queryCar" { | |
return s.queryCar(APIstub, args) | |
} else if function == "initLedger" { | |
return s.initLedger(APIstub) | |
} else if function == "createCar" { | |
return s.createCar(APIstub, args) | |
} else if function == "queryAllCars" { | |
return s.queryAllCars(APIstub) | |
} else if function == "changeCarOwner" { | |
return s.changeCarOwner(APIstub, args) | |
} | |
return shim.Error("Invalid Smart Contract function name.") | |
} | |
func (s *SmartContract) queryCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { | |
if len(args) != 1 { | |
return shim.Error("Incorrect number of arguments. Expecting 1") | |
} | |
carAsBytes, _ := APIstub.GetState(args[0]) | |
return shim.Success(carAsBytes) | |
} | |
func (s *SmartContract) initLedger(APIstub shim.ChaincodeStubInterface) sc.Response { | |
cars := []Car{ | |
Car{Make: "Toyota", Model: "Prius", Colour: "blue", Owner: "Tomoko"}, | |
Car{Make: "Ford", Model: "Mustang", Colour: "red", Owner: "Brad"}, | |
Car{Make: "Hyundai", Model: "Tucson", Colour: "green", Owner: "Jin Soo"}, | |
Car{Make: "Volkswagen", Model: "Passat", Colour: "yellow", Owner: "Max"}, | |
Car{Make: "Tesla", Model: "S", Colour: "black", Owner: "Adriana"}, | |
Car{Make: "Peugeot", Model: "205", Colour: "purple", Owner: "Michel"}, | |
Car{Make: "Chery", Model: "S22L", Colour: "white", Owner: "Aarav"}, | |
Car{Make: "Fiat", Model: "Punto", Colour: "violet", Owner: "Pari"}, | |
Car{Make: "Tata", Model: "Nano", Colour: "indigo", Owner: "Valeria"}, | |
Car{Make: "Holden", Model: "Barina", Colour: "brown", Owner: "Shotaro"}, | |
} | |
i := 0 | |
for i < len(cars) { | |
fmt.Println("i is ", i) | |
carAsBytes, _ := json.Marshal(cars[i]) | |
APIstub.PutState("CAR"+strconv.Itoa(i), carAsBytes) | |
fmt.Println("Added", cars[i]) | |
i = i + 1 | |
} | |
return shim.Success(nil) | |
} | |
func (s *SmartContract) createCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { | |
if len(args) != 5 { | |
return shim.Error("Incorrect number of arguments. Expecting 5") | |
} | |
var car = Car{Make: args[1], Model: args[2], Colour: args[3], Owner: args[4]} | |
carAsBytes, _ := json.Marshal(car) | |
APIstub.PutState(args[0], carAsBytes) | |
return shim.Success(nil) | |
} | |
func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response { | |
startKey := "CAR0" | |
endKey := "CAR999" | |
resultsIterator, err := APIstub.GetStateByRange(startKey, endKey) | |
if err != nil { | |
return shim.Error(err.Error()) | |
} | |
defer resultsIterator.Close() | |
// buffer is a JSON array containing QueryResults | |
var buffer bytes.Buffer | |
buffer.WriteString("[") | |
bArrayMemberAlreadyWritten := false | |
for resultsIterator.HasNext() { | |
queryResponse, err := resultsIterator.Next() | |
if err != nil { | |
return shim.Error(err.Error()) | |
} | |
// Add a comma before array members, suppress it for the first array member | |
if bArrayMemberAlreadyWritten == true { | |
buffer.WriteString(",") | |
} | |
buffer.WriteString("{\"Key\":") | |
buffer.WriteString("\"") | |
buffer.WriteString(queryResponse.Key) | |
buffer.WriteString("\"") | |
buffer.WriteString(", \"Record\":") | |
// Record is a JSON object, so we write as-is | |
buffer.WriteString(string(queryResponse.Value)) | |
buffer.WriteString("}") | |
bArrayMemberAlreadyWritten = true | |
} | |
buffer.WriteString("]") | |
fmt.Printf("- queryAllCars:\n%s\n", buffer.String()) | |
return shim.Success(buffer.Bytes()) | |
} | |
func (s *SmartContract) changeCarOwner(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { | |
if len(args) != 2 { | |
return shim.Error("Incorrect number of arguments. Expecting 2") | |
} | |
carAsBytes, _ := APIstub.GetState(args[0]) | |
car := Car{} | |
json.Unmarshal(carAsBytes, &car) | |
car.Owner = args[1] | |
carAsBytes, _ = json.Marshal(car) | |
APIstub.PutState(args[0], carAsBytes) | |
return shim.Success(nil) | |
} | |
// 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) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment