查看“诊疗信息的分布式记录系统”的源代码
←
诊疗信息的分布式记录系统
跳转至:
导航
、
搜索
因为以下原因,你没有权限编辑本页:
您刚才请求的操作只对以下1个用户组开放:
用户
。
您可以查看并复制此页面的源代码:
===项目背景=== *数据安全,隐私难以保证 *“信息孤岛”现象严重 *中心化数据库价格高昂 ===项目思路=== 1.写入区块的信息 *患者公钥 *患者信息(不可识别) *就诊时间 *诊疗结果 *医院签名 *患者签名 2.实现功能 *新建节点(医疗机构、患者) *写入信息(医疗机构) *查询信息(患者) *查询信息(医疗机构) ===ChainCode实现接口=== 增 *insertPatient 改 *updatePatientState 查 *queryPatientByKey *queryRecordByDisease *queryPatientHistory *queryPatientByRange ===ChainCode代码=== {{{{ package main import ( "fmt" "strings" "encoding/json" "bytes" "time" "strconv" "github.com/hyperledger/fabric/core/chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer" ) type SimpleChaincode struct { } type record struct { ObjectType string `json:"docType"` RecordKey string `json:"rkey"` PatientKey string `json:"pkey"` PatientSex string `json:"psex"` PatientAge int `json:"page"` DateInfo time.Time `json:"date"` PatientDisease string `json:"info"` } type jsontime time.Time const timeFormat = "2006-01-02 15:04:05" func main() { err := shim.Start(new(SimpleChaincode)) if err != nil { fmt.Printf("Error starting Simple chaincode: %s", err) } } func (recordTime jsontime) MarshalJSON() ([]byte, error) { var stamp = fmt.Sprintf("\"%s\"", time.Time(recordTime).Format(timeFormat)) return []byte(stamp), nil } func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { return shim.Success(nil) } func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { function, args := stub.GetFunctionAndParameters() fmt.Println("Invoke is running " + function) if function == "insertRecord" { return t.insertPatient(stub, args) } else if function == "queryPatientByKey" { return t.queryPatientByKey(stub, args) } else if function == "queryPatientByAge" { return t.queryRecordByAge(stub, args) } else if function == "queryRecordByKey" { return t.queryRecordByKey(stub, args) } else if function == "queryRecordByDisease" { return t.queryRecordByDisease(stub, args) } else if function == "queryRecordBySex" { return t.queryRecordBySex(stub, args) } else if function == "queryPatientHistory" { return t.queryPatientHistory(stub, args) } else if function == "updatePatientState" { return t.updatePatientState(stub, args) } else if function == "queryPatientByRange" { return t.queryPatientByRange(stub, args) } fmt.Println("Invoke did not find func: " + function) //not supported func return shim.Error("Received unknown function invocation") } func (t *SimpleChaincode) insertPatient(stub shim.ChaincodeStubInterface, args []string) pb.Response { var err error // 0 1 2 3 4 5 // "0123","0000","male","35","2006-01-02 15:04:05","Headache" if len(args) != 6 { return shim.Error("Insert: incorrect number of arguments. Expecting 4") } // === Insert Running === fmt.Println("Insert- start insert patient") for i := 0; i < 6; i++ { if len(args[i]) <= 0 { return shim.Error("Insert: " + strconv.Itoa(i) + "th argument must be a non-empty string/integer/time") } } recordKey := args[0] patientKey := args[1] patientSex := strings.ToLower(args[2]) patientAge, err := strconv.Atoi(args[3]) if err != nil { return shim.Error("Insert: 3rd argument must be a numeric integer") } dateInfo, err := time.Parse(timeFormat, args[4]) if err != nil { return shim.Error("Insert: 4rd argument must be in time format") } patientDisease := strings.ToLower(args[5]) // === Check if patient exists === patientAsBytes, err := stub.GetState(patientKey) if err != nil { return shim.Error("Insert: failed to get patient. " + err.Error()) } else if patientAsBytes != nil { fmt.Println("Insert: This patient already exists--" + patientKey) return shim.Error("Insert: This patient already exists--" + patientKey) } // === Create record object and marshal to JSON === objectType := "record" record := &record{objectType, recordKey, patientKey, patientSex, patientAge, dateInfo, patientDisease} recordJSONasBytes, err := json.Marshal(record) if err != nil { return shim.Error("Insert: " + err.Error()) } // === Save record to state === err = stub.PutState(patientKey, recordJSONasBytes) if err != nil { return shim.Error("Insert: " + err.Error()) } // ==== Index the patient to enable age-based range queries, e.g. return all 35-year-old patients ==== // An 'index' is a normal key/value entry in state. // The key is a composite key, with the elements that you want to range query on listed first. // In our case, the composite key is based on indexName~patientAge~patientKey. // This will enable very efficient state range queries based on composite keys matching indexName~color~* indexName := "disease~pkey" diseaseKeyIndexKey, err := stub.CreateCompositeKey(indexName, []string{record.PatientDisease, record.PatientKey}) if err != nil { return shim.Error(err.Error()) } // Save index entry to state. Only the key name is needed, no need to store a duplicate copy of the marble. // Note - passing a 'nil' value will effectively delete the key from state, therefore we pass null character as value value := []byte{0x00} stub.PutState(diseaseKeyIndexKey, value) // === Record saved and indexed. Return success ==== fmt.Println("- end init patient") return shim.Success(nil) } func (t *SimpleChaincode) queryPatientByKey(stub shim.ChaincodeStubInterface, args []string) pb.Response { var patientKey, jsonResp string var err error if len(args) != 1 { return shim.Error("Query: Incorrect number of arguments. Expecting key of the patient to query") } patientKey = args[0] valAsbytes, err := stub.GetState(patientKey) if err != nil { jsonResp = "{\"Error\":\"Failed to get state for " + patientKey + "\"}" return shim.Error(jsonResp) } else if valAsbytes == nil { jsonResp = "{\"Error\":\"Patient does not exist: " + patientKey + "\"}" return shim.Error(jsonResp) } return shim.Success(valAsbytes) } func (t *SimpleChaincode) queryRecordByKey(stub shim.ChaincodeStubInterface, args []string) pb.Response { // 0 // "0123" if len(args) != 1 { return shim.Error("Query: incorrect number of arguments. Expecting 1") } recordKey := args[0] queryString := fmt.Sprintf("{\"selector\":{\"doctype\":\"record\",\"rkey\":\"%s\"}}", recordKey) var err error queryResults, err := getQueryResultForQueryString(stub, queryString) if err != nil { return shim.Error(err.Error()) } return shim.Success(queryResults) } func (t *SimpleChaincode) queryRecordByAge(stub shim.ChaincodeStubInterface, args []string) pb.Response { // 0 // "35" if len(args) != 1 { return shim.Error("Query: incorrect number of arguments. Expecting 1") } var err error patientAge, err := strconv.Atoi(args[0]) if err != nil { return shim.Error("Query: 1th argument must be a numeric integer") } queryString := fmt.Sprintf("{\"selector\":{\"doctype\":\"record\",\"page\":%s}}", strconv.Itoa(patientAge)) queryResults, err := getQueryResultForQueryString(stub, queryString) if err != nil { return shim.Error(err.Error()) } return shim.Success(queryResults) } func (t *SimpleChaincode) queryRecordByDisease(stub shim.ChaincodeStubInterface, args []string) pb.Response { // 0 // "headache" if len(args) != 1 { return shim.Error("Query: incorrect number of arguments. Expecting 1") } var err error patientDisease := strings.ToLower(args[0]) diseasePatientResultsIterator, err := stub.GetStateByPartialCompositeKey("disease~pkey", []string{patientDisease}) if err != nil { return shim.Error(err.Error()) } defer diseasePatientResultsIterator.Close() // Iterate through result set and for each patient found var buffer bytes.Buffer var jsonResp string buffer.WriteString("[") for diseasePatientResultsIterator.HasNext() { // Note that we don't get the value (2nd return variable), we'll just get the patient key from the composite key responseRange, err := diseasePatientResultsIterator.Next() if err != nil { return shim.Error(err.Error()) } // Get the disease and patient key from disease~pkey composite key objectType, compositeKeyParts, err := stub.SplitCompositeKey(responseRange.Key) if err != nil { return shim.Error(err.Error()) } returnedDisease := compositeKeyParts[0] returnedPatientKey := compositeKeyParts[1] fmt.Printf("- found a patient from index:%s disease:%s patinet key:%s\n", objectType, returnedDisease, returnedPatientKey) valAsbytes, err := stub.GetState(returnedPatientKey) if err != nil { jsonResp = "{\"Error\":\"Failed to get state for " + returnedPatientKey + "\"}" return shim.Error(jsonResp) } else if valAsbytes == nil { jsonResp = "{\"Error\":\"Patient does not exist: " + returnedPatientKey + "\"}" return shim.Error(jsonResp) } buffer.Write(valAsbytes) buffer.WriteByte('\n') } fmt.Printf("- found patients info as follows:%s\n", buffer.String()) return shim.Success(buffer.Bytes()) } func (t *SimpleChaincode) queryRecordBySex(stub shim.ChaincodeStubInterface, args []string) pb.Response { // 0 // "male" if len(args) != 1 { return shim.Error("Query: incorrect number of arguments. Expecting 1") } var err error patientSex := strings.ToLower(args[0]) queryString := fmt.Sprintf("{\"selector\":{\"doctype\":\"record\",\"psex\":\"%s\"}}", patientSex) queryResults, err := getQueryResultForQueryString(stub, queryString) if err != nil { return shim.Error(err.Error()) } return shim.Success(queryResults) } func (t *SimpleChaincode) queryPatientHistory(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) < 1 { return shim.Error("Query: Incorrect number of arguments. Expecting 1") } patientKey := args[0] fmt.Printf("Query- start query patient's history: %s\n", patientKey) resultsIterator, err := stub.GetHistoryForKey(patientKey) 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("- query patient's history returning:\n%s\n", buffer.String()) return shim.Success(buffer.Bytes()) } func (t *SimpleChaincode) queryPatientByRange(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) < 2 { return shim.Error("RangeQuery: Incorrect number of arguments. Expecting 2") } startKey := args[0] endKey := args[1] resultsIterator, err := stub.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("- queryPatientByRange queryResult:\n%s\n", buffer.String()) return shim.Success(buffer.Bytes()) } 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 is a JSON array containing QueryRecords 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("]") fmt.Printf("- getQueryResultForQueryString queryResult:\n%s\n", buffer.String()) return buffer.Bytes(), nil } func (t *SimpleChaincode) updatePatientState(stub shim.ChaincodeStubInterface, args []string) pb.Response { // 0 1 2 3 4 // '"0124","0000","35","2006-01-02 15:04:05","legbroke" if len(args) < 4 { return shim.Error("Update: incorrect number of arguments. Expecting 4") } var err error recordKey := args[0] patientKey := args[1] newAge, err := strconv.Atoi(args[2]) if err != nil { return shim.Error("Update: 3rd argument must be a numeric integer") } newDate, err := time.Parse(timeFormat, args[3]) if err != nil { return shim.Error("Update: 4rd argument must be in time format") } newDisease := strings.ToLower(args[4]) fmt.Println("Update- start update patient state ", patientKey, ":", recordKey, newAge, newDate, newDisease) patientAsBytes, err := stub.GetState(patientKey) if err != nil { return shim.Error("Update: failed to get patient. " + err.Error()) } else if patientAsBytes == nil { fmt.Println("Update: This patient does not exist--" + patientKey) return shim.Error("Update: This patient does not exist--" + patientKey) } patientToTransfer := record{} err = json.Unmarshal(patientAsBytes, &patientToTransfer) if err != nil { return shim.Error(err.Error()) } // Maintain the index indexName := "disease~pkey" diseaseKeyIndexKey, err := stub.CreateCompositeKey(indexName, []string{patientToTransfer.PatientDisease, patientToTransfer.PatientKey}) if err != nil { return shim.Error(err.Error()) } // Delete index entry to state err = stub.DelState(diseaseKeyIndexKey) if err != nil { return shim.Error("Update: Failed to maintain index :" + err.Error()) } return shim.Success(nil) patientToTransfer.PatientAge = newAge patientToTransfer.DateInfo = newDate patientToTransfer.PatientDisease = newDisease //change info // Create new index entry to state newDiseaseKeyIndexKey, err := stub.CreateCompositeKey(indexName, []string{patientToTransfer.PatientDisease, patientToTransfer.PatientKey}) if err != nil { return shim.Error(err.Error()) } // Save index entry to state. Only the key name is needed, no need to store a duplicate copy of the marble. // Note - passing a 'nil' value will effectively delete the key from state, therefore we pass null character as value value := []byte{0x00} stub.PutState(newDiseaseKeyIndexKey, value) patientJSONasBytes, _ := json.Marshal(patientToTransfer) err = stub.PutState(patientKey, patientJSONasBytes) //rewrite the patient if err != nil { return shim.Error(err.Error()) } fmt.Println("- end update patient state (success)") return shim.Success(nil) } }}}}
返回
诊疗信息的分布式记录系统
。
导航菜单
个人工具
创建账户
登录
名字空间
页面
讨论
变种
查看
阅读
查看源代码
查看历史
操作
搜索
导航
首页
实践教学
个性化3D设计与实现
人工智能实践教学
区块链技术及应用
虚拟现实技术与内容制作
超越学科界限的认知基础课程
电子工艺实习
Nand2Tetris Engine Curriculum
TULLL Creative Learning Group
Wiki上手说明
Wiki账户创建
最近更改
工具
链入页面
相关更改
特殊页面
页面信息