-
Notifications
You must be signed in to change notification settings - Fork 0
/
SmartContract.go
209 lines (207 loc) · 7.36 KB
/
SmartContract.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
// Smart Contract used in the project -
package main
import (
"fmt"
"time"
"bytes"
"strings"
"strconv"
"encoding/json"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
)
// SimpleAsset implements a simple chaincode to manage an asset
type SmartContract struct {
}
type Person struct {
Name string `json:"name"`
Rollno int `json:"rollno"`
Designation string `json:"desg"`
Hash string `json:"hash"`
}
// Init is called during chaincode instantiation to initialize any
// data. Note that chaincode upgrade also calls this function to reset
// or to migrate data.
func (t *SmartContract) Init(stub shim.ChaincodeStubInterface) peer.Response {
// Get the args from the transaction proposal
args := stub.GetStringArgs()
var check bool
if len(args) != 5 {
return shim.Error("Incorrect arguments, Expecting 5")
}
if len(args[4])!= 46 {
return shim.Error(fmt.Sprintf("hash should be 46 characters long"))
}
check = strings.HasPrefix(args[4], "Qm")
if check != true {
return shim.Error(fmt.Sprintf("hash should start with Qm"))
}
rollno,errp := strconv.Atoi(args[2])
if errp != nil {
return shim.Error(fmt.Sprintf("Error starting SmartContract chaincode: %s", errp))
}
var data = Person{Name: args[1], Rollno: rollno, Designation: args[3], Hash:
args[4]}
PersonBytes, _ := json.Marshal(data)
err := stub.PutState(args[2], PersonBytes)
if err != nil {
return shim.Error(fmt.Sprintf("Failed to create record for: %s", args[2]))
}
return shim.Success(nil)
}
// Invoke is called per transaction on the chaincode. Each transaction is
// either a 'get' or a 'set' on the asset created by Init function. The Set
// method may create a new asset by specifying a new key-value pair.
func (t *SmartContract) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
// Extract the function and args from the transaction proposal
fn, args := stub.GetFunctionAndParameters()
var result string
var err error
if fn != "invoke" {
return shim.Error("unknown fxn call")
}
if args[0] == "set"{
result,err = set(stub, args)
} else if args[0] == "clerk" || args[0] == "hod"{ // assume 'get' even if fn is nil
result, err = get(stub, args)
} else if args[0] == "getHistory"{
return getHistory(stub, args)
} else if args[0] == "accounts"{
return getall(stub)
} else if args[0] == "warden"{
if args[1] == ""{
return getall(stub)
} else {
result, err = get(stub, args)
}
}
if err != nil {
return shim.Error(err.Error())
}
return shim.Success([]byte(result))
}
// Set stores the asset (both key and value) on the ledger. If the key exists,
// it will override the value with the new one
func set(stub shim.ChaincodeStubInterface, args []string) (string, error) {
var check bool
if len(args) != 5 {
return "", fmt.Errorf("Incorrect arguments, Expecting 5")
}
if len(args[4])!=46 {
return "", fmt.Errorf("hash should be 46 characters long")
}
check = strings.HasPrefix(args[4], "Qm")
if check != true {
return "", fmt.Errorf("hash should start with Qm")
}
rollno, errp := strconv.Atoi(args[2])
if errp != nil {
return "",fmt.Errorf("Error starting SmartContract chaincode: %s", errp)
}
var data = Person{Name: args[1], Rollno: rollno, Designation: args[3], Hash:
args[4]}
PersontBytes, _ := json.Marshal(data)
err := stub.PutState(args[2], PersonBytes)
if err != nil {
return "", fmt.Errorf("Failed to set asset: %s", args[2])
}
// Notify listeners that an event "eventInvoke" have been executed (check line 19
in the file invoke.go)
err = stub.SetEvent("eventInvoke", []byte{})
if err != nil {
return "", fmt.Errorf("Failed to set asset: %s", args[2])
}
return args[2], nil
}
// Get returns the value of the specified asset key
func get(stub shim.ChaincodeStubInterface, args []string) (string, error) {
if len(args) != 2 {
return "", fmt.Errorf("Incorrect arguments. Expecting a key")
}
PersonBytes, err := stub.GetState(args[1])
if err != nil {
return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[1], err)
}
if PersomBytes == nil {
return "", fmt.Errorf("Asset not found: %s", args[1])
}
return string(PersonBytes), nil
}
// getHistory returns the complete history for any transactions made corresponding to same participant
func getHistory(stub shim.ChaincodeStubInterface, args []string) peer.Response {
if len(args) < 2 {
return shim.Error("Incorrect number of arguments, Expecting 2")
}
PersonId := args[1]
fmt.Printf("- start getHistory: %s\n", PersonId)
resultsIterator, err := stub.GetHistoryForKey(PersonId)
if err != nil {
return shim.Error(err.Error())
}
defer resultsIterator.Close()
//buffer is a json array containing historic values for the person
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'll write the response.Value
//as-is (as the Value itself a JSON person)
if response.IsDelete {
buffer.WriteString("null")
} else {
buffer.WriteString(string(response.Value))
}
buffer.WriteString(",\"Timestamp\":")
buffer.WriteString("\"")
buffer.WriteString(time.Unix(response.Timestamp.Seconds+19800, int64
(response.Timestamp.Nanos)).String())
buffer.WriteString("\"")
buffer.WriteString("}")
bArrayMemberAlreadyWritten = true
}
buffer.WriteString("]")
fmt.Printf("- getHistory returning:\n%s\n", buffer.String())
fmt.Printf("\n");
return shim.Success(buffer.Bytes())
}
// getall lists out all the participants existing in the ledger
func getall(stub shim.ChaincodeStubInterface) peer.Response {
startkey := "172000"
endkey := "172100"
PersonBytes, err := stub.GetStateByRange(startkey,endkey)
if err != nil {
return shim.Error(err.Error())
}
defer PersonBytes.Close()
var buffer bytes.Buffer
for PersonBytes.HasNext() {
queryResponse, err := PersonBytes.Next()
if err != nil {
return shim.Error(err.Error())
}
buffer.WriteString(string(queryResponse.Value))
}
fmt.Printf("-all query:\n%s\n",buffer.String())
return shim.Success(buffer.Bytes())
}
// main function starts up the chaincode in the container during instantiate
func main() {
err := shim.Start(new(SmartContract));
if err != nil {
fmt.Printf("Error starting SmartContract chaincode: %s", err)
}
}