// Invoke function func (t *EventSender) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { b, err := stub.GetState("noevents") if err != nil { return nil, errors.New("Failed to get state") } noevts, _ := strconv.Atoi(string(b)) tosend := "Event " + string(b) for _, s := range args { tosend = tosend + "," + s } err = stub.PutState("noevents", []byte(strconv.Itoa(noevts+1))) if err != nil { return nil, err } err = stub.SetEvent("evtsender", []byte(tosend)) if err != nil { return nil, err } return nil, nil }
// Query callback representing the query of a chaincode func (t *SampleSysCC) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { if function != "getval" { return nil, errors.New("Invalid query function name. Expecting \"getval\"") } var key string // Entities var err error if len(args) != 1 { return nil, errors.New("Incorrect number of arguments. Expecting key to query") } key = args[0] // Get the state from the ledger valbytes, err := stub.GetState(key) if err != nil { jsonResp := "{\"Error\":\"Failed to get state for " + key + "\"}" return nil, errors.New(jsonResp) } if valbytes == nil { jsonResp := "{\"Error\":\"Nil val for " + key + "\"}" return nil, errors.New(jsonResp) } return valbytes, nil }
// ============================================================================================================================ // findMarble4Trade - look for a matching marble that this user owns and return it // ============================================================================================================================ func findMarble4Trade(stub shim.ChaincodeStubInterface, user string, color string, size int) (m Marble, err error) { var fail Marble fmt.Println("- start find marble 4 trade") fmt.Println("looking for " + user + ", " + color + ", " + strconv.Itoa(size)) //get the marble index marblesAsBytes, err := stub.GetState(marbleIndexStr) if err != nil { return fail, errors.New("Failed to get marble index") } var marbleIndex []string json.Unmarshal(marblesAsBytes, &marbleIndex) //un stringify it aka JSON.parse() for i := range marbleIndex { //iter through all the marbles //fmt.Println("looking @ marble name: " + marbleIndex[i]); marbleAsBytes, err := stub.GetState(marbleIndex[i]) //grab this marble if err != nil { return fail, errors.New("Failed to get marble") } res := Marble{} json.Unmarshal(marbleAsBytes, &res) //un stringify it aka JSON.parse() //fmt.Println("looking @ " + res.User + ", " + res.Color + ", " + strconv.Itoa(res.Size)); //check for user && color && size if strings.ToLower(res.User) == strings.ToLower(user) && strings.ToLower(res.Color) == strings.ToLower(color) && res.Size == size { fmt.Println("found a marble: " + res.Name) fmt.Println("! end find marble 4 trade") return res, nil } } fmt.Println("- end find marble 4 trade - error") return fail, errors.New("Did not find marble to use in this trade") }
// Invoke gets the supplied key and if it exists, updates the key with the newly // supplied value. func (t *SampleSysCC) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { var key, val string // Entities if len(args) != 2 { return nil, errors.New("need 2 args (key and a value)") } // Initialize the chaincode key = args[0] val = args[1] _, err := stub.GetState(key) if err != nil { jsonResp := "{\"Error\":\"Failed to get val for " + key + "\"}" return nil, errors.New(jsonResp) } // Write the state to the ledger err = stub.PutState(key, []byte(val)) if err != nil { return nil, err } return nil, nil }
// Query callback representing the query of a chaincode func (t *Attributes2State) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { if function != "read" { return nil, errors.New("Invalid query function name. Expecting \"read\"") } var attributeName string // Name of the attributeName to query. var err error if len(args) != 1 { return nil, errors.New("Incorrect number of arguments. Expecting only 1 (attributeName)") } attributeName = args[0] fmt.Printf("Reading attribute %v", attributeName) // Get the state from the ledger Avalbytes, err := stub.GetState(attributeName) if err != nil { jsonResp := "{\"Error\":\"Failed to get state for " + attributeName + "\"}" fmt.Printf("Query Response:%s\n", jsonResp) return nil, errors.New(jsonResp) } if Avalbytes == nil { jsonResp := "{\"Error\":\"Nil amount for " + attributeName + "\"}" fmt.Printf("Query Response:%s\n", jsonResp) return nil, errors.New(jsonResp) } jsonResp := "{\"Name\":\"" + attributeName + "\",\"Amount\":\"" + string(Avalbytes) + "\"}" fmt.Printf("Query Response:%s\n", jsonResp) return []byte(jsonResp), nil }
// Transaction makes payment of X units from A to B func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { if function == "delete" { // Deletes an entity from its state return t.delete(stub, args) } var A, B string // Entities var Aval, Bval int // Asset holdings var X int // Transaction value var err error if len(args) != 3 { return nil, errors.New("Incorrect number of arguments. Expecting 3") } A = args[0] B = args[1] // Get the state from the ledger // TODO: will be nice to have a GetAllState call to ledger Avalbytes, err := stub.GetState(A) if err != nil { return nil, errors.New("Failed to get state") } if Avalbytes == nil { return nil, errors.New("Entity not found") } Aval, _ = strconv.Atoi(string(Avalbytes)) Bvalbytes, err := stub.GetState(B) if err != nil { return nil, errors.New("Failed to get state") } if Bvalbytes == nil { return nil, errors.New("Entity not found") } Bval, _ = strconv.Atoi(string(Bvalbytes)) // Perform the execution X, err = strconv.Atoi(args[2]) if err != nil { return nil, errors.New("Invalid transaction amount, expecting a integer value") } Aval = Aval - X Bval = Bval + X fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval) // Write the state back to the ledger err = stub.PutState(A, []byte(strconv.Itoa(Aval))) if err != nil { return nil, err } err = stub.PutState(B, []byte(strconv.Itoa(Bval))) if err != nil { return nil, err } return nil, nil }
// ============================================================================================================================ // Delete - remove a key/value pair from state // ============================================================================================================================ func (t *SimpleChaincode) Delete(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { if len(args) != 1 { return nil, errors.New("Incorrect number of arguments. Expecting 1") } name := args[0] err := stub.DelState(name) //remove the key from chaincode state if err != nil { return nil, errors.New("Failed to delete state") } //get the marble index marblesAsBytes, err := stub.GetState(marbleIndexStr) if err != nil { return nil, errors.New("Failed to get marble index") } var marbleIndex []string json.Unmarshal(marblesAsBytes, &marbleIndex) //un stringify it aka JSON.parse() //remove marble from index for i, val := range marbleIndex { fmt.Println(strconv.Itoa(i) + " - looking at " + val + " for " + name) if val == name { //find the correct marble fmt.Println("found marble") marbleIndex = append(marbleIndex[:i], marbleIndex[i+1:]...) //remove it for x := range marbleIndex { //debug prints... fmt.Println(string(x) + " - " + marbleIndex[x]) } break } } jsonAsBytes, _ := json.Marshal(marbleIndex) //save new index err = stub.PutState(marbleIndexStr, jsonAsBytes) return nil, nil }
// delete Deletes an entity from the state, returning error if the entity was not found in the state. func (t *Attributes2State) delete(stub shim.ChaincodeStubInterface, args []string) error { if len(args) != 1 { return errors.New("Incorrect number of arguments. Expecting only 1 (attributeName)") } attributeName := args[0] fmt.Printf("Deleting attribute %v", attributeName) valBytes, err := stub.GetState(attributeName) if err != nil { return err } if valBytes == nil { return errors.New("Attribute '" + attributeName + "' not found.") } isOk, err := stub.VerifyAttribute(attributeName, valBytes) if err != nil { return err } if isOk { // Delete the key from the state in ledger err = stub.DelState(attributeName) if err != nil { return errors.New("Failed to delete state") } } return nil }
// ============================================================================================================================ // Set User Permission on Marble // ============================================================================================================================ func (t *SimpleChaincode) set_user(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { var err error // 0 1 // "name", "bob" if len(args) < 2 { return nil, errors.New("Incorrect number of arguments. Expecting 2") } fmt.Println("- start set user") fmt.Println(args[0] + " - " + args[1]) marbleAsBytes, err := stub.GetState(args[0]) if err != nil { return nil, errors.New("Failed to get thing") } res := Marble{} json.Unmarshal(marbleAsBytes, &res) //un stringify it aka JSON.parse() res.User = args[1] //change the user jsonAsBytes, _ := json.Marshal(res) err = stub.PutState(args[0], jsonAsBytes) //rewrite the marble with id as key if err != nil { return nil, err } fmt.Println("- end set user") return nil, nil }
// Query callback representing the query of a chaincode func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { if function != "query" { return nil, errors.New("Invalid query function name. Expecting \"query\"") } var A string // Entities var err error if len(args) != 1 { return nil, errors.New("Incorrect number of arguments. Expecting name of the person to query") } A = args[0] // Get the state from the ledger Avalbytes, err := stub.GetState(A) if err != nil { jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}" return nil, errors.New(jsonResp) } if Avalbytes == nil { jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}" return nil, errors.New(jsonResp) } jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}" fmt.Printf("Query Response:%s\n", jsonResp) return Avalbytes, nil }
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { var event string // Event entity var err error if len(args) != 1 { return nil, errors.New("Incorrect number of arguments. Expecting entity to query") } event = args[0] // Get the state from the ledger eventValbytes, err := stub.GetState(event) if err != nil { jsonResp := "{\"Error\":\"Failed to get state for " + event + "\"}" return nil, errors.New(jsonResp) } if eventValbytes == nil { jsonResp := "{\"Error\":\"Nil value for " + event + "\"}" return nil, errors.New(jsonResp) } jsonResp := "{\"Name\":\"" + event + "\",\"Amount\":\"" + string(eventValbytes) + "\"}" fmt.Printf("Query Response:%s\n", jsonResp) return []byte(jsonResp), nil }
// Query function func (t *EventSender) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { b, err := stub.GetState("noevents") if err != nil { return nil, errors.New("Failed to get state") } jsonResp := "{\"NoEvents\":\"" + string(b) + "\"}" return []byte(jsonResp), nil }
func (t *AssetManagementChaincode) assign(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { fmt.Println("Assigning Asset...") if len(args) != 2 { return nil, errors.New("Incorrect number of arguments. Expecting 2") } asset := args[0] owner, err := base64.StdEncoding.DecodeString(args[1]) if err != nil { fmt.Printf("Error decoding [%v] \n", err) return nil, errors.New("Failed decodinf owner") } // Recover the role that is allowed to make assignments assignerRole, err := stub.GetState("assignerRole") if err != nil { fmt.Printf("Error getting role [%v] \n", err) return nil, errors.New("Failed fetching assigner role") } callerRole, err := stub.ReadCertAttribute("role") if err != nil { fmt.Printf("Error reading attribute 'role' [%v] \n", err) return nil, fmt.Errorf("Failed fetching caller role. Error was [%v]", err) } caller := string(callerRole[:]) assigner := string(assignerRole[:]) if caller != assigner { fmt.Printf("Caller is not assigner - caller %v assigner %v\n", caller, assigner) return nil, fmt.Errorf("The caller does not have the rights to invoke assign. Expected role [%v], caller role [%v]", assigner, caller) } account, err := attr.GetValueFrom("account", owner) if err != nil { fmt.Printf("Error reading account [%v] \n", err) return nil, fmt.Errorf("Failed fetching recipient account. Error was [%v]", err) } // Register assignment myLogger.Debugf("New owner of [%s] is [% x]", asset, owner) ok, err := stub.InsertRow("AssetsOwnership", shim.Row{ Columns: []*shim.Column{ &shim.Column{Value: &shim.Column_String_{String_: asset}}, &shim.Column{Value: &shim.Column_Bytes{Bytes: account}}}, }) if !ok && err == nil { fmt.Println("Error inserting row") return nil, errors.New("Asset was already assigned.") } return nil, err }
func (t *ChaincodeExample) GetState(stub shim.ChaincodeStubInterface, entity string) (int, error) { bytes, err := stub.GetState(entity) if err != nil { return 0, errors.New("Failed to get state") } if bytes == nil { return 0, errors.New("Entity not found") } val, _ := strconv.Atoi(string(bytes)) return val, nil }
// Invoke gets the supplied key and if it exists, updates the key with the newly // supplied value. func (t *SampleSysCC) Invoke(stub shim.ChaincodeStubInterface) ([]byte, error) { f, args := stub.GetFunctionAndParameters() switch f { case "putval": if len(args) != 2 { return nil, errors.New("need 2 args (key and a value)") } // Initialize the chaincode key := args[0] val := args[1] _, err := stub.GetState(key) if err != nil { jsonResp := "{\"Error\":\"Failed to get val for " + key + "\"}" return nil, errors.New(jsonResp) } // Write the state to the ledger err = stub.PutState(key, []byte(val)) return nil, err case "getval": var err error if len(args) != 1 { return nil, errors.New("Incorrect number of arguments. Expecting key to query") } key := args[0] // Get the state from the ledger valbytes, err := stub.GetState(key) if err != nil { jsonResp := "{\"Error\":\"Failed to get state for " + key + "\"}" return nil, errors.New(jsonResp) } if valbytes == nil { jsonResp := "{\"Error\":\"Nil val for " + key + "\"}" return nil, errors.New(jsonResp) } return valbytes, nil default: jsonResp := "{\"Error\":\"Unknown functon " + f + "\"}" return nil, errors.New(jsonResp) } }
// ============================================================================================================================ // Read - read a variable from chaincode state // ============================================================================================================================ func (t *SimpleChaincode) read(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { var name, jsonResp string var err error if len(args) != 1 { return nil, errors.New("Incorrect number of arguments. Expecting name of the var to query") } name = args[0] valAsbytes, err := stub.GetState(name) //get the var from chaincode state if err != nil { jsonResp = "{\"Error\":\"Failed to get state for " + name + "\"}" return nil, errors.New(jsonResp) } return valAsbytes, nil //send it onward }
func (t *AssetManagementChaincode) assign(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { myLogger.Debug("Assign...") if len(args) != 2 { return nil, errors.New("Incorrect number of arguments. Expecting 2") } asset := args[0] owner, err := base64.StdEncoding.DecodeString(args[1]) if err != nil { return nil, errors.New("Failed decodinf owner") } // Verify the identity of the caller // Only an administrator can invoker assign adminCertificate, err := stub.GetState("admin") if err != nil { return nil, errors.New("Failed fetching admin identity") } ok, err := t.isCaller(stub, adminCertificate) if err != nil { return nil, errors.New("Failed checking admin identity") } if !ok { return nil, errors.New("The caller is not an administrator") } // Register assignment myLogger.Debugf("New owner of [%s] is [% x]", asset, owner) ok, err = stub.InsertRow("AssetsOwnership", shim.Row{ Columns: []*shim.Column{ &shim.Column{Value: &shim.Column_String_{String_: asset}}, &shim.Column{Value: &shim.Column_Bytes{Bytes: owner}}}, }) if !ok && err == nil { return nil, errors.New("Asset was already assigned.") } myLogger.Debug("Assign...done!") return nil, err }
// Query has two functions // get - takes one argument, a key, and returns the value for the key // keys - returns all keys stored in this chaincode func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { switch function { case "get": if len(args) < 1 { return nil, errors.New("get operation must include one argument, a key") } key := args[0] value, err := stub.GetState(key) if err != nil { return nil, fmt.Errorf("get operation failed. Error accessing state: %s", err) } return value, nil case "keys": keysIter, err := stub.RangeQueryState("", "") if err != nil { return nil, fmt.Errorf("keys operation failed. Error accessing state: %s", err) } defer keysIter.Close() var keys []string for keysIter.HasNext() { key, _, iterErr := keysIter.Next() if iterErr != nil { return nil, fmt.Errorf("keys operation failed. Error accessing state: %s", err) } keys = append(keys, key) } jsonKeys, err := json.Marshal(keys) if err != nil { return nil, fmt.Errorf("keys operation failed. Error marshaling JSON: %s", err) } return jsonKeys, nil default: return nil, errors.New("Unsupported operation") } }
func (t *AuthorizableCounterChaincode) read(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { var err error // Get the state from the ledger Avalbytes, err := stub.GetState("counter") if err != nil { jsonResp := "{\"Error\":\"Failed to get state for counter\"}" return nil, errors.New(jsonResp) } if Avalbytes == nil { jsonResp := "{\"Error\":\"Nil amount for counter\"}" return nil, errors.New(jsonResp) } jsonResp := "{\"Name\":\"counter\",\"Amount\":\"" + string(Avalbytes) + "\"}" fmt.Printf("Query Response:%s\n", jsonResp) return Avalbytes, nil }
//Invoke makes increment counter func (t *AuthorizableCounterChaincode) increment(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { val, err := stub.ReadCertAttribute("position") fmt.Printf("Position => %v error %v \n", string(val), err) isOk, _ := stub.VerifyAttribute("position", []byte("Software Engineer")) // Here the ABAC API is called to verify the attribute, just if the value is verified the counter will be incremented. if isOk { counter, err := stub.GetState("counter") if err != nil { return nil, err } var cInt int cInt, err = strconv.Atoi(string(counter)) if err != nil { return nil, err } cInt = cInt + 1 counter = []byte(strconv.Itoa(cInt)) stub.PutState("counter", counter) } return nil, nil }
// ============================================================================================================================ // Remove Open Trade - close an open trade // ============================================================================================================================ func (t *SimpleChaincode) remove_trade(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { var err error // 0 //[data.id] if len(args) < 1 { return nil, errors.New("Incorrect number of arguments. Expecting 1") } fmt.Println("- start remove trade") timestamp, err := strconv.ParseInt(args[0], 10, 64) if err != nil { return nil, errors.New("1st argument must be a numeric string") } //get the open trade struct tradesAsBytes, err := stub.GetState(openTradesStr) if err != nil { return nil, errors.New("Failed to get opentrades") } var trades AllTrades json.Unmarshal(tradesAsBytes, &trades) //un stringify it aka JSON.parse() for i := range trades.OpenTrades { //look for the trade //fmt.Println("looking at " + strconv.FormatInt(trades.OpenTrades[i].Timestamp, 10) + " for " + strconv.FormatInt(timestamp, 10)) if trades.OpenTrades[i].Timestamp == timestamp { fmt.Println("found the trade") trades.OpenTrades = append(trades.OpenTrades[:i], trades.OpenTrades[i+1:]...) //remove this trade jsonAsBytes, _ := json.Marshal(trades) err = stub.PutState(openTradesStr, jsonAsBytes) //rewrite open orders if err != nil { return nil, err } break } } fmt.Println("- end remove trade") return nil, nil }
func (t *RBACChaincode) read(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { if len(args) != 0 { return nil, errors.New("Incorrect number of arguments. Expecting 0") } myLogger.Debug("Read...") // Verify that the invoker has the 'reader' role ok, _, err := t.hasInvokerRole(stub, "reader") if err != nil { return nil, fmt.Errorf("Failed checking role [%s]", err) } if !ok { return nil, fmt.Errorf("The invoker does not have the required roles") } res, err := stub.GetState("state") if err != nil { return nil, fmt.Errorf("Failed getting state [%s]", err) } myLogger.Debug("State [%s]", string(res)) return res, nil }
// ============================================================================================================================ // Perform Trade - close an open trade and move ownership // ============================================================================================================================ func (t *SimpleChaincode) perform_trade(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { var err error // 0 1 2 3 4 5 //[data.id, data.closer.user, data.closer.name, data.opener.user, data.opener.color, data.opener.size] if len(args) < 6 { return nil, errors.New("Incorrect number of arguments. Expecting 6") } fmt.Println("- start close trade") timestamp, err := strconv.ParseInt(args[0], 10, 64) if err != nil { return nil, errors.New("1st argument must be a numeric string") } size, err := strconv.Atoi(args[5]) if err != nil { return nil, errors.New("6th argument must be a numeric string") } //get the open trade struct tradesAsBytes, err := stub.GetState(openTradesStr) if err != nil { return nil, errors.New("Failed to get opentrades") } var trades AllTrades json.Unmarshal(tradesAsBytes, &trades) //un stringify it aka JSON.parse() for i := range trades.OpenTrades { //look for the trade fmt.Println("looking at " + strconv.FormatInt(trades.OpenTrades[i].Timestamp, 10) + " for " + strconv.FormatInt(timestamp, 10)) if trades.OpenTrades[i].Timestamp == timestamp { fmt.Println("found the trade") marbleAsBytes, err := stub.GetState(args[2]) if err != nil { return nil, errors.New("Failed to get thing") } closersMarble := Marble{} json.Unmarshal(marbleAsBytes, &closersMarble) //un stringify it aka JSON.parse() //verify if marble meets trade requirements if closersMarble.Color != trades.OpenTrades[i].Want.Color || closersMarble.Size != trades.OpenTrades[i].Want.Size { msg := "marble in input does not meet trade requriements" fmt.Println(msg) return nil, errors.New(msg) } marble, e := findMarble4Trade(stub, trades.OpenTrades[i].User, args[4], size) //find a marble that is suitable from opener if e == nil { fmt.Println("! no errors, proceeding") t.set_user(stub, []string{args[2], trades.OpenTrades[i].User}) //change owner of selected marble, closer -> opener t.set_user(stub, []string{marble.Name, args[1]}) //change owner of selected marble, opener -> closer trades.OpenTrades = append(trades.OpenTrades[:i], trades.OpenTrades[i+1:]...) //remove trade jsonAsBytes, _ := json.Marshal(trades) err = stub.PutState(openTradesStr, jsonAsBytes) //rewrite open orders if err != nil { return nil, err } } } } fmt.Println("- end close trade") return nil, nil }
// ============================================================================================================================ // Open Trade - create an open trade for a marble you want with marbles you have // ============================================================================================================================ func (t *SimpleChaincode) open_trade(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { var err error var will_size int var trade_away Description // 0 1 2 3 4 5 6 //["bob", "blue", "16", "red", "16"] *"blue", "35* if len(args) < 5 { return nil, errors.New("Incorrect number of arguments. Expecting like 5?") } if len(args)%2 == 0 { return nil, errors.New("Incorrect number of arguments. Expecting an odd number") } size1, err := strconv.Atoi(args[2]) if err != nil { return nil, errors.New("3rd argument must be a numeric string") } open := AnOpenTrade{} open.User = args[0] open.Timestamp = makeTimestamp() //use timestamp as an ID open.Want.Color = args[1] open.Want.Size = size1 fmt.Println("- start open trade") jsonAsBytes, _ := json.Marshal(open) err = stub.PutState("_debug1", jsonAsBytes) for i := 3; i < len(args); i++ { //create and append each willing trade will_size, err = strconv.Atoi(args[i+1]) if err != nil { msg := "is not a numeric string " + args[i+1] fmt.Println(msg) return nil, errors.New(msg) } trade_away = Description{} trade_away.Color = args[i] trade_away.Size = will_size fmt.Println("! created trade_away: " + args[i]) jsonAsBytes, _ = json.Marshal(trade_away) err = stub.PutState("_debug2", jsonAsBytes) open.Willing = append(open.Willing, trade_away) fmt.Println("! appended willing to open") i++ } //get the open trade struct tradesAsBytes, err := stub.GetState(openTradesStr) if err != nil { return nil, errors.New("Failed to get opentrades") } var trades AllTrades json.Unmarshal(tradesAsBytes, &trades) //un stringify it aka JSON.parse() trades.OpenTrades = append(trades.OpenTrades, open) //append to open trades fmt.Println("! appended open to trades") jsonAsBytes, _ = json.Marshal(trades) err = stub.PutState(openTradesStr, jsonAsBytes) //rewrite open orders if err != nil { return nil, err } fmt.Println("- end open trade") return nil, nil }
// ============================================================================================================================ // Init Marble - create a new marble, store into chaincode state // ============================================================================================================================ func (t *SimpleChaincode) init_marble(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { var err error // 0 1 2 3 // "asdf", "blue", "35", "bob" if len(args) != 4 { return nil, errors.New("Incorrect number of arguments. Expecting 4") } //input sanitation fmt.Println("- start init marble") if len(args[0]) <= 0 { return nil, errors.New("1st argument must be a non-empty string") } if len(args[1]) <= 0 { return nil, errors.New("2nd argument must be a non-empty string") } if len(args[2]) <= 0 { return nil, errors.New("3rd argument must be a non-empty string") } if len(args[3]) <= 0 { return nil, errors.New("4th argument must be a non-empty string") } name := args[0] color := strings.ToLower(args[1]) user := strings.ToLower(args[3]) size, err := strconv.Atoi(args[2]) if err != nil { return nil, errors.New("3rd argument must be a numeric string") } //check if marble already exists marbleAsBytes, err := stub.GetState(name) if err != nil { return nil, errors.New("Failed to get marble name") } res := Marble{} json.Unmarshal(marbleAsBytes, &res) if res.Name == name { fmt.Println("This marble arleady exists: " + name) fmt.Println(res) return nil, errors.New("This marble arleady exists") //all stop a marble by this name exists } //build the marble json string manually str := `{"name": "` + name + `", "color": "` + color + `", "size": ` + strconv.Itoa(size) + `, "user": "******"}` err = stub.PutState(name, []byte(str)) //store marble with id as key if err != nil { return nil, err } //get the marble index marblesAsBytes, err := stub.GetState(marbleIndexStr) if err != nil { return nil, errors.New("Failed to get marble index") } var marbleIndex []string json.Unmarshal(marblesAsBytes, &marbleIndex) //un stringify it aka JSON.parse() //append marbleIndex = append(marbleIndex, name) //add marble name to index list fmt.Println("! marble index: ", marbleIndex) jsonAsBytes, _ := json.Marshal(marbleIndex) err = stub.PutState(marbleIndexStr, jsonAsBytes) //store name of marble fmt.Println("- end init marble") return nil, nil }
// Invoke has two functions // put - takes two arguements, a key and value, and stores them in the state // remove - takes one argument, a key, and removes if from the state func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) ([]byte, error) { function, args := stub.GetFunctionAndParameters() switch function { case "put": if len(args) < 2 { return nil, errors.New("put operation must include two arguments, a key and value") } key := args[0] value := args[1] err := stub.PutState(key, []byte(value)) if err != nil { fmt.Printf("Error putting state %s", err) return nil, fmt.Errorf("put operation failed. Error updating state: %s", err) } return nil, nil case "remove": if len(args) < 1 { return nil, errors.New("remove operation must include one argument, a key") } key := args[0] err := stub.DelState(key) if err != nil { return nil, fmt.Errorf("remove operation failed. Error updating state: %s", err) } return nil, nil case "get": if len(args) < 1 { return nil, errors.New("get operation must include one argument, a key") } key := args[0] value, err := stub.GetState(key) if err != nil { return nil, fmt.Errorf("get operation failed. Error accessing state: %s", err) } return value, nil case "keys": keysIter, err := stub.RangeQueryState("", "") if err != nil { return nil, fmt.Errorf("keys operation failed. Error accessing state: %s", err) } defer keysIter.Close() var keys []string for keysIter.HasNext() { key, _, iterErr := keysIter.Next() if iterErr != nil { return nil, fmt.Errorf("keys operation failed. Error accessing state: %s", err) } keys = append(keys, key) } jsonKeys, err := json.Marshal(keys) if err != nil { return nil, fmt.Errorf("keys operation failed. Error marshaling JSON: %s", err) } return jsonKeys, nil default: return nil, errors.New("Unsupported operation") } }
// ============================================================================================================================ // Clean Up Open Trades - make sure open trades are still possible, remove choices that are no longer possible, remove trades that have no valid choices // ============================================================================================================================ func cleanTrades(stub shim.ChaincodeStubInterface) (err error) { var didWork = false fmt.Println("- start clean trades") //get the open trade struct tradesAsBytes, err := stub.GetState(openTradesStr) if err != nil { return errors.New("Failed to get opentrades") } var trades AllTrades json.Unmarshal(tradesAsBytes, &trades) //un stringify it aka JSON.parse() fmt.Println("# trades " + strconv.Itoa(len(trades.OpenTrades))) for i := 0; i < len(trades.OpenTrades); { //iter over all the known open trades fmt.Println(strconv.Itoa(i) + ": looking at trade " + strconv.FormatInt(trades.OpenTrades[i].Timestamp, 10)) fmt.Println("# options " + strconv.Itoa(len(trades.OpenTrades[i].Willing))) for x := 0; x < len(trades.OpenTrades[i].Willing); { //find a marble that is suitable fmt.Println("! on next option " + strconv.Itoa(i) + ":" + strconv.Itoa(x)) _, e := findMarble4Trade(stub, trades.OpenTrades[i].User, trades.OpenTrades[i].Willing[x].Color, trades.OpenTrades[i].Willing[x].Size) if e != nil { fmt.Println("! errors with this option, removing option") didWork = true trades.OpenTrades[i].Willing = append(trades.OpenTrades[i].Willing[:x], trades.OpenTrades[i].Willing[x+1:]...) //remove this option x-- } else { fmt.Println("! this option is fine") } x++ fmt.Println("! x:" + strconv.Itoa(x)) if x >= len(trades.OpenTrades[i].Willing) { //things might have shifted, recalcuate break } } if len(trades.OpenTrades[i].Willing) == 0 { fmt.Println("! no more options for this trade, removing trade") didWork = true trades.OpenTrades = append(trades.OpenTrades[:i], trades.OpenTrades[i+1:]...) //remove this trade i-- } i++ fmt.Println("! i:" + strconv.Itoa(i)) if i >= len(trades.OpenTrades) { //things might have shifted, recalcuate break } } if didWork { fmt.Println("! saving open trade changes") jsonAsBytes, _ := json.Marshal(trades) err = stub.PutState(openTradesStr, jsonAsBytes) //rewrite open orders if err != nil { return err } } else { fmt.Println("! all open trades are fine") } fmt.Println("- end clean trades") return nil }
// Transaction makes payment of X units from A to B func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) { if function == "delete" { // Deletes an entity from its state return t.delete(stub, args) } if function == "createAccNO" { accNO := args[0] var amount int var err error if 1 == len(args) { amount = 0 } else { amount, err = strconv.Atoi(args[1]) if err != nil { return nil, errors.New("Expecting integer value for asset holding") } } err = stub.PutState(accNO, []byte(strconv.Itoa(amount))) if err != nil { return nil, err } } if function == "transferAcc" { if len(args) != 3 { return nil, errors.New("Incorrect number of arguments. Expecting 3") } srcAcc := args[0] // 转出户名 tarAcc := args[1] // 转入户名 amount, err := strconv.Atoi(args[2]) // 金额 // 获取A的余额 srcAccvalbytes, err := stub.GetState(srcAcc) if err != nil { return nil, errors.New("Failed to get state") } if srcAccvalbytes == nil { return nil, errors.New("Entity not found") } srcAccVal, _ := strconv.Atoi(string(srcAccvalbytes)) // 获取B的月 tarAccvalbytes, err := stub.GetState(tarAcc) if err != nil { return nil, errors.New("Failed to get state") } if tarAccvalbytes == nil { return nil, errors.New("Entity not found") } tarAccVal, _ := strconv.Atoi(string(tarAccvalbytes)) srcAccVal -= amount tarAccVal += amount // Write the state back to the ledger err = stub.PutState(srcAcc, []byte(strconv.Itoa(srcAccVal))) if err != nil { return nil, err } err = stub.PutState(tarAcc, []byte(strconv.Itoa(tarAccVal))) if err != nil { return nil, err } } if function == "ECashPrinter" { accNO := args[0] // 转出户名 amount, err := strconv.Atoi(args[1]) // 金额 // 获取A的余额 accValbytes, err := stub.GetState(accNO) if err != nil { return nil, errors.New("Failed to get state") } if accValbytes == nil { return nil, errors.New("Entity not found") } accVal, _ := strconv.Atoi(string(accValbytes)) accVal += amount // Write the state back to the ledger err = stub.PutState(accNO, []byte(strconv.Itoa(accVal))) if err != nil { return nil, err } } return nil, nil }