本项目基于区块链溯源技术,构建了数据溯源系统。
以下为相关算法和代码。
智能合约代码
溯源信息的存储
func (f *FactContract) save() protogo.Response {
params := sdk.Instance.GetArgs()
organizationStr := string(params["organization"])
addressStr := string(params["address"])
activityStr := string(params["activity"])
activityStart := string(params["activity_start"])
activityEnd := string(params["activity_end"])
activityaddr := string(params["activity_addr"])
fileid := string(params["file_id"])
fileHash := string(params["file_hash"])
fileName := string(params["file_name"])
fileUrl := string(params["file_url"])
timeStr := string(params["Established_time"])
uac := string(params["u_a_c"])
filekeyword := string(params["file_keyword"])
if fileHash == "" || fileName == "" || timeStr == "" || addressStr == "" || organizationStr == "" || activityStr == "" || activityStart == "" || activityStart == "" || activityEnd == "" || activityaddr == "" || fileid == "" || fileUrl == "" || filekeyword == "" {
return sdk.Error("请完整填写必要的信息")
}
exists, _ := f.FactExists(fileHash)
if exists {
return sdk.Error("the fact already exists")
}
fact := NewFact(organizationStr, timeStr, addressStr, activityStr, activityStart, activityEnd, activityaddr, fileHash, fileName, fileid, fileUrl, uac, filekeyword)
factBytes, err := json.Marshal(fact)
if err != nil {
return sdk.Error(fmt.Sprintf("marshal fact failed, err: %s", err))
}
sdk.Instance.EmitEvent("topic_vx", []string{fact.FileHash, fact.FileName})
err = sdk.Instance.PutStateByte("fact_bytes", fact.FileHash, factBytes)
if err != nil {
return sdk.Error("fail to save fact bytes")
}
sdk.Instance.Infof("[save] fileHash=" + fact.FileHash)
sdk.Instance.Infof("[save] fileName=" + fact.FileName)
return sdk.Success([]byte(fact.FileName + fact.FileHash))
}
存储功能调用执行
溯源信息的更新
func (f *FactContract) UpdateByFileHash() protogo.Response {
params := sdk.Instance.GetArgs()
// 获取参数
fileHash := string(params["file_hash"])
exists, _ := f.FactExists(fileHash)
if !exists {
return sdk.Error("the fact is not exists")
}
result, err := sdk.Instance.GetStateByte("fact_bytes", fileHash)
if err != nil {
return sdk.Error("failed to call get_state")
}
// 反序列化
var fact Fact
if err = json.Unmarshal(result, &fact); err != nil {
return sdk.Error(fmt.Sprintf("unmarshal fact failed, err: %s", err))
}
// 修改结构体
if string(params["organization"]) != "" {
fact.Organization = string(params["organization"])
}
if string(params["Established_time"]) != "" {
fact.Address = string(params["Established_time"])
}
if string(params["activity"]) != "" {
fact.Activity = string(params["activity"])
}
if string(params["activity_start"]) != "" {
fact.ActivityStart = string(params["activity_start"])
}
if string(params["activity_end"]) != "" {
fact.ActivityEnd = string(params["activity_end"])
}
if string(params["address"]) != "" {
fact.ActivityAddr = string(params["address"])
}
if string(params["file_id"]) != "" {
fact.FileID = string(params["file_id"])
}
if string(params["file_name"]) != "" {
fact.FileName = string(params["file_name"])
}
if string(params["file_url"]) != "" {
fact.FileUrl = string(params["file_url"])
}
if string(params["Established_time"]) != "" {
fact.Time = string(params["Established_time"])
}
if string(params["u_a_c"]) != "" {
fact.UAC = string(params["u_a_c"])
}
if string(params["file_keyword"]) != "" {
fact.FileKeyword = string(params["file_keyword"])
}
// 序列化
factBytes, err := json.Marshal(fact)
if err != nil {
return sdk.Error(fmt.Sprintf("marshal fact failed, err: %s", err))
}
// 发送事件
sdk.Instance.EmitEvent("topic_vx", []string{fact.FileHash, fact.FileName})
更新方法调用执行
溯源信息的查询
全生命周期精确溯源
func (f *FactContract) findByFileHash() protogo.Response {
fileHash := string(sdk.Instance.GetArgs()["file_hash"])
var arr []Fact
for {
result, err := sdk.Instance.GetStateByte("fact_bytes", fileHash)
if err != nil {
return sdk.Error("failed to call get_state")
}
var fact Fact
if err = json.Unmarshal(result, &fact); err != nil {
return sdk.Error(fmt.Sprintf("unmarshal fact failed, err: %s", err))
}
sdk.Instance.Infof("[find_by_file_hash] fileHash=" + fact.FileHash)
sdk.Instance.Infof("[find_by_file_hash] fileName=" + fact.FileName)
sdk.Instance.Infof("[find_by_file_hash] file name:" + fact.UAC)
arr = append(arr, fact)
fileHash = fact.UAC
if fact.UAC == "" {
break
}
}
arrBytes, err := json.Marshal(arr)
if err != nil {
msg := "marshal data fail"
sdk.Instance.Infof(msg + err.Error())
return sdk.Error(msg)
}
精确查找方法调用执行
模糊溯源
type TrieNode struct {
Children map[rune]*TrieNode
Results []Item
}
func insert(node *TrieNode, key string, value Item) {
for _, char := range key {
child, exists := node.Children[char]
if !exists {
child = &TrieNode{Children: make(map[rune]*TrieNode)}
node.Children[char] = child
}
node = child
}
node.Results = append(node.Results, value)
}
func search(node *TrieNode, prefix string) []Item {
var results []Item
for _, char := range prefix {
child, exists := node.Children[char]
if !exists {
continue
}
results = append(results, child.Results...)
results = append(results, search(child, prefix)...)
}
return results
}
root := &TrieNode{Children: make(map[rune]*TrieNode)}
for _, item := range items {
keywords := strings.Split(item.FileKeyword, ";")
for _, keyword := range keywords {
insert(root, strings.ToLower(keyword), item)
}
}
for {
var inputs []string
fmt.Println("☆☆☆☆☆ 输入关键词进行搜索 ☆☆☆☆☆")
for i := 1; i <= 5; i++ {
fmt.Printf("输入第 %d 个关键词(回车直接搜索/输入'ESC' 退出): ", i)
var input string
fmt.Scanln(&input)
if strings.EqualFold(input, "ESC") {
fmt.Println("已退出。")
return
}
if input == "" {
break
}
inputs = append(inputs, input)
}
if len(inputs) == 0 {
fmt.Println("没有输入关键词,已退出。")
return
}
模糊溯源方法调用执行
溯源信息的删除
func (f *FactContract) deleteByFileHash() protogo.Response {
fileHash := string(sdk.Instance.GetArgs()["file_hash"])
err := sdk.Instance.DelStateFromKey(fileHash)
if err != nil {
msg := "failed to call Del_state"
return sdk.Error(msg)
}
return sdk.Success([]byte("aleady delete!"))
}
发表回复