From 06dfc409b5e8788c545e17dc221619cc6ae62b24 Mon Sep 17 00:00:00 2001 From: projet Date: Wed, 3 Apr 2019 10:17:16 +0200 Subject: [PATCH] correction des bugs --- monnethic.go | 265 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 262 insertions(+), 3 deletions(-) diff --git a/monnethic.go b/monnethic.go index 6bbcbcc..b5166f7 100644 --- a/monnethic.go +++ b/monnethic.go @@ -23,10 +23,12 @@ package main //hard-coding. import ( + "bytes" "encoding/json" "fmt" "strconv" "strings" + "time" "github.com/hyperledger/fabric/core/chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer" @@ -113,6 +115,9 @@ func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { } else if function == "deleteUser" { // delete a specific user from the ledger return t.deleteUser(stub, args) + } else if function == "setUserPermission" { + // change the permission of an account + return t.setUserPermission(stub, args) } else if function == "initWallet" { // initiate a new wallet return t.initWallet(stub, args) @@ -131,6 +136,18 @@ func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { } else if function == "transaction" { // make a transaction of X units from a wallet to an other return t.transaction(stub, args) + } else if function == "queryWalletsByOwner" { + // make a transaction of X units from a wallet to an other + return t.queryWalletsByOwner(stub, args) + } else if function == "queryWalletsByType" { + // make a transaction of X units from a wallet to an other + return t.queryWalletsByType(stub, args) + } else if function == "queryWallets" { + // make a transaction of X units from a wallet to an other + return t.queryWallets(stub, args) + } else if function == "getHistoryForWallet" { + // make a transaction of X units from a wallet to an other + return t.getHistoryForWallet(stub, args) } return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\" \"register\"") @@ -438,6 +455,49 @@ func (t *SimpleChaincode) deleteUser(stub shim.ChaincodeStubInterface, args []st } +// =========================================================== +// set a permission of an account by setting authorization to create a wallet +// =========================================================== +func (t *SimpleChaincode) setUserPermission(stub shim.ChaincodeStubInterface, args []string) pb.Response { + + // 0 1 + // "name", "bob" + if len(args) < 1 { + return shim.Error("Incorrect number of arguments. Expecting 2") + } + + userId := args[0] + + fmt.Println("- start setUserPermission ", userId) + + // ==== Check if user already exists ==== + ownerAsBytes, err := stub.GetState(userId) + if err != nil { + return shim.Error("Failed to get user: " + err.Error()) + } else if ownerAsBytes == nil { + fmt.Println("This wallet doesn't exists: " + userId) + return shim.Error("This wallet doesn't exists: " + userId) + } + + ownerToSet := owner{} + err = json.Unmarshal(ownerAsBytes, &ownerToSet) //unmarshal it aka JSON + if err != nil { + return shim.Error(err.Error()) + } + + //if walletToSet.Owner + ownerToSet.UserAuthorized = true //change the permission + + ownerJSONasBytes, _ := json.Marshal(ownerToSet) + err = stub.PutState(userId, ownerJSONasBytes) //rewrite the wallet + if err != nil { + return shim.Error(err.Error()) + } + fmt.Println("- end setUserPermission (success)") + return shim.Success(nil) +} + + func (t *SimpleChaincode) initWallet(stub shim.ChaincodeStubInterface, args []string) pb.Response { var err error @@ -465,7 +525,7 @@ func (t *SimpleChaincode) initWallet(stub shim.ChaincodeStubInterface, args []st walletId := args[0] walletType := strings.ToLower(args[1]) - owner := strings.ToLower(args[2]) + owner := args[2] sold := 0 //authorized_by_association := args[4] @@ -697,7 +757,9 @@ func (t *SimpleChaincode) setSoldOnWallet(stub shim.ChaincodeStubInterface, args if err != nil { return shim.Error(err.Error()) } - walletToSet.Sold = newSold //change the sold + + //if walletToSet.Owner + walletToSet.Sold = walletToSet.Sold + newSold //change the sold walletJSONasBytes, _ := json.Marshal(walletToSet) err = stub.PutState(walletId, walletJSONasBytes) //rewrite the wallet @@ -746,7 +808,11 @@ func (t *SimpleChaincode) transaction(stub shim.ChaincodeStubInterface, args []s return shim.Error(err.Error()) } - walletSoldToSet.Sold = walletSoldToSet.Sold - transactionValue //change the sold + if walletSoldToSet.Sold <= 0 { + return shim.Error("This wallet is not allowed to make a transaction:" + walletId) + } else { + walletSoldToSet.Sold = walletSoldToSet.Sold - transactionValue //change the sold + } walletJSONasBytes, _ := json.Marshal(walletSoldToSet) err = stub.PutState(walletId, walletJSONasBytes) //rewrite the wallet @@ -773,9 +839,202 @@ func (t *SimpleChaincode) transaction(stub shim.ChaincodeStubInterface, args []s } +func (t *SimpleChaincode) queryWalletsByOwner(stub shim.ChaincodeStubInterface, args []string) pb.Response { + + // 0 + // "bob" + if len(args) < 1 { + return shim.Error("Incorrect number of arguments. Expecting 1") + } + + owner := strings.ToLower(args[0]) + + queryString := fmt.Sprintf("{\"selector\":{\"docType\":\"wallet\",\"owner\":\"%s\"}}", owner) + + queryResults, err := getQueryResultForQueryString(stub, queryString) + if err != nil { + return shim.Error(err.Error()) + } + return shim.Success(queryResults) +} + + +func (t *SimpleChaincode) queryWalletsByType(stub shim.ChaincodeStubInterface, args []string) pb.Response { + + // 0 + // "bob" + if len(args) < 1 { + return shim.Error("Incorrect number of arguments. Expecting 1") + } + + walletType := strings.ToLower(args[0]) + + queryString := fmt.Sprintf("{\"selector\":{\"docType\":\"wallet\",\"walletType\":\"%s\"}}", walletType) + + queryResults, err := getQueryResultForQueryString(stub, queryString) + if err != nil { + return shim.Error(err.Error()) + } + return shim.Success(queryResults) +} + + +// ===== Example: Ad hoc rich query ======================================================== +// queryMarbles uses a query string to perform a query for marbles. +// Query string matching state database syntax is passed in and executed as is. +// Supports ad hoc queries that can be defined at runtime by the client. +// If this is not desired, follow the queryMarblesForOwner example for parameterized queries. +// Only available on state databases that support rich query (e.g. CouchDB) +// ========================================================================================= +func (t *SimpleChaincode) queryWallets(stub shim.ChaincodeStubInterface, args []string) pb.Response { + + // 0 + // "queryString" + if len(args) < 1 { + return shim.Error("Incorrect number of arguments. Expecting 1") + } + + queryString := args[0] + + queryResults, err := getQueryResultForQueryString(stub, queryString) + if err != nil { + return shim.Error(err.Error()) + } + return shim.Success(queryResults) +} + + +func (t *SimpleChaincode) getHistoryForWallet(stub shim.ChaincodeStubInterface, args []string) pb.Response { + + if len(args) < 1 { + return shim.Error("Incorrect number of arguments. Expecting 1") + } + + walletId := args[0] + + fmt.Printf("- start getHistoryForWallet: %s\n", walletId) + + resultsIterator, err := stub.GetHistoryForKey(walletId) + if err != nil { + return shim.Error(err.Error()) + } + defer resultsIterator.Close() + + // buffer is a JSON array containing historic values for the marble + var buffer bytes.Buffer + buffer.WriteString("[") + + bArrayMemberAlreadyWritten := false + for resultsIterator.HasNext() { + response, 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("{\"TxId\":") + buffer.WriteString("\"") + buffer.WriteString(response.TxId) + buffer.WriteString("\"") + + buffer.WriteString(", \"Value\":") + // if it was a delete operation on given key, then we need to set the + //corresponding value null. Else, we will write the response.Value + //as-is (as the Value itself a JSON marble) + if response.IsDelete { + buffer.WriteString("null") + } else { + buffer.WriteString(string(response.Value)) + } + + buffer.WriteString(", \"Timestamp\":") + buffer.WriteString("\"") + buffer.WriteString(time.Unix(response.Timestamp.Seconds, int64(response.Timestamp.Nanos)).String()) + buffer.WriteString("\"") + + buffer.WriteString(", \"IsDelete\":") + buffer.WriteString("\"") + buffer.WriteString(strconv.FormatBool(response.IsDelete)) + buffer.WriteString("\"") + + buffer.WriteString("}") + bArrayMemberAlreadyWritten = true + } + buffer.WriteString("]") + + fmt.Printf("- getHistoryForWallet returning:\n%s\n", buffer.String()) + + return shim.Success(buffer.Bytes()) +} + + func main() { err := shim.Start(new(SimpleChaincode)) if err != nil { fmt.Printf("Error starting Simple chaincode: %s", err) } } + + +// =========================================================================================== +// constructQueryResponseFromIterator constructs a JSON array containing query results from +// a given result iterator +// =========================================================================================== +func constructQueryResponseFromIterator(resultsIterator shim.StateQueryIteratorInterface) (*bytes.Buffer, error) { + // 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 nil, err + } + // 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("]") + + return &buffer, nil +} + + +// ========================================================================================= +// getQueryResultForQueryString executes the passed in query string. +// Result set is built and returned as a byte array containing the JSON results. +// ========================================================================================= +func getQueryResultForQueryString(stub shim.ChaincodeStubInterface, queryString string) ([]byte, error) { + + fmt.Printf("- getQueryResultForQueryString queryString:\n%s\n", queryString) + + resultsIterator, err := stub.GetQueryResult(queryString) + if err != nil { + return nil, err + } + defer resultsIterator.Close() + + buffer, err := constructQueryResponseFromIterator(resultsIterator) + if err != nil { + return nil, err + } + + fmt.Printf("- getQueryResultForQueryString queryResult:\n%s\n", buffer.String()) + + return buffer.Bytes(), nil +} +