4.7 commit

parent 46b87768
...@@ -4,8 +4,8 @@ import ( ...@@ -4,8 +4,8 @@ import (
"bytes" "bytes"
"crypto/x509" "crypto/x509"
"encoding/json" "encoding/json"
"math/big"
"reflect" "reflect"
"sync"
"time" "time"
//"encoding/json" //"encoding/json"
...@@ -19,35 +19,31 @@ import ( ...@@ -19,35 +19,31 @@ import (
type GXHCC struct { type GXHCC struct {
} }
type AuthGroup struct { type AuthGroup struct {
Users map[string]int64 `json:"users"` //用户组权限,默认使用用户组。我们使用形如:“User1”:timestamp. key 表示用户或者角色,value 表示有效时间。我们使用格林威治时间时间戳 Users map[string]int64 `json:"users"` //用户组权限,默认使用用户组。我们使用形如:“User1”:timestamp. key 表示用户或者角色,value 表示有效时间。我们使用格林威治时间时间戳
Roles map[string]int64 `json:"roles"` //角色组权限, Roles map[string]int64 `json:"roles"` //角色组权限,
} }
type Auth struct { type Auth struct {
Read AuthGroup `json:"read"` // 字段的读权限,“”,不存在权限, Read AuthGroup `json:"read"` // 字段的读权限,“”,不存在权限,
Write AuthGroup `json:"write"`//字段的写权限 Write AuthGroup `json:"write"` //字段的写权限
} }
type LeadgerAuth struct { type LeadgerAuth struct { // 账本数据除了读权限外
Read AuthGroup `json:"read"` // 字段的读权限,“”,不存在权限, Read AuthGroup `json:"read"` // 字段的读权限,“”,不存在权限,
// Write AuthGroup `json:"write"`//字段的写权限 如果是账本数据 Issue AuthGroup `json:"issue"` //账本数据的发行权限,
Issue AuthGroup `json:"issue"` //账本数据的发行权限 Extract AuthGroup `json:"extrate"` //账本数据的提取权限,
Extract AuthGroup `json:"extrate"`//账本数据的提取权限 Transfer AuthGroup `json:"transfer"` // 账本数据的转账权限,
Transfer AuthGroup `json:"transfer"` // 账本数据的转账权限,默认是只有账户的所属者
} }
type SchemaParameters struct { type SchemaParameters struct {
Value interface{} `json:"val"`//默认值 这里特别说明一下如果这里是backUp 字段,我们不进行更深一步的校验,包括格式 Value interface{} `json:"val"` //默认值 这里特别说明一下如果这里是backUp 字段,我们不进行更深一步的校验,包括格式
PAuth Auth `json:"auth"` PAuth Auth `json:"auth"`
FCheck *Checks `json:"fcheck"` FCheck *Checks `json:"fcheck"`
} }
type SchemaLeadgerParameters struct { type SchemaLeadgerParameters struct {
Value interface{} `json:"val"`//默认值 这里特别说明一下如果这里是backUp 字段,我们不进行更深一步的校验,包括格式 Value interface{} `json:"val"` //默认值 这里特别说明一下如果这里是backUp 字段,我们不进行更深一步的校验,包括格式
PAuth LeadgerAuth `json:"auth"` PAuth LeadgerAuth `json:"auth"`
FCheck *Checks `json:"fcheck"` FCheck *Checks `json:"fcheck"`
} }
...@@ -58,36 +54,33 @@ type Checks struct { ...@@ -58,36 +54,33 @@ type Checks struct {
Fieldlen int `json:"fieldlen"` //字段长度(如果字段类型是string,表示字段长度,如果是数值类型用0,1表示数据正负) Fieldlen int `json:"fieldlen"` //字段长度(如果字段类型是string,表示字段长度,如果是数值类型用0,1表示数据正负)
} }
type Schema struct { type Schema struct {
//Fields map[string]SchemaParameters `json:"fields"`
LeadgerFields map[string]SchemaLeadgerParameters `json:"leadger_fields"` //账本字段 LeadgerFields map[string]SchemaLeadgerParameters `json:"leadger_fields"` //账本字段
StorageFields map[string]SchemaParameters `json:"storage_fields"` //存证字段 StorageFields map[string]SchemaParameters `json:"storage_fields"` //存证字段
SchemaAuth Auth `json:"schema_auth"`//schema 的写权限,主要是用在 schema update 部分 SchemaAuth Auth `json:"schema_auth"` //schema 的写权限,主要是用在 schema update 部分
SAuth Auth `json:"auth"` SAuth Auth `json:"auth"` //数据总的读权限
} }
type Action struct { type Action struct {
AccountType string `json:"account_type"`//账户类型 AccountType string `json:"account_type"` //账户类型
AccountId string `json:"account_id"` //账户Id AccountId string `json:"account_id"` //账户Id
ActionAmount float64 `json:"action_amount"`//这次的动作金额 ActionAmount string `json:"action_amount"` //这次的动作金额
FundType string `json:"fund_type"` //资金类型 FundType string `json:"fund_type"` //资金类型
BackUp interface{} `json:"back_up"`//备注信息 BackUp interface{} `json:"back_up"` //备注信息
} }
type TransferAccount struct { type TransferAccount struct {
AccountType string `json:"account_type"`//账户类型 AccountType string `json:"account_type"` //账户类型
AccountId string `json:"account_id"` //账户Id AccountId string `json:"account_id"` //账户Id
FundType string `json:"fund_type"` //资金类型 FundType string `json:"fund_type"` //资金类型
} }
type Node struct { type Node struct {
Key string Key string
Value []byte Value *Schema
pre *Node pre *Node
next *Node next *Node
} }
type LRUCache struct { type LRUCache struct {
limit int limit int
HashMap map[string]*Node HashMap map[string]*Node
...@@ -95,28 +88,40 @@ type LRUCache struct { ...@@ -95,28 +88,40 @@ type LRUCache struct {
end *Node end *Node
} }
type Merchantsale struct { type Merchantsale struct {
Mid string `json:"mid"` //商户Id Mid string `json:"mid"` //商户Id
Bid string `json:"bid"` // 分支机构id,也是一笔交易的接受者 Bid string `json:"bid"` // 分支机构id,也是一笔交易的接受者
Tamount float64 `json:"tamount"` //交易金额 Tamount string `json:"tamount"` //交易金额
Treposit float64 `json:"treposit"` //扣除预付金 Treposit string `json:"treposit"` //扣除预付金
Bereposit float64 `json:"bereposit"` //扣除前预付金 Bereposit string `json:"bereposit"` //扣除前预付金
Afreposit float64 `json:"afreposit"` //扣除后预付金 Afreposit string `json:"afreposit"` //扣除后预付金
Feerate float64 `json:"feerate"` // 手续费扣率 Feerate float64 `json:"feerate"` // 手续费扣率
Fee float64 `json:"fee"` // 手续费 Free string `json:"free"` // 手续费
Oamount float64 `json:"oamount"` // 原始交易金额 Oamount string `json:"oamount"` // 原始交易金额
Adiscounts float64 `json:"adiscounts"` //代理结算折扣 Adiscounts float64 `json:"adiscounts"` //代理结算折扣
Sdiscounts float64 `json:"sdiscounts"` //消费折扣 Sdiscounts float64 `json:"sdiscounts"` //消费折扣
Nodisamount float64 `json:"nodisamount"` //不打折金额 Nodisamount string `json:"nodisamount"` //不打折金额
Disamount float64 `json:"disamount"` //打折金额 Disamount string `json:"disamount"` //打折金额
Perquisites float64 `json:"perquisites"` //额外收益 Perquisites string `json:"perquisites"` //额外收益
} }
type OrderTx struct {
Oamount string `json:"oamount"` // 原始交易金额
Pamount string `json:"pamount"` // 支付金额
Odesc *OrderDescribe `json:"odesc"` //订单描述
Mid string `json:"mid"` //商户Id
Norate float64 `json:"norate"` //无预付金收益率
Outfree string `json:"outfree"` //付款方手续费
Infree string `json:"infree"` //收款方手续费
Partnersfree string `json:"partnersfree"` //订单合作方手续费
Free string `json:"free"` // 手续费
Pid string `json:"pid"` //合作方Id
}
type Merchant struct { type OrderDescribe struct {
Id string `json:"id"` Codes []string `json:"codes"` //码
TicketType int `json:"ticket_type"` //券类型,折扣券只能使用一次
Tid string `json:"tid"` //券Id
} }
type CommonTx struct { type CommonTx struct {
...@@ -124,36 +129,37 @@ type CommonTx struct { ...@@ -124,36 +129,37 @@ type CommonTx struct {
SenderId string `json:"sender_id"` SenderId string `json:"sender_id"`
SenderFunt string `json:"sender_funt"` SenderFunt string `json:"sender_funt"`
ReceiverAccountType string `json:"receiver_account"` ReceiverAccountType string `json:"receiver_account"`
ReceiverId string `json:"receiver_account_id"` ReceiverId string `json:"receiver_id"`
ReceiverFunt string `json:"receiver_funt"` ReceiverFunt string `json:"receiver_funt"`
Amount float64 `json:"amount"` Amount string `json:"amount"`
} }
type transferTypes func(args []string, stub shim.ChaincodeStubInterface)error // 声明了一个函数类型 type transferTypes func(args []string, stub shim.ChaincodeStubInterface) error // 声明了一个函数类型
type putDataFilter func(putDatas []map[string]interface{}, name, tableName string, schema *Schema, stub shim.ChaincodeStubInterface) (string, error) // 声明了一个函数类型,这个函数类型主要是用于putdata 数据过滤使用
var ( var (
defValue = "***" //查询用户权限不足的情况下默认返回值 defValue = "***" //查询用户权限不足的情况下默认返回值
PREFIX = "GXH"
StoragePrefix = "SGXH" StoragePrefix = "SGXH"
LeadgerPrefix = "LGXH" LeadgerPrefix = "LGXH"
IsUsers = true //是否启用用户权限,false 表示启用Roles IsUsers = true //是否启用用户权限,false 表示启用Roles
GxhSchema = "gxhSchema" //schema 存储前缀,为了实现复合主键使用。 GxhSchema = "gxhSchema" //schema 存储前缀,为了实现复合主键使用。
InitSchemaLength = 12 //初始化时schema 的长度 InitSchemaLength = 12 //缓存的 schema 的长度
schemaCache = Constructor(InitSchemaLength) schemaCache = Constructor(InitSchemaLength)
once = sync.Once{} updateTime = int64(60 * 60 * 12) //schema 更新时间间隔,默认是12小时
lastTime = int64(0)
transferType = initTransfer() transferType = initTransfer()
PutDataFilter = initPutData()
) )
// Init does nothing for this cc // Init does nothing for this cc
func (t *GXHCC) Init(stub shim.ChaincodeStubInterface) pb.Response { func (t *GXHCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success([]byte("GXHCC init successful! ")) return shim.Success([]byte("gxhcc init successful! "))
} }
/* /*
初始化我们要使用的交易类型 初始化我们要使用的交易执行方法
*/ */
func initTransfer()map[string]transferTypes{ func initTransfer() map[string]transferTypes {
transferType := make(map[string]transferTypes) transferType := make(map[string]transferTypes)
transferType["merchants"] = merchantsale transferType["merchants"] = merchantsale
transferType["tickerorders"] = tickerorders transferType["tickerorders"] = tickerorders
...@@ -161,42 +167,67 @@ func initTransfer()map[string]transferTypes{ ...@@ -161,42 +167,67 @@ func initTransfer()map[string]transferTypes{
return transferType return transferType
} }
func initSchema(stub shim.ChaincodeStubInterface)error{ func initPutData() map[string]putDataFilter {
var errinfo error filter := make(map[string]putDataFilter)
once.Do(func(){ filter["couticketcodes"] = codeFilter
schemaIterator,err := stub.GetStateByPartialCompositeKey(GxhSchema,nil) filter["commonput"] = commanFilter
filter["coutcantm"] = ticketMerFilter
return filter
}
/*
处理缓存内容的方法,
*/
func initSchema(stub shim.ChaincodeStubInterface) error {
timeStamp, err := stub.GetTxTimestamp()
if err != nil { if err != nil {
errinfo = err return err
return } else if timeStamp.GetSeconds() < lastTime+updateTime {
return nil
}
var values map[string]*Schema
values = make(map[string]*Schema)
schemaIterator, err := stub.GetStateByPartialCompositeKey(GxhSchema, nil)
if err != nil {
return err
} }
defer schemaIterator.Close() defer schemaIterator.Close()
index := 1 index := 1
for schemaIterator.HasNext(){ for schemaIterator.HasNext() {
querykv,err := schemaIterator.Next() querykv, err := schemaIterator.Next()
if err != nil { if err != nil {
errinfo = err return err
return
} }
fmt.Println("add cache key:",querykv.Key) fmt.Println("add cache key:", querykv.Key)
_,compisiteKeys ,err := stub.SplitCompositeKey(querykv.Key) _, compisiteKeys, err := stub.SplitCompositeKey(querykv.Key)
if err!=nil{ if err != nil {
errinfo = err return err
return }
scema := &Schema{}
err = json.Unmarshal(querykv.Value, scema)
if err != nil {
fmt.Sprintf("json unmarshal %s schema fail,err: %s \n", querykv.Key, err)
} }
schemaCache.Put(compisiteKeys[0],querykv.Value) if schemaCache.Get(compisiteKeys[0]) != nil {
fmt.Println("add cache key:",querykv.Key) schemaCache.Put(compisiteKeys[0], scema)
fmt.Println("add cache key:", querykv.Key)
index++ index++
if index > InitSchemaLength { if index > InitSchemaLength {
fmt.Println("cache data length :",len(schemaCache.HashMap)) fmt.Println("cache data length :", len(schemaCache.HashMap))
return return nil
} }
} else {
values[compisiteKeys[0]] = scema
} }
fmt.Println("cache data length :",len(schemaCache.HashMap))
return
})
if errinfo != nil{
return errinfo
} }
for len(schemaCache.HashMap) < InitSchemaLength {
for k, v := range values {
schemaCache.Put(k, v)
}
}
fmt.Println("cache data length :", len(schemaCache.HashMap))
lastTime = timeStamp.GetSeconds() //设置最新修改时间
return nil return nil
} }
...@@ -204,70 +235,52 @@ func initSchema(stub shim.ChaincodeStubInterface)error{ ...@@ -204,70 +235,52 @@ func initSchema(stub shim.ChaincodeStubInterface)error{
func (t *GXHCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response { func (t *GXHCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
// get arguments and transient // get arguments and transient
functionName, args := stub.GetFunctionAndParameters() functionName, args := stub.GetFunctionAndParameters()
err := initSchema(stub) var err error
if err !=nil{ err = initSchema(stub)
if err != nil {
return shim.Error(err.Error()) return shim.Error(err.Error())
} }
var res string
switch functionName { switch functionName {
case "authority":
case "schema": case "schema":
res,err := SchemaProcess(args,stub) res, err = SchemaProcess(args, stub)
if err!=nil{ if err != nil {
return shim.Error(fmt.Sprintf("SchemaProcess function err: %s", err)) return shim.Error(fmt.Sprintf("schema process function err: %s", err))
}
case "put":
res, err = put(args, stub)
if err != nil {
return shim.Error(fmt.Sprintf("put function err: %s", err))
} }
return shim.Success([]byte(res)) case "update":
case "putData": res, err = updateStoreData(args, stub)
res,err := putData(args,stub) if err != nil {
if err!=nil{ return shim.Error(fmt.Sprintf("up store data function err: %s", err))
return shim.Error(fmt.Sprintf("putData function err: %s", err))
} }
return shim.Success([]byte(res))
case "get": case "get":
res,err := get(args,stub) res, err = get(args, stub)
if err!=nil{ if err != nil {
return shim.Error(fmt.Sprintf("get function err: %s", err)) return shim.Error(fmt.Sprintf("get function err: %s", err))
} }
return shim.Success([]byte(res))
case "upStoreData": //
res,err := updateStoreData(args,stub)
if err!=nil{
return shim.Error(fmt.Sprintf("upStoreData function err: %s", err))
}
return shim.Success([]byte(res))
case "createAccount":
res,err := createAccount(args,stub)
if err!=nil{
return shim.Error(fmt.Sprintf("createAccount function err: %s", err))
}
return shim.Success([]byte(res))
case "createTx": case "createTx":
res,err := transactionProcess(args,stub) res, err = transactionProcess(args, stub)
if err!=nil{ if err != nil {
return shim.Error(fmt.Sprintf("transactionProcess function err: %s", err)) return shim.Error(fmt.Sprintf("transaction process function err: %s", err))
} }
return shim.Success([]byte(res))
case "getCertCommonName": case "getCertCommonName":
name,err := getCertificateCommonName(stub) res, err = getCertificateCommonName(stub)
if err != nil{ if err != nil {
return shim.Error(fmt.Sprintf("get certificate CommonName fail,err: %s",err)) return shim.Error(fmt.Sprintf("get certificate common_name fail,err: %s", err))
} }
return shim.Success([]byte("current user certificate commonname :" +name)) res = "current user certificate common_name is:" + res
default: default:
return shim.Error(fmt.Sprintf("Unsupported function %s", functionName)) return shim.Error(fmt.Sprintf("Unsupported function %s", functionName))
} }
return shim.Success([]byte("GXHCC invoke successful ")) return shim.Success([]byte("gxhcc invoke successful:" + res))
} }
/*
根据账户类型创建账本账户,由于我们这里有存储数据与账本数据两种,所以我们还需要在schema 部分标识不同的数据类型。 func put(args []string, stub shim.ChaincodeStubInterface) (string, error) {
伪代码:
1:检查当前用户是否具有账户的总写(创建)权限
2:检查账户必备的属性,如Id,账户名,账户所属者,对应的是证书commonName
2:根据schema 标注的金额(账本)字段,和存证字段,分别进行数据的putState存储工作。其中在存证数据的Id 字段是标示字段。
3:完成账户创建工作
*/
func createAccount(args []string, stub shim.ChaincodeStubInterface) (string, error){
if len(args) < 2 { if len(args) < 2 {
return "", fmt.Errorf("put data operation expected more than 2 parameters! ") return "", fmt.Errorf("put data operation expected more than 2 parameters! ")
} }
...@@ -277,16 +290,32 @@ func createAccount(args []string, stub shim.ChaincodeStubInterface) (string, err ...@@ -277,16 +290,32 @@ func createAccount(args []string, stub shim.ChaincodeStubInterface) (string, err
return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err) return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
} }
schema := &Schema{} schema := &Schema{}
err = schema.get(args[0], stub) err, schema = schema.get(args[0], stub)
if err != nil { if err != nil {
return "", err return "", err
} }
if ok,err := authorityCheck(schema.SAuth.Write, commonName);!ok { if ok, err := authorityCheck(schema.SAuth.Write, commonName, ""); !ok {
return "", fmt.Errorf("write %s table fail,err: %s ", args[0],err) return "", fmt.Errorf("write %s table fail,err: %s ", args[0], err)
} }
if err := json.Unmarshal([]byte(args[1]), &PutDatas); err != nil { if err := json.Unmarshal([]byte(args[1]), &PutDatas); err != nil {
return "", fmt.Errorf("%s table parameters Unmarshal fail,put string not json array, err:%s",args[0], err) return "", fmt.Errorf("%s table parameters Unmarshal fail,put string not json array, err:%s", args[0], err)
}
if len(schema.LeadgerFields) != 0 {
return createAccount(args[0],PutDatas,schema,stub)
}else{
return putData(args[0], PutDatas, commonName, schema, stub)
} }
}
/*
根据账户类型创建账本账户,由于我们这里有存储数据与账本数据两种,所以我们还需要在schema 部分标识不同的数据类型。
伪代码:
1:检查当前用户是否具有账户的总写(创建)权限
2:检查账户必备的属性,如Id,账户名,账户所属者,对应的是证书commonName
2:根据schema 标注的金额(账本)字段,和存证字段,分别进行数据的putState存储工作。其中在存证数据的Id 字段是标示字段。
3:完成账户创建工作
*/
func createAccount(tablename string,PutDatas []map[string]interface{},schema *Schema, stub shim.ChaincodeStubInterface) (string, error) {
for k, mapres := range PutDatas { for k, mapres := range PutDatas {
Id, ok := mapres["id"] Id, ok := mapres["id"]
if !ok { if !ok {
...@@ -296,34 +325,66 @@ func createAccount(args []string, stub shim.ChaincodeStubInterface) (string, err ...@@ -296,34 +325,66 @@ func createAccount(args []string, stub shim.ChaincodeStubInterface) (string, err
if !ok { if !ok {
return "", fmt.Errorf("The common_name field must exist ") return "", fmt.Errorf("The common_name field must exist ")
} }
err = SchemaCheck(schema, mapres) err := SchemaCheck(schema, mapres)
if err != nil { if err != nil {
return "", fmt.Errorf("args index %d string, %s schema cheack fail,err : %s ", k, args[0],err) return "", fmt.Errorf("args index %d string, %s schema cheack fail,err : %s ", k, tablename, err)
} }
if err := FiledsCheck(schema,mapres);err !=nil{ if err := FiledsCheck(schema, mapres); err != nil {
return "",err return "", err
} }
storagemap,leadgermap := separateFields(schema,mapres,[]string{"id","common_name"}) storagemap, leadgermap := separateFields(schema, mapres, []string{"id", "common_name"})
storageDate, _ := json.Marshal(storagemap) storageDate, _ := json.Marshal(storagemap)
leadgerDate, _ := json.Marshal(leadgermap) leadgerDate, _ := json.Marshal(leadgermap)
key := StoragePrefix+"_"+args[0]+"_"+Id.(string) key := StoragePrefix + "_" + tablename + "_" + Id.(string)
getResult,err := stub.GetState(key) getResult, err := stub.GetState(key)
if err != nil { if err != nil {
return "", fmt.Errorf("GetState %s data fail,please check your parameters ",key) return "", fmt.Errorf("GetState %s data fail,please check your parameters ", key)
} }
if getResult != nil{ if getResult != nil {
return "", fmt.Errorf("%s data already exists and cannot be added",key) return "", fmt.Errorf("%s data already exists and cannot be added", key)
} }
if err := stub.PutState(key, storageDate); err != nil { if err := stub.PutState(key, storageDate); err != nil {
return "", fmt.Errorf("PutState fail, err :%s", err) return "", fmt.Errorf("PutState fail, err :%s", err)
} }
if err := stub.PutState(LeadgerPrefix+"_"+args[0]+"_"+Id.(string), leadgerDate); err != nil { if err := stub.PutState(LeadgerPrefix+"_"+tablename+"_"+Id.(string), leadgerDate); err != nil {
return "", fmt.Errorf("PutState fail, err :%s", err) return "", fmt.Errorf("PutState fail, err :%s", err)
} }
} }
return fmt.Sprintf("create %s account success!", args[0]), nil return fmt.Sprintf("create %s account success!", tablename), nil
} }
///*
// 存储数据,某些不产生账本数据的数据使用这个接口来存储。例如码数据,进件表数据
//
//*/
//func putData(args []string, stub shim.ChaincodeStubInterface) (string, error) {
// if len(args) < 2 {
// return "", fmt.Errorf("put data operation expected more than 2 parameters! ")
// }
// var PutDatas []map[string]interface{}
// commonName, err := getCertificateCommonName(stub)
// if err != nil {
// return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
// }
// schema := &Schema{}
// err, schema = schema.get(args[0], stub)
// if err != nil {
// return "", err
// }
// if ok, err := authorityCheck(schema.SAuth.Write, commonName, ""); !ok {
// return "", fmt.Errorf("write %s table fail,err: %s ", args[0], err)
// }
// if err := json.Unmarshal([]byte(args[1]), &PutDatas); err != nil {
// return "", fmt.Errorf("%s table parameters Unmarshal fail,put string not json array, err:%s", args[0], err)
// }
// //存储过滤器
// _, err = filterByput(args[0], PutDatas, commonName, schema, stub)
// if err != nil {
// return "", err
// }
//
// return fmt.Sprintf("%s put data success!", args[0]), nil
//}
/* /*
修改一个账户的存储数据,修改规则由Schema 控制,有些特殊数据在账本数据也使用,所以无法修改 修改一个账户的存储数据,修改规则由Schema 控制,有些特殊数据在账本数据也使用,所以无法修改
...@@ -337,13 +398,13 @@ func updateStoreData(args []string, stub shim.ChaincodeStubInterface) (string, e ...@@ -337,13 +398,13 @@ func updateStoreData(args []string, stub shim.ChaincodeStubInterface) (string, e
return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err) return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
} }
schema := &Schema{} schema := &Schema{}
err = schema.get(args[0], stub) err, schema = schema.get(args[0], stub)
if err != nil { if err != nil {
return "", err return "", err
} }
var Updata map[string]interface{} var Updata map[string]interface{}
if err := json.Unmarshal([]byte(args[1]), &Updata); err != nil { if err := json.Unmarshal([]byte(args[1]), &Updata); err != nil {
return "", fmt.Errorf("%s table parameters Unmarshal fail,err: %s",args[0], err) return "", fmt.Errorf("%s table parameters Unmarshal fail,err: %s", args[0], err)
} }
Id, ok := Updata["id"] Id, ok := Updata["id"]
if !ok { if !ok {
...@@ -353,16 +414,16 @@ func updateStoreData(args []string, stub shim.ChaincodeStubInterface) (string, e ...@@ -353,16 +414,16 @@ func updateStoreData(args []string, stub shim.ChaincodeStubInterface) (string, e
if ok { if ok {
return "", fmt.Errorf("The common_name field cannot update ") return "", fmt.Errorf("The common_name field cannot update ")
} }
if ok ,_ := authorityCheck(schema.SAuth.Write, commonName);!ok { if ok, _ := authorityCheck(schema.SAuth.Write, commonName, ""); !ok {
if ok, err := parsauthorityCheck(schema.StorageFields, Updata, commonName); !ok { if ok, err := parsauthorityCheck(schema.StorageFields, Updata, commonName); !ok {
return "", fmt.Errorf("authority Check err: %s", err) return "", fmt.Errorf("authority Check err: %s", err)
} }
} }
if err := FiledsCheck(schema,Updata);err !=nil{ if err := FiledsCheck(schema, Updata); err != nil {
return "",err return "", err
} }
key := StoragePrefix+"_"+args[0]+"_"+Id.(string) key := StoragePrefix + "_" + args[0] + "_" + Id.(string)
allMap,err := getState(key,stub) allMap, err := getState(key, stub)
if err != nil { if err != nil {
return "", err return "", err
} }
...@@ -370,61 +431,13 @@ func updateStoreData(args []string, stub shim.ChaincodeStubInterface) (string, e ...@@ -370,61 +431,13 @@ func updateStoreData(args []string, stub shim.ChaincodeStubInterface) (string, e
if err := Deassign(Updata, allMap); err != nil { if err := Deassign(Updata, allMap); err != nil {
return "", err return "", err
} }
err = putState(key,allMap,stub) err = putState(key, allMap, stub)
if err != nil { if err != nil {
return "", err return "", err
} }
return fmt.Sprintf("%s update data success!", args[0]), nil return fmt.Sprintf("%s update data success!", args[0]), nil
} }
/*
存储数据,某些不产生账本数据的数据使用这个接口来存储。例如码数据,进件表数据
允许覆盖
*/
func putData(args []string, stub shim.ChaincodeStubInterface) (string, error) {
if len(args) < 2 {
return "", fmt.Errorf("put data operation expected more than 2 parameters! ")
}
var PutDatas []map[string]interface{}
commonName, err := getCertificateCommonName(stub)
if err != nil {
return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
}
schema := &Schema{}
err = schema.get(args[0], stub)
if err != nil {
return "", err
}
if ok,err := authorityCheck(schema.SAuth.Write, commonName);!ok {
return "", fmt.Errorf("write %s table fail,err: %s ", args[0],err)
}
if err := json.Unmarshal([]byte(args[1]), &PutDatas); err != nil {
return "", fmt.Errorf("%s table parameters Unmarshal fail,put string not json array, err:%s",args[0], err)
}
for k, mapres := range PutDatas {
Id, ok := mapres["id"]
if !ok {
return "", fmt.Errorf("The id field must exist ")
}
if len(schema.LeadgerFields)!= 0{
return "", fmt.Errorf("%s schema exist leadger fields,cannot putData", args[0])
}
err = SchemaCheck(schema, mapres)
if err != nil {
return "", fmt.Errorf("args index %d string, %s schema cheack fail,err : %s ", k, args[0],err)
}
if err := FiledsCheck(schema,mapres);err !=nil{
return "",err
}
key := StoragePrefix+"_"+args[0]+"_"+Id.(string)
err = putState(key,mapres,stub)
if err != nil {
return "", err
}
}
return fmt.Sprintf("%s put data success!", args[0]), nil
}
/* /*
查询数据,如果存在账本数据,与存证数据,则进行数据拼接,然后返回。 查询数据,如果存在账本数据,与存证数据,则进行数据拼接,然后返回。
*/ */
...@@ -446,18 +459,18 @@ func get(args []string, stub shim.ChaincodeStubInterface) (string, error) { ...@@ -446,18 +459,18 @@ func get(args []string, stub shim.ChaincodeStubInterface) (string, error) {
if !ok { if !ok {
return "", fmt.Errorf("The id field must exist ") return "", fmt.Errorf("The id field must exist ")
} }
storageKey := StoragePrefix+"_"+args[0]+"_"+Id.(string) storageKey := StoragePrefix + "_" + args[0] + "_" + Id.(string)
mapResult, err := getState(storageKey,stub) mapResult, err := getState(storageKey, stub)
if err != nil { if err != nil {
return "", err return "", err
} }
leadgerKey := LeadgerPrefix+"_"+args[0]+"_"+Id.(string) leadgerKey := LeadgerPrefix + "_" + args[0] + "_" + Id.(string)
leadgerResult, err := stub.GetState(leadgerKey) leadgerResult, err := stub.GetState(leadgerKey)
if err != nil { if err != nil {
return "", fmt.Errorf("get %s data fail,please check your parameters ",leadgerKey) return "", fmt.Errorf("get %s data fail,please check your parameters ", leadgerKey)
} }
schema := &Schema{} schema := &Schema{}
err = schema.get(args[0], stub) err, schema = schema.get(args[0], stub)
if err != nil { if err != nil {
return "", err return "", err
} }
...@@ -466,8 +479,12 @@ func get(args []string, stub shim.ChaincodeStubInterface) (string, error) { ...@@ -466,8 +479,12 @@ func get(args []string, stub shim.ChaincodeStubInterface) (string, error) {
return "", fmt.Errorf("The leadger original data Unmarshal fail err:%s ", err) return "", fmt.Errorf("The leadger original data Unmarshal fail err:%s ", err)
} }
} }
if ok,_:= authorityCheck(schema.SAuth.Read, commonName);!ok { onwer, ok := mapResult["common_name"].(string)
if filteredData, err := dataFilter(schema, mapResult, commonName); err != nil { if !ok {
return "", fmt.Errorf("common_name fields resolution failed ")
}
if ok, _ := authorityCheck(schema.SAuth.Read, commonName, ""); !ok {
if filteredData, err := dataFilter(schema, mapResult, commonName, onwer); err != nil {
return "", fmt.Errorf("get data authority filter fail, err: %s", err) return "", fmt.Errorf("get data authority filter fail, err: %s", err)
} else { } else {
result, _ := json.Marshal(filteredData) result, _ := json.Marshal(filteredData)
...@@ -480,127 +497,6 @@ func get(args []string, stub shim.ChaincodeStubInterface) (string, error) { ...@@ -480,127 +497,6 @@ func get(args []string, stub shim.ChaincodeStubInterface) (string, error) {
} }
} }
func SchemaCheck(schema *Schema, checkmap map[string]interface{}) error {
if len(schema.StorageFields)+len(schema.LeadgerFields) != len(checkmap) {
return fmt.Errorf("The input field length is less than the schema field length ! ")
}
for k, v := range schema.StorageFields {
if schemaV, ok := checkmap[k]; !ok {
return fmt.Errorf("There is no input storage field %s ",k)
} else {
if parameterS, ok := v.Value.(map[string]interface{}); ok {
if parameterC, ok := schemaV.(map[string]interface{}); !ok {
return fmt.Errorf("The input field %s does not match the output field format ",k)
}else{
err := BackUpCheck(parameterS,parameterC)
if err != nil{
return err
}
}
}
}
}
for k, _ := range schema.LeadgerFields {
if _, ok := checkmap[k]; !ok {
return fmt.Errorf("There is no input leadger field %s ",k)
}
}
return nil
}
func FiledsCheck(schema *Schema, checkmap map[string]interface{}) error{
for k, schemaV := range schema.StorageFields {
if k != "backup" && schemaV.FCheck!= nil && schemaV.FCheck.FType != "" && checkmap[k] != nil{
if err := fieldCheckout(schemaV.FCheck,checkmap[k]);err!=nil{
return fmt.Errorf("%s %s ",k,err)
}
}
}
for k, schemaV := range schema.LeadgerFields {
if schemaV.FCheck!= nil && schemaV.FCheck.FType != "" && checkmap[k] != nil{
if err := fieldCheckout(schemaV.FCheck,checkmap[k]);err!=nil{
return fmt.Errorf("%s %s ",k,err)
}
}
}
return nil
}
func BackUpCheck(backUp map[string]interface{}, checkmap map[string]interface{}) error {
if len(backUp) != len(checkmap) {
return fmt.Errorf("The input backup field length is less than the schema backup field length ! ")
}
for k, _ := range checkmap {
if _, ok := backUp[k]; !ok {
return fmt.Errorf("There is no input backup field %s ",k)
}
}
return nil
}
/*
将字段根据账本数据,与存储数据分开
leadgers:参数表示我们需要在账本数据包含的字段,这些字段不属于账本数据。
*/
func separateFields(schema *Schema,checkmap map[string]interface{},leadgers []string)(storagemap ,leadgermap map[string]interface{}){
storagemap = make(map[string]interface{})
leadgermap = make(map[string]interface{})
for k,_ :=range schema.LeadgerFields{
leadgermap[k] = checkmap[k]
}
for _,v :=range leadgers{
leadgermap[v] = checkmap[v]
}
for k,_ :=range schema.StorageFields{
storagemap[k] = checkmap[k]
}
return
}
/*
根据权限拼装数据,进行数据过滤
*/
func dataFilter(schema *Schema, checkmap map[string]interface{}, commonName string) (map[string]interface{}, error) {
for k, schemaV := range schema.StorageFields {
if v, ok := checkmap[k]; !ok {
return nil, fmt.Errorf("Update data parameter mismatch with schema structure! ")
} else {
if _, ok := schemaV.Value.(map[string]SchemaParameters); ok {
if _, ok := v.(map[string]interface{}); !ok {
return nil, fmt.Errorf("Update data parameter mismatch with schema structure! ")
}
if ok,_ := authorityCheck(schemaV.PAuth.Read, commonName);!ok {
checkmap[k] = defValue
}
} else {
if ok,_ := authorityCheck(schemaV.PAuth.Read, commonName);!ok {
checkmap[k] = defValue
}
}
}
}
for k, schemaV := range schema.LeadgerFields {
if v, ok := checkmap[k]; !ok {
return nil, fmt.Errorf("Update data parameter mismatch with schema structure! ")
} else {
if _, ok := schemaV.Value.(map[string]SchemaLeadgerParameters); ok {
if _, ok := v.(map[string]interface{}); !ok {
return nil, fmt.Errorf("Update data parameter mismatch with schema structure! ")
}
if ok,_ := authorityCheck(schemaV.PAuth.Read, commonName);!ok {
checkmap[k] = defValue
}
} else {
if ok,_ := authorityCheck(schemaV.PAuth.Read, commonName);!ok {
checkmap[k] = defValue
}
}
}
}
return checkmap, nil
}
func SchemaProcess(args []string, stub shim.ChaincodeStubInterface) (string, error) { func SchemaProcess(args []string, stub shim.ChaincodeStubInterface) (string, error) {
if len(args) < 2 { if len(args) < 2 {
return "", fmt.Errorf("Expect features with 2 or more parameters to play! ") return "", fmt.Errorf("Expect features with 2 or more parameters to play! ")
...@@ -628,17 +524,18 @@ func transactionProcess(args []string, stub shim.ChaincodeStubInterface) (string ...@@ -628,17 +524,18 @@ func transactionProcess(args []string, stub shim.ChaincodeStubInterface) (string
switch args[0] { switch args[0] {
case "issue": //进行账户金额发行(无中生有) case "issue": //进行账户金额发行(无中生有)
return funtOperation(args[1:],stub,true) return funtOperation(args[1:], stub, true)
case "extract": //提取账户金额(直接减去) case "extract": //提取账户金额(直接减去)
return funtOperation(args[1:],stub,false) return funtOperation(args[1:], stub, false)
case "transfer": // 一笔普通转账 case "transfer": // 一笔普通转账
return transferTx(args[1:],stub) return transferTx(args[1:], stub)
default: default:
return "", fmt.Errorf(fmt.Sprintf("Unsupported schema function of %s", args[0])) return "", fmt.Errorf(fmt.Sprintf("Unsupported schema function of %s", args[0]))
} }
return "", nil return "", nil
} }
/* /*
put put
args 字段说明: args 字段说明:
...@@ -655,11 +552,11 @@ func (this *Schema) put(args []string, stub shim.ChaincodeStubInterface) (string ...@@ -655,11 +552,11 @@ func (this *Schema) put(args []string, stub shim.ChaincodeStubInterface) (string
} }
var schema *Schema var schema *Schema
var err error var err error
if schema ,err = NewSchema(args[1]);err != nil{ if schema, err = NewSchema(args[1]); err != nil {
return "", fmt.Errorf("The parameters Unmarshal to a Schema structural fail,err: %s ", err) return "", fmt.Errorf("The parameters Unmarshal to a Schema structural fail,err: %s ", err)
}else{ } else {
if backupValue, ok := schema.StorageFields["backup"]; ok { if backupValue, ok := schema.StorageFields["backup"]; ok {
if _,ok := backupValue.Value.(map[string]interface{}); !ok { if _, ok := backupValue.Value.(map[string]interface{}); !ok {
return "", fmt.Errorf("backup parameters Unmarshal fail,it not json string,err: %s", err) return "", fmt.Errorf("backup parameters Unmarshal fail,it not json string,err: %s", err)
} }
} }
...@@ -673,22 +570,20 @@ func (this *Schema) put(args []string, stub shim.ChaincodeStubInterface) (string ...@@ -673,22 +570,20 @@ func (this *Schema) put(args []string, stub shim.ChaincodeStubInterface) (string
return "", fmt.Errorf("The common_name field must exist ") return "", fmt.Errorf("The common_name field must exist ")
} }
CompositeKey,err := stub.CreateCompositeKey(GxhSchema,[]string{args[0]}) CompositeKey, err := stub.CreateCompositeKey(GxhSchema, []string{args[0]})
if err != nil{ if err != nil {
return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args[0],err) return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args[0], err)
} }
if schemaCache.Get(args[0]) != nil { if schemaCache.Get(args[0]) != nil {
fmt.Println("schemaCache.Get err")
return "", fmt.Errorf("the schema %s already exists and cannot be added", args[0]) return "", fmt.Errorf("the schema %s already exists and cannot be added", args[0])
}else if value, _ := stub.GetState(CompositeKey); value != nil { } else if value, _ := stub.GetState(CompositeKey); value != nil {
fmt.Println("GetState.Get err")
return "", fmt.Errorf("the schema %s already exists and cannot be added", args[0]) return "", fmt.Errorf("the schema %s already exists and cannot be added", args[0])
} }
putDate, _ := json.Marshal(schema) //处理重复字段 putDate, _ := json.Marshal(schema) //处理重复字段
if err := stub.PutState(CompositeKey, putDate); err != nil { if err := stub.PutState(CompositeKey, putDate); err != nil {
return "", fmt.Errorf("Schema PutState fail,err: %s ", err) return "", fmt.Errorf("Schema PutState fail,err: %s ", err)
} }
schemaCache.Put(args[0],putDate) schemaCache.Put(args[0], schema)
return fmt.Sprintf("%s schema put success!", args[0]), nil return fmt.Sprintf("%s schema put success!", args[0]), nil
} }
...@@ -702,13 +597,13 @@ func (this *Schema) update(args []string, stub shim.ChaincodeStubInterface) (str ...@@ -702,13 +597,13 @@ func (this *Schema) update(args []string, stub shim.ChaincodeStubInterface) (str
return "", fmt.Errorf("Schema update operation expected 2 parameters! ") return "", fmt.Errorf("Schema update operation expected 2 parameters! ")
} }
var schema *Schema var schema *Schema
var schemaOld *Schema schemaOld := &Schema{}
var err error var err error
if schema ,err = NewSchema(args[1]);err != nil{ if schema, err = NewSchema(args[1]); err != nil {
return "", fmt.Errorf("The parameters Unmarshal to a Schema structural fail,err: %s ", err) return "", fmt.Errorf("The parameters Unmarshal to a Schema structural fail,err: %s ", err)
}else{ } else {
if backupValue, ok := schema.StorageFields["backup"]; ok { if backupValue, ok := schema.StorageFields["backup"]; ok {
if _,ok := backupValue.Value.(map[string]interface{}); !ok { if _, ok := backupValue.Value.(map[string]interface{}); !ok {
return "", fmt.Errorf("backup parameters Unmarshal fail,it not json string,err: %s", err) return "", fmt.Errorf("backup parameters Unmarshal fail,it not json string,err: %s", err)
} }
} }
...@@ -721,120 +616,381 @@ func (this *Schema) update(args []string, stub shim.ChaincodeStubInterface) (str ...@@ -721,120 +616,381 @@ func (this *Schema) update(args []string, stub shim.ChaincodeStubInterface) (str
if !ok { if !ok {
return "", fmt.Errorf("The common_name field must exist ") return "", fmt.Errorf("The common_name field must exist ")
} }
CompositeKey,err := stub.CreateCompositeKey(GxhSchema,[]string{args[0]}) CompositeKey, err := stub.CreateCompositeKey(GxhSchema, []string{args[0]})
if err != nil{ if err != nil {
return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args[0],err) return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args[0], err)
}
var result []byte
if result = schemaCache.Get(args[0]);result == nil{
fmt.Println("schemaCache.Get nil")
result, err := stub.GetState(CompositeKey)
if err != nil || result == nil {
return "", fmt.Errorf("%s schema data doesn't exist,please check your parameters ",args[0])
}
} }
if err := json.Unmarshal(result, &schemaOld); err != nil { err, schemaOld = schemaOld.get(args[0], stub)
return "", fmt.Errorf("The parameters Unmarshal to a Schema structural fail, err: %s ", err) if err != nil {
return "", err
} }
//if err := json.Unmarshal(result, &schemaOld); err != nil {
// return "", fmt.Errorf("The parameters Unmarshal to a Schema structural fail, err: %s ", err)
//}
commonName, err := getCertificateCommonName(stub) commonName, err := getCertificateCommonName(stub)
if err != nil { if err != nil {
return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err) return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
} }
if ok,err := authorityCheck(schemaOld.SchemaAuth.Write,commonName);!ok{ if ok, err := authorityCheck(schemaOld.SchemaAuth.Write, commonName, ""); !ok {
return "", fmt.Errorf("update %s schema fail,err: %s ",args[0],err) return "", fmt.Errorf("update %s schema fail,err: %s ", args[0], err)
} }
schema.LeadgerFields = schemaOld.LeadgerFields schema.LeadgerFields = schemaOld.LeadgerFields
updateData,_ := json.Marshal(schema) updateData, _ := json.Marshal(schema)
if err = stub.PutState(CompositeKey, updateData);err != nil{ if err = stub.PutState(CompositeKey, updateData); err != nil {
return "", fmt.Errorf("%s schema data PutState fail,please try again ",args[0]) return "", fmt.Errorf("%s schema data PutState fail,please try again ", args[0])
} }
schemaCache.Put(args[0],updateData)
return fmt.Sprintf("%s schema update success!", args[0]), err return fmt.Sprintf("%s schema update success!", args[0]), err
} }
func (this *Schema) get(args string, stub shim.ChaincodeStubInterface) error { func (this *Schema) get(args string, stub shim.ChaincodeStubInterface) (error, *Schema) {
schema := &Schema{}
var result []byte var result []byte
if result = schemaCache.Get(args);result == nil{ if schema = schemaCache.Get(args); schema == nil {
CompositeKey,err := stub.CreateCompositeKey(GxhSchema,[]string{args}) CompositeKey, err := stub.CreateCompositeKey(GxhSchema, []string{args})
if err != nil{ if err != nil {
return fmt.Errorf("the schema %s create comosite key fail,err : %s", args,err) return fmt.Errorf("the schema %s create comosite key fail,err : %s", args, err), nil
} }
result, err = stub.GetState(CompositeKey) result, err = stub.GetState(CompositeKey)
if err != nil || result == nil { if err != nil || result == nil {
return fmt.Errorf("%s schema data doesn't exist,please check your parameters ",args) return fmt.Errorf("%s schema data doesn't exist,please check your parameters ", args), nil
} }
schemaCache.Put(args,result) if err := json.Unmarshal(result, schema); err != nil {
return fmt.Errorf("SchemaData Unmarshal fail, err: %s", err), nil
} }
return json.Unmarshal(result,this) schemaCache.Put(args, schema)
}
return nil, schema
} }
func (this *Schema) getSchema(args string, stub shim.ChaincodeStubInterface)(string, error) { func (this *Schema) getSchema(args string, stub shim.ChaincodeStubInterface) (string, error) {
schema := &Schema{}
var result []byte var result []byte
if result = schemaCache.Get(args);result == nil{ if schema = schemaCache.Get(args); schema == nil {
CompositeKey,err := stub.CreateCompositeKey(GxhSchema,[]string{args}) CompositeKey, err := stub.CreateCompositeKey(GxhSchema, []string{args})
if err != nil{ if err != nil {
return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args,err) return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args, err)
} }
result, err = stub.GetState(CompositeKey) result, err := stub.GetState(CompositeKey)
if err != nil || result == nil { if err != nil || result == nil {
return "", fmt.Errorf("%s schema data doesn't exist,please check your parameters ",args) return "", fmt.Errorf("%s schema data doesn't exist,please check your parameters ", args)
} }
schemaCache.Put(args,result) if err := json.Unmarshal(result, schema); err != nil {
}
if err := json.Unmarshal(result, this); err != nil {
return "", fmt.Errorf("SchemaData Unmarshal fail, err: %s", err) return "", fmt.Errorf("SchemaData Unmarshal fail, err: %s", err)
} }
schemaCache.Put(args, schema)
} else {
result, _ = json.Marshal(schema)
}
commonName, err := getCertificateCommonName(stub) commonName, err := getCertificateCommonName(stub)
if err != nil { if err != nil {
return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err) return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
} }
if ok,err := authorityCheck(this.SchemaAuth.Read,commonName);!ok{ if ok, err := authorityCheck(this.SchemaAuth.Read, commonName, ""); !ok {
return "",fmt.Errorf("get %s schema fail,err: %s", args,err) return "", fmt.Errorf("get %s schema fail,err: %s", args, err)
} }
return string(result), nil return string(result), nil
} }
func transferTx(args []string, stub shim.ChaincodeStubInterface) (string, error) {
func transferTx(args []string, stub shim.ChaincodeStubInterface)(string, error) {
txFunc := transferType[args[0]] txFunc := transferType[args[0]]
if txFunc == nil{ if txFunc == nil {
return "", fmt.Errorf("No matching transfer operation method was found ! ") return "", fmt.Errorf("No matching transfer operation method was found ! ")
} }
err := txFunc(args[1:],stub) err := txFunc(args[1:], stub)
if err != nil { if err != nil {
return "", fmt.Errorf("%s transfer operation fail,err:%s ",args[0],err) return "", fmt.Errorf("%s transfer operation fail,err:%s ", args[0], err)
} }
return "", nil return "", nil
} }
func authorityCheck(authority AuthGroup, commonName string) (bool,error) { /*
var auths map[string]int64 有些特殊的putdata 数据是存在过滤条件的,此方法就是进行过滤
if IsUsers { */
auths = authority.Users func putData(filterName string, putDatas []map[string]interface{}, commonName string, schema *Schema, stub shim.ChaincodeStubInterface) (string, error) {
}else{ filterFunc := PutDataFilter[filterName]
auths = authority.Roles if filterFunc == nil {
} return "", fmt.Errorf("No matching filter operation method was found ! ")
if len(auths) == 0 {
return true,nil
}
for k, v := range auths {
if k == commonName {
if v == 0 || v > time.Now().Unix(){
return true,nil
}else{
return false,fmt.Errorf("%s user permission period ",commonName)
}
} }
str, err := filterFunc(putDatas, commonName, filterName, schema, stub)
if err != nil {
return "", fmt.Errorf("%s filter operation fail,err:%s ", filterName, err)
} }
return false,fmt.Errorf("%s user does not have permission",commonName) return str, nil
} }
/* /*
检查一组参数的权限是否匹配 在共享惠项目中当用户上传码数据时,存在对发行总数控制的要求。
*/ */
func parsauthorityCheck(schema map[string]SchemaParameters, checkmap map[string]interface{}, commonName string) (bool, error) { func codeFilter(putDatas []map[string]interface{}, commonName, tableName string, schema *Schema, stub shim.ChaincodeStubInterface) (string, error) {
sum := len(putDatas)
if sum == 0 {
return "", fmt.Errorf("put length cannot zero! ")
}
tid, ok := putDatas[0]["tid"].(string)
if !ok {
return "", fmt.Errorf("tid fields type must string! ")
}
dependData := "coutickets"
Stkey := StoragePrefix + "_" + dependData + "_" + tid
tmap, err := getState(Stkey, stub)
if err != nil {
return "", err
}
count, ok := tmap["surplusCount"].(float64) //剩余可发行数
if !ok {
return "", fmt.Errorf("surplusCount fields type must float64! ")
}
count -= float64(sum)
if count >= 0 {
tmap["surplusCount"] = count
} else {
return "", fmt.Errorf("The number of issues exceeds the total number of issues! ")
}
err = putState(Stkey, tmap, stub)
if err != nil {
return "", err
}
for k, mapres := range putDatas {
Id, ok := mapres["id"]
if !ok {
return "", fmt.Errorf("The id field must exist ")
}
_, ok = mapres["common_name"]
if !ok {
return "", fmt.Errorf("The common_name field must exist ")
}
err = SchemaCheck(schema, mapres)
if err != nil {
return "", fmt.Errorf("args index %d string, %s schema cheack fail,err : %s ", k, tableName, err)
}
if err := FiledsCheck(schema, mapres); err != nil {
return "", err
}
key := StoragePrefix + "_" + tableName + "_" + Id.(string)
_, err := getState(key, stub)
if err != nil {
return "", err
}
err = putState(key, mapres, stub)
if err != nil {
return "", err
}
}
return fmt.Sprintf("%s data save success!", tableName), nil
}
func commanFilter(putDatas []map[string]interface{}, commonName, tableName string, schema *Schema, stub shim.ChaincodeStubInterface) (string, error) {
for k, mapres := range putDatas {
Id, ok := mapres["id"]
if !ok {
return "", fmt.Errorf("The id field must exist ")
}
_, ok = mapres["common_name"]
if !ok {
return "", fmt.Errorf("The common_name field must exist ")
}
err := SchemaCheck(schema, mapres)
if err != nil {
return "", fmt.Errorf("args index %d string, %s schema cheack fail,err : %s ", k, tableName, err)
}
if err := FiledsCheck(schema, mapres); err != nil {
return "", err
}
key := StoragePrefix + "_" + tableName + "_" + Id.(string)
err = putState(key, mapres, stub)
if err != nil {
return "", err
}
}
return fmt.Sprintf("%s data save success!", tableName), nil
}
/*
券可用门店过滤表
*/
func ticketMerFilter(putDatas []map[string]interface{}, commonName, tableName string, schema *Schema, stub shim.ChaincodeStubInterface) (string, error) {
for k, mapres := range putDatas {
mid, ok := mapres["mid"]
if !ok {
return "", fmt.Errorf("The mid field must exist ")
}
tid, ok := mapres["tid"]
if !ok {
return "", fmt.Errorf("The tid field must exist ")
}
_, ok = mapres["common_name"]
if !ok {
return "", fmt.Errorf("The common_name field must exist ")
}
if len(schema.LeadgerFields) != 0 {
return "", fmt.Errorf("%s schema exist leadger fields,cannot putData", tableName)
}
err := SchemaCheck(schema, mapres)
if err != nil {
return "", fmt.Errorf("args index %d string, %s schema cheack fail,err : %s ", k, tableName, err)
}
if err := FiledsCheck(schema, mapres); err != nil {
return "", err
}
key := StoragePrefix + "_" + tableName + "_" + mid.(string) + "_" + tid.(string)
err = putState(key, mapres, stub)
if err != nil {
return "", err
}
}
return "", nil
}
func SchemaCheck(schema *Schema, checkmap map[string]interface{}) error {
if len(schema.StorageFields)+len(schema.LeadgerFields) != len(checkmap) {
return fmt.Errorf("The input field length is less than the schema field length ! ")
}
for k, v := range schema.StorageFields {
if schemaV, ok := checkmap[k]; !ok {
return fmt.Errorf("There is no input storage field %s ", k)
} else {
if parameterS, ok := v.Value.(map[string]interface{}); ok {
if parameterC, ok := schemaV.(map[string]interface{}); !ok {
return fmt.Errorf("The input field %s does not match the output field format ", k)
} else {
err := BackUpCheck(parameterS, parameterC)
if err != nil {
return err
}
}
}
}
}
for k, _ := range schema.LeadgerFields {
if _, ok := checkmap[k]; !ok {
return fmt.Errorf("There is no input leadger field %s ", k)
}
}
return nil
}
func FiledsCheck(schema *Schema, checkmap map[string]interface{}) error {
for k, schemaV := range schema.StorageFields {
if k != "backup" && schemaV.FCheck != nil && schemaV.FCheck.FType != "" && checkmap[k] != nil {
if err := fieldCheckout(schemaV.FCheck, checkmap[k]); err != nil {
return fmt.Errorf("%s %s ", k, err)
}
}
}
for k, schemaV := range schema.LeadgerFields {
if schemaV.FCheck != nil && schemaV.FCheck.FType != "" && checkmap[k] != nil {
if err := fieldCheckout(schemaV.FCheck, checkmap[k]); err != nil {
return fmt.Errorf("%s %s ", k, err)
}
}
}
return nil
}
func BackUpCheck(backUp map[string]interface{}, checkmap map[string]interface{}) error {
if len(backUp) != len(checkmap) {
return fmt.Errorf("The input backup field length is less than the schema backup field length ! ")
}
for k, _ := range checkmap {
if _, ok := backUp[k]; !ok {
return fmt.Errorf("There is no input backup field %s ", k)
}
}
return nil
}
/*
将字段根据账本数据,与存储数据分开
leadgers:参数表示我们需要在账本数据包含的字段,这些字段不属于账本数据。
*/
func separateFields(schema *Schema, checkmap map[string]interface{}, leadgers []string) (storagemap, leadgermap map[string]interface{}) {
storagemap = make(map[string]interface{})
leadgermap = make(map[string]interface{})
for k, _ := range schema.LeadgerFields {
leadgermap[k] = checkmap[k]
}
for _, v := range leadgers {
leadgermap[v] = checkmap[v]
}
for k, _ := range schema.StorageFields {
storagemap[k] = checkmap[k]
}
return
}
/*
根据权限拼装数据,进行数据过滤
*/
func dataFilter(schema *Schema, checkmap map[string]interface{}, commonName, onwer string) (map[string]interface{}, error) {
for k, schemaV := range schema.StorageFields {
if v, ok := checkmap[k]; !ok {
return nil, fmt.Errorf("Update data parameter mismatch with schema structure! ")
} else {
if _, ok := schemaV.Value.(map[string]SchemaParameters); ok {
if _, ok := v.(map[string]interface{}); !ok {
return nil, fmt.Errorf("Update data parameter mismatch with schema structure! ")
}
if ok, _ := authorityCheck(schemaV.PAuth.Read, commonName, onwer); !ok {
checkmap[k] = defValue
}
} else {
if ok, _ := authorityCheck(schemaV.PAuth.Read, commonName, onwer); !ok {
checkmap[k] = defValue
}
}
}
}
for k, schemaV := range schema.LeadgerFields {
if v, ok := checkmap[k]; !ok {
return nil, fmt.Errorf("Update data parameter mismatch with schema structure! ")
} else {
if _, ok := schemaV.Value.(map[string]SchemaLeadgerParameters); ok {
if _, ok := v.(map[string]interface{}); !ok {
return nil, fmt.Errorf("Update data parameter mismatch with schema structure! ")
}
if ok, _ := authorityCheck(schemaV.PAuth.Read, commonName, onwer); !ok {
checkmap[k] = defValue
}
} else {
if ok, _ := authorityCheck(schemaV.PAuth.Read, commonName, onwer); !ok {
checkmap[k] = defValue
}
}
}
}
return checkmap, nil
}
func authorityCheck(authority AuthGroup, commonName, owner string) (bool, error) {
var auths map[string]int64
if IsUsers {
auths = authority.Users
} else {
auths = authority.Roles
}
if len(auths) == 0 {
return true, nil
}
for k, v := range auths {
if k == commonName || (k == "owner" && commonName == owner) {
if v == 0 || v > time.Now().Unix() {
return true, nil
} else {
return false, fmt.Errorf("%s user permission period ", commonName)
}
}
}
return false, fmt.Errorf("%s user does not have permission", commonName)
}
/*
检查一组参数的权限是否匹配
*/
func parsauthorityCheck(schema map[string]SchemaParameters, checkmap map[string]interface{}, commonName string) (bool, error) {
for k, v := range checkmap { for k, v := range checkmap {
if schemaV, ok := schema[k]; !ok { if schemaV, ok := schema[k]; !ok {
return false, fmt.Errorf("Update data parameter mismatch with schema structure! ") return false, fmt.Errorf("Update data parameter mismatch with schema structure! ")
...@@ -844,8 +1000,8 @@ func parsauthorityCheck(schema map[string]SchemaParameters, checkmap map[string] ...@@ -844,8 +1000,8 @@ func parsauthorityCheck(schema map[string]SchemaParameters, checkmap map[string]
return false, fmt.Errorf("Update data parameter mismatch with schema structure! ") return false, fmt.Errorf("Update data parameter mismatch with schema structure! ")
} }
} }
if ok,err := authorityCheck(schemaV.PAuth.Write, commonName);!ok { if ok, err := authorityCheck(schemaV.PAuth.Write, commonName, ""); !ok {
return false, fmt.Errorf("%s field permission check does not match, err: %s ", k,err) return false, fmt.Errorf("%s field permission check does not match, err: %s ", k, err)
} }
} }
} }
...@@ -877,14 +1033,12 @@ func Deassign(upMap, result map[string]interface{}) error { ...@@ -877,14 +1033,12 @@ func Deassign(upMap, result map[string]interface{}) error {
return nil return nil
} }
/* /*
账户金额发现,核心是在对应的schema 找到有发行的权利。 账户金额发现,核心是在对应的schema 找到有发行的权利。
1:金额字段也就是(账本字段数据)都有发行标示 1:金额字段也就是(账本字段数据)都有发行标示
2:发行交易可以存在多个字段,但只要保证我们要求的字段存在就可以。账户类型,Id,发行金额(大于0) 2:发行交易可以存在多个字段,但只要保证我们要求的字段存在就可以。账户类型,Id,发行金额(大于0)
*/ */
func funtOperation(args []string, stub shim.ChaincodeStubInterface,isIssue bool) (string, error){ func funtOperation(args []string, stub shim.ChaincodeStubInterface, isIssue bool) (string, error) {
if len(args) != 1 { if len(args) != 1 {
return "", fmt.Errorf("issue or extract operation expected 1 parameters ! ") return "", fmt.Errorf("issue or extract operation expected 1 parameters ! ")
} }
...@@ -893,68 +1047,69 @@ func funtOperation(args []string, stub shim.ChaincodeStubInterface,isIssue bool) ...@@ -893,68 +1047,69 @@ func funtOperation(args []string, stub shim.ChaincodeStubInterface,isIssue bool)
return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err) return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
} }
action := &Action{} action := &Action{}
err = json.Unmarshal([]byte(args[0]),action) err = json.Unmarshal([]byte(args[0]), action)
if err != nil{ if err != nil {
return "", fmt.Errorf("json unmarshal Action structure fail,err: %s",err) return "", fmt.Errorf("json unmarshal Action structure fail,err: %s", err)
} }
schema := &Schema{} schema := &Schema{}
err = schema.get(action.AccountType, stub) err, schema = schema.get(action.AccountType, stub)
if err != nil { if err != nil {
return "", err return "", err
} }
if isIssue{ leadgerKey := LeadgerPrefix + "_" + action.AccountType + "_" + action.AccountId
if ok,err := authorityCheck(schema.LeadgerFields[action.FundType].PAuth.Issue, commonName);!ok { leadgermap, err := getState(leadgerKey, stub)
return "", fmt.Errorf("%s field issue permission check does not match, err: %s ", action.FundType , err) if err != nil {
return "", err
} }
}else { onwer, ok := leadgermap["common_name"].(string)
if ok,err := authorityCheck(schema.LeadgerFields[action.FundType].PAuth.Extract, commonName);!ok { if isIssue {
return "", fmt.Errorf("%s field extract permission check does not match, err: %s ", action.FundType , err) if ok, err := authorityCheck(schema.LeadgerFields[action.FundType].PAuth.Issue, commonName, onwer); !ok {
return "", fmt.Errorf("%s field issue permission check does not match, err: %s ", action.FundType, err)
} }
} else {
if ok, err := authorityCheck(schema.LeadgerFields[action.FundType].PAuth.Extract, commonName, onwer); !ok {
return "", fmt.Errorf("%s field extract permission check does not match, err: %s ", action.FundType, err)
} }
leadgerKey := LeadgerPrefix+"_"+action.AccountType+"_"+action.AccountId
leadgerResult, err := stub.GetState(leadgerKey)
if err != nil {
return "", fmt.Errorf("GetState %s data fail,err %s ",leadgerKey,err)
} }
if leadgerResult == nil { funt, ok := leadgermap[action.FundType].(string)
return "", fmt.Errorf("GetState %s data is null,please check your parameters ",leadgerKey) funtAmount, ok := new(big.Int).SetString(funt, 10)
if !ok {
return "", fmt.Errorf("%s parameter resolution to big.int failed ", action.FundType)
} }
var leadgermap map[string]interface{} actionAmount, ok := new(big.Int).SetString(action.ActionAmount, 10)
err = json.Unmarshal(leadgerResult,&leadgermap) if !ok {
if err != nil{ return "", fmt.Errorf("action_amount parameter resolution to big.int failed ")
return "", fmt.Errorf("json unmarshal leadger map fail,err: %s",err)
} }
funt := leadgermap[action.FundType].(float64) sum := new(big.Int)
amount := Decimal(action.ActionAmount)
if isIssue { if isIssue {
funt += amount sum = sum.Add(funtAmount, actionAmount)
}else{ } else {
if funt < amount{ if funtAmount.Cmp(actionAmount) == -1 {
return "", fmt.Errorf("The current amount is less than the withdrawal amount and cannot be extracted ") return "", fmt.Errorf("The current amount is less than the withdrawal amount and cannot be extracted ")
} }
funt-= amount sum = sum.Sub(funtAmount, actionAmount)
} }
leadgermap[action.FundType] = funt leadgermap[action.FundType] = sum.String()
leadgerResult,_ = json.Marshal(leadgermap) leadgerResult, _ := json.Marshal(leadgermap)
err = stub.PutState(leadgerKey,leadgerResult)
if err!=nil{ err = stub.PutState(leadgerKey, leadgerResult)
return "", fmt.Errorf("putState %s data fail,err: %s",leadgerKey,err) if err != nil {
return "", fmt.Errorf("putState %s data fail,err: %s", leadgerKey, err)
} }
return "transaction successful!", nil return "transaction successful!", nil
} }
/* /*
*/ */
func normalTransfer(args []string, stub shim.ChaincodeStubInterface)error{ func normalTransfer(args []string, stub shim.ChaincodeStubInterface) error {
if len(args) != 1 { if len(args) != 1 {
return nil return nil
} }
tx := &CommonTx{} tx := &CommonTx{}
err := json.Unmarshal([]byte(args[0]),tx) err := json.Unmarshal([]byte(args[0]), tx)
if err!= nil{ if err != nil {
fmt.Errorf("CommonTx structure json unmarshal fail,err : %s ",err) fmt.Errorf("CommonTx structure json unmarshal fail,err : %s ", err)
} }
sender := &TransferAccount{ sender := &TransferAccount{
tx.SenderAccountType, tx.SenderAccountType,
...@@ -966,47 +1121,32 @@ func normalTransfer(args []string, stub shim.ChaincodeStubInterface)error{ ...@@ -966,47 +1121,32 @@ func normalTransfer(args []string, stub shim.ChaincodeStubInterface)error{
tx.ReceiverId, tx.ReceiverId,
tx.ReceiverFunt, tx.ReceiverFunt,
} }
commonName ,err := getCertificateCommonName(stub) commonName, err := getCertificateCommonName(stub)
if err!= nil { if err != nil {
return nil return nil
} }
return transfer(Decimal(tx.Amount),sender,receiver,commonName,stub) amount, ok := new(big.Int).SetString(tx.Amount, 10)
if !ok {
return fmt.Errorf("amount parameter resolution to big.int failed ")
}
return transfer(amount, sender, receiver, commonName, stub)
} }
/* /*
当增加一条交易记录的时候,我们需要根据交易记录实现,1.预付金的计算,2.计算分成,3.预付金的变化。分成的计算 当增加一条交易记录的时候,我们需要根据交易记录实现,
1.预付金的计算,2.计算分成,3.预付金的变化。分成的计算
*/ */
func merchantsale(args []string, stub shim.ChaincodeStubInterface)error{ func merchantsale(args []string, stub shim.ChaincodeStubInterface) error {
commanName,err := getCertificateCommonName(stub) commanName, err := getCertificateCommonName(stub)
if err!=nil{ if err != nil {
return err return err
} }
senderaccountType := "merchants" senderaccountType := "merchants"
receiverAccountType := "alibusi" receiverAccountType := "alibusi"
mer := &Merchantsale{} mer := &Merchantsale{}
err = json.Unmarshal([]byte(args[0]),mer) err = json.Unmarshal([]byte(args[0]), mer)
if err != nil { if err != nil {
return fmt.Errorf("Merchantsale struct json unmarshal fail,err : %s ",err) return fmt.Errorf("Merchantsale struct json unmarshal fail,err : %s ", err)
}
//1.计算预付金 这部分待定1698.83
var treposit float64
if mer.Nodisamount == 0 || mer.Disamount == 0{ //如果打折金额与不打折金额任一为0,则认为全部打折
treposit = Decimal(mer.Oamount * mer.Adiscounts)
}else{
treposit = Decimal(mer.Nodisamount+ mer.Disamount * mer.Adiscounts)
}
if treposit != mer.Treposit {
return fmt.Errorf("treposit calculation fail ")
}
if mer.Fee != Decimal(mer.Tamount * mer.Feerate){
return fmt.Errorf("fee calculation fail ")
}
profit := mer.Tamount - mer.Fee - treposit //计算利润
if profit < 0 {
return fmt.Errorf("profit is negative ")
} }
sender := &TransferAccount{ sender := &TransferAccount{
senderaccountType, senderaccountType,
...@@ -1018,117 +1158,389 @@ func merchantsale(args []string, stub shim.ChaincodeStubInterface)error{ ...@@ -1018,117 +1158,389 @@ func merchantsale(args []string, stub shim.ChaincodeStubInterface)error{
mer.Bid, mer.Bid,
"abail", "abail",
} }
err = transfer(treposit,sender,receiver,commanName,stub)
if err!=nil{ rtreposit, ok := new(big.Int).SetString(mer.Treposit, 10)
return nil if !ok {
return fmt.Errorf("Treposit parameter resolution to big.int failed ")
}
//errinfo := make(chan error)
err = transfer(rtreposit, sender, receiver, commanName, stub)
if err != nil {
return err
}
//1.计算预付金 这部分待定
treposit := new(big.Int)
nodisamount, ok := new(big.Int).SetString(mer.Nodisamount, 10)
if !ok {
return fmt.Errorf("Nodisamount parameter resolution to big.int failed ")
}
disamount, ok := new(big.Int).SetString(mer.Disamount, 10)
if !ok {
return fmt.Errorf("Disamount parameter resolution to big.int failed ")
}
oamount, ok := new(big.Int).SetString(mer.Oamount, 10)
if !ok {
return fmt.Errorf("Oamount parameter resolution to big.int failed ")
}
if nodisamount.Cmp(big.NewInt(0)) == 0 || disamount.Cmp(big.NewInt(0)) == 0 { //如果打折金额与不打折金额任一为0,则认为全部打折
treposit, err = dividecalc(oamount, mer.Adiscounts)
if err != nil {
return err
}
} else {
distre, err := dividecalc(disamount, mer.Adiscounts) //计算打折部分的金额
if err != nil {
return err
}
treposit = new(big.Int).Add(nodisamount, distre)
} }
//进行分成数据 if treposit.Cmp(rtreposit) != 0 {
return fmt.Errorf("treposit calculation fail ")
}
return nil rfee, ok := new(big.Int).SetString(mer.Free, 10)
if !ok {
return fmt.Errorf("Fee parameter resolution to big.int failed ")
}
tamount, ok := new(big.Int).SetString(mer.Tamount, 10)
if !ok {
return fmt.Errorf("Tamount parameter resolution to big.int failed ")
}
fee, err := dividecalc(tamount, mer.Feerate)
if err != nil {
return err
}
if fee.Cmp(rfee) != 0 {
return fmt.Errorf("fee calculation fail ")
}
profit := new(big.Int).Sub(tamount, new(big.Int).Add(rfee, rtreposit)) //计算分成
if profit.Cmp(big.NewInt(0)) == -1 {
return fmt.Errorf("profit is negative ")
}
//进行分成数据
err = dividesTransaction(mer.Mid,treposit,stub)
if err!= nil{
return err
}
return err
} }
/* /*
共享惠订单交易 共享惠订单交易
*/ */
func tickerorders(args []string, stub shim.ChaincodeStubInterface)error{ func tickerorders(args []string, stub shim.ChaincodeStubInterface) error {
/* /*
由于共享惠还没有进行确定的订单交易所以这部分先进行伪代码的记录 由于共享惠还没有进行确定的订单交易所以这部分先进行伪代码的记录
1:计算实际支付是否正确, 1:计算实际支付是否正确,
2:计算手续费总和是否正确 2:计算手续费总和是否正确
3:计算利润 3:计算利润
4:是否需要进行商户金额的清分(待定) 4:是否需要进行商户金额的清分(待定)//待办
5:合作方分成 5:合作方分成
6:最终分成 6:最终分成
*/ */
//commanName, err := getCertificateCommonName(stub)
//if err != nil {
// return err
//}
ticketcanName := "coutcantm"
ticketName := "coutickets"
codeName := "couticketcodes"
oTx := &OrderTx{}
err := json.Unmarshal([]byte(args[0]), oTx)
if err != nil {
return fmt.Errorf("OrderTx struct json unmarshal fail,err : %s ", err)
}
tickMerKey := StoragePrefix + "_" + ticketcanName + "_" + oTx.Mid + "_" + oTx.Odesc.Tid //券可用门店key
tickM, err := getState(tickMerKey, stub)
if err != nil {
return err
}
tickKey := StoragePrefix + "_" + ticketName +"_" + oTx.Odesc.Tid //券key
tick, err := getState(tickKey, stub)
if err != nil {
return err
}
resid, _ := tickM["resid"].(float64) //剩余可用码数
discount, _ := tick["discount"].(float64) //得到券面值
fieldkeys := []string{"status"} // 码状态
var checkvalue, upvalue []interface{}
if resid == 0 {
return fmt.Errorf("The current merchant has been unable to use the %s ticket ", oTx.Odesc.Tid)
}
oamount,ok := new(big.Int).SetString(oTx.Oamount,10)
if !ok {
return fmt.Errorf("Oamount parameter resolution to big.int failed ")
}
pamount,ok := new(big.Int).SetString(oTx.Pamount,10)
if !ok {
return fmt.Errorf("Pamount parameter resolution to big.int failed ")
}
outfree,ok := new(big.Int).SetString(oTx.Outfree,10)
if !ok {
return fmt.Errorf("Outfree parameter resolution to big.int failed ")
}
infree,ok := new(big.Int).SetString(oTx.Infree,10)
if !ok {
return fmt.Errorf("Infree parameter resolution to big.int failed ")
}
partnersfree,ok := new(big.Int).SetString(oTx.Partnersfree,10)
if !ok {
return fmt.Errorf("Partnersfree parameter resolution to big.int failed ")
}
free,ok := new(big.Int).SetString(oTx.Free,10)
if !ok {
return fmt.Errorf("Free parameter resolution to big.int failed ")
}
if oTx.Odesc.TicketType == 1 { //如果是折扣券则只能使用一张券
if len(oTx.Odesc.Codes) > 1 {
return fmt.Errorf("Only one coupon can be used ")
}
codeKey := StoragePrefix + "_" + codeName + "_" + oTx.Odesc.Codes[0]
checkvalue[0] = float64(1)
upvalue[0] = float64(2)
_,err = checkandUpdate(codeKey,fieldkeys,checkvalue,upvalue,stub)
if err != nil {
return err
}
camount,_ := dividecalc(oamount,discount)
if camount.Cmp(pamount) != 0{
return fmt.Errorf("pamount calculation fail ")
}
} else {
for i, v := range oTx.Odesc.Codes {
codeKey := StoragePrefix + "_" + codeName + "_" + v
checkvalue[i] = float64(1)
upvalue[i] = float64(2)
_,err = checkandUpdate(codeKey,fieldkeys,checkvalue,upvalue,stub)
if err != nil {
return err
}
}
length := int64(len(oTx.Odesc.Codes))
disint := int64(discount) //将discount 转化为整数
camount := new(big.Int).Sub(oamount,big.NewInt(disint*length))
if camount.Cmp(pamount) != 0{
return fmt.Errorf("pamount calculation fail ")
}
}
cfree := new(big.Int).Add(new(big.Int).Add(outfree,infree),partnersfree)
if free.Cmp(cfree) != 0{
return fmt.Errorf("free calculation fail ")
}
income := new(big.Int).Sub(pamount,free)
treposit,err := dividecalc(income,oTx.Norate)
if err != nil{
return err
}
receiver := &TransferAccount{
AccountType:"coupartners",
AccountId:oTx.Pid,
FundType:"benefit",
}
err = transfer(partnersfree,nil,receiver,"",stub)
if err!= nil{
return err
}
//netincome := new(big.Int).Sub(income,treposit)
err = dividesTransaction(oTx.Mid,treposit,stub)
if err!= nil{
return err
}
return nil return nil
} }
/*
根据商户Id,进行分成交易
*/
func dividesTransaction(mid string,treposit *big.Int,stub shim.ChaincodeStubInterface)error{
merkey := StoragePrefix+ "_" + "merchants" + "_" + mid
mermap,err := getState(merkey,stub)
if err != nil{
return err
}
aid,ok := mermap["aid"].(string) //得到代理商Id
if !ok {
return fmt.Errorf("aid parameter resolution to string failed ")
}
bid,ok := mermap["bid"].(string) //得到分支机构Id
if !ok {
return fmt.Errorf("Free parameter resolution to string failed ")
}
acid,ok := mermap["acid"].(string) //得到加盟商Id
if !ok {
return fmt.Errorf("Free parameter resolution to string failed ")
}
fid,ok := mermap["fid"].(string) //得到保理
if !ok {
return fmt.Errorf("Free parameter resolution to string failed ")
}
asdiscounts ,err := divide(aid,treposit,stub)
if err != nil{
return err
}
bsdiscounts ,err := divide(bid,treposit,stub)
if err != nil{
return err
}
acsdiscounts ,err := divide(acid,treposit,stub)
if err != nil{
return err
}
fsdiscounts ,err := divide(fid,treposit,stub)
if err != nil{
return err
}
if asdiscounts+bsdiscounts+acsdiscounts+fsdiscounts > 1 {
return fmt.Errorf("The divide proportion must not exceed 1 ")
}
return nil
}
func divide(id string,treposit *big.Int,stub shim.ChaincodeStubInterface)(float64,error){
akey := StoragePrefix+ "_" + "alibusi" + "_" + id
amap,err := getState(akey,stub)
if err != nil{
return 0,err
}
sdiscounts,ok := amap["sdiscounts"].(float64)
if !ok {
return 0,fmt.Errorf("sdiscounts parameter resolution to float64 failed ")
}
adivide,err := dividecalc(treposit,sdiscounts)
if err != nil{
return 0, err
}
areceiver := &TransferAccount{
AccountType:"alibusi",
AccountId:id,
FundType:"amount",
}
return sdiscounts,transfer(adivide,nil,areceiver,"",stub)
}
/*
特别说明interface 不能是引用类型
*/
func checkandUpdate(key string, fieldkeys []string, checkvalue, upvalue []interface{}, stub shim.ChaincodeStubInterface)(map[string]interface{},error ){
valueMap, err := getState(key, stub)
if err != nil {
return nil,err
}
for i, fk := range fieldkeys {
if !reflect.DeepEqual(valueMap[fk], checkvalue[i]) {
return nil, fmt.Errorf("%s not the expected field value",fk)
} else {
valueMap[fk] = upvalue[i]
}
}
value, err := json.Marshal(valueMap)
if err != nil {
return nil, err
}
err = stub.PutState(key, value)
if err != nil {
return nil, err
}
return valueMap, nil
}
/* /*
实现普通的转账操作 实现普通的转账操作
*/ */
func transfer(amount float64,sender ,receiver *TransferAccount,commonName string,stub shim.ChaincodeStubInterface)error{ func transfer(amount *big.Int, sender, receiver *TransferAccount, commonName string, stub shim.ChaincodeStubInterface) error {
if amount <= 0 { var err error
return fmt.Errorf("transfer limit must greater than 0 ") if amount.Cmp(big.NewInt(0)) == -1 {
err = fmt.Errorf("transfer limit must greater than 0 ")
return err
} }
if sender != nil {
senderSchema := &Schema{} senderSchema := &Schema{}
err := senderSchema.get(sender.AccountType, stub) err, senderSchema = senderSchema.get(sender.AccountType, stub)
if err != nil {
return err
}
senderKey := LeadgerPrefix + "_" + sender.AccountType + "_" + sender.AccountId
senderleadgermap, err := getState(senderKey, stub)
if err != nil { if err != nil {
return err return err
} }
if ok,err := authorityCheck(senderSchema.LeadgerFields[sender.FundType].PAuth.Transfer, commonName);!ok { onwer, ok := senderleadgermap["common_name"].(string)
return fmt.Errorf("%s field issue permission check does not match, err: %s ", sender.FundType , err) if ok, err := authorityCheck(senderSchema.LeadgerFields[sender.FundType].PAuth.Transfer, commonName, onwer); !ok {
err = fmt.Errorf("%s field issue permission check does not match, err: %s ", sender.FundType, err)
return err
} }
senderKey := LeadgerPrefix+"_"+sender.AccountType+"_"+sender.AccountId fundstr := senderleadgermap[sender.FundType].(string)
senderleadgermap,err := getState(senderKey,stub) fund, ok := new(big.Int).SetString(fundstr, 10)
if err != nil{ if !ok {
err = fmt.Errorf("%s parameter resolution to big.int failed ", sender.FundType)
return err return err
} }
funt := senderleadgermap[sender.FundType].(float64) if fund.Cmp(amount) == -1 {
if funt < amount{ err = fmt.Errorf("The current amount is less than the withdrawal amount and cannot be extracted ")
return fmt.Errorf("The current amount is less than the withdrawal amount and cannot be extracted ") return err
} }
funt-= amount fund.Sub(fund, amount)
senderleadgermap[sender.FundType] = funt senderleadgermap[sender.FundType] = fund.String()
err = putState(senderKey,senderleadgermap,stub) err = putState(senderKey, senderleadgermap, stub)
if err != nil{ if err != nil {
return err return err
} }
receiverKey := LeadgerPrefix+"_"+receiver.AccountType+"_"+receiver.AccountId }
receiverleadgermap,err := getState(receiverKey,stub) if receiver != nil {
if err != nil{ receiverKey := LeadgerPrefix + "_" + receiver.AccountType + "_" + receiver.AccountId
receiverleadgermap, err := getState(receiverKey, stub)
if err != nil {
return err
}
rfundstr := receiverleadgermap[receiver.FundType].(string)
rfund, ok := new(big.Int).SetString(rfundstr, 10)
if !ok {
err = fmt.Errorf("%s parameter resolution to big.int failed ", receiver.FundType)
return err return err
} }
rfunt := receiverleadgermap[receiver.FundType].(float64) rfund.Add(rfund, amount)
rfunt+= amount receiverleadgermap[receiver.FundType] = rfund.String()
receiverleadgermap[receiver.FundType] = rfunt
err = putState(receiverKey,receiverleadgermap,stub) err = putState(receiverKey, receiverleadgermap, stub)
if err != nil{ if err != nil {
return err return err
} }
}
return nil return nil
} }
func getState(key string, stub shim.ChaincodeStubInterface) (map[string]interface{}, error) {
func getState(key string,stub shim.ChaincodeStubInterface)(map[string]interface{},error){
var resultmap map[string]interface{} var resultmap map[string]interface{}
result, err := stub.GetState(key) result, err := stub.GetState(key)
if err != nil { if err != nil {
return nil, fmt.Errorf("GetState %s data fail,err %s ",key,err) return nil, fmt.Errorf("GetState %s data fail,err %s ", key, err)
} }
if result == nil { if result == nil {
return nil,fmt.Errorf("GetState %s data is null,please check your parameters ",key) return nil, fmt.Errorf("GetState %s data is null,please check your parameters ", key)
} }
err = json.Unmarshal(result,&resultmap) err = json.Unmarshal(result, &resultmap)
if err != nil{ if err != nil {
return nil,fmt.Errorf("json unmarshal leadger map fail,err: %s",err) return nil, fmt.Errorf("json unmarshal leadger map fail,err: %s", err)
} }
return resultmap,nil return resultmap, nil
} }
func putState(key string,value map[string]interface{},stub shim.ChaincodeStubInterface)error{ func putState(key string, value map[string]interface{}, stub shim.ChaincodeStubInterface) error {
valueByte,err := json.Marshal(value) valueByte, err := json.Marshal(value)
if err != nil{ if err != nil {
return fmt.Errorf(" %s json marshal data fail,err: %s",key,err) return fmt.Errorf(" %s json marshal data fail,err: %s", key, err)
} }
err = stub.PutState(key,valueByte) err = stub.PutState(key, valueByte)
if err!=nil{ if err != nil {
return fmt.Errorf("putState %s data fail,err: %s",key,err) return fmt.Errorf("putState %s data fail,err: %s", key, err)
} }
return nil return nil
} }
func unmarshalMap(arg string)(error,map[string]interface{}){
var valueMap map[string]interface{}
err := json.Unmarshal([]byte(arg),&valueMap)
if err != nil{
return err,nil
}
return nil,valueMap
}
func getCertificateCommonName(stub shim.ChaincodeStubInterface) (string, error) { func getCertificateCommonName(stub shim.ChaincodeStubInterface) (string, error) {
return "Admin@org2.example.com", nil return "Admin@org2.example.com", nil
creatorByte, _ := stub.GetCreator() creatorByte, _ := stub.GetCreator()
...@@ -1153,133 +1565,146 @@ func Decimal(value float64) float64 { ...@@ -1153,133 +1565,146 @@ func Decimal(value float64) float64 {
return value return value
} }
func NewSchema(arg string)(*Schema,error){ func NewSchema(arg string) (*Schema, error) {
schema := &Schema{ schema := &Schema{
LeadgerFields:make(map[string]SchemaLeadgerParameters), LeadgerFields: make(map[string]SchemaLeadgerParameters),
StorageFields:make(map[string]SchemaParameters), StorageFields: make(map[string]SchemaParameters),
} }
var argMap map[string]interface{} var argMap map[string]interface{}
if err := json.Unmarshal([]byte(arg),&argMap);err!=nil{ if err := json.Unmarshal([]byte(arg), &argMap); err != nil {
return nil,err return nil, err
} }
if (argMap["storage_fields"] != nil || argMap["leadger_fields"] != nil)&& argMap["schema_auth"] != nil && argMap["auth"] != nil{ if (argMap["storage_fields"] != nil || argMap["leadger_fields"] != nil) && argMap["schema_auth"] != nil && argMap["auth"] != nil {
if err := json.Unmarshal([]byte(arg),schema);err!=nil{ if err := json.Unmarshal([]byte(arg), schema); err != nil {
return nil,err return nil, err
} }
//检查schema leadger字段 //检查schema leadger字段
err := leadgerFieldsCheck(&schema.LeadgerFields) err := leadgerFieldsCheck(&schema.LeadgerFields)
if err!=nil{ if err != nil {
return nil,err return nil, err
} }
return schema,nil return schema, nil
} }
for k,v := range argMap{ //假设用户只传递了map类型的信息,我们则默认它全部都是存储字段 for k, v := range argMap { //假设用户只传递了map类型的信息,我们则默认它全部都是存储字段
schema.StorageFields[k] = SchemaParameters{ schema.StorageFields[k] = SchemaParameters{
Value:v, Value: v,
PAuth:Auth{}, PAuth: Auth{},
} }
} }
return schema,nil return schema, nil
} }
func leadgerFieldsCheck(leadgerFields *map[string]SchemaLeadgerParameters)error{ func leadgerFieldsCheck(leadgerFields *map[string]SchemaLeadgerParameters) error {
for k,fields := range *leadgerFields{ for k, fields := range *leadgerFields {
if fields.FCheck == nil { if fields.FCheck == nil {
fields.FCheck = &Checks{ fields.FCheck = &Checks{
FType:"float64", FType: "big.int",
Must:false, Must: false,
Fieldlen:1, Fieldlen: 1,
} }
}else{ } else {
if fields.FCheck.FType != "float64"{ if fields.FCheck.FType != "big.int" {
return fmt.Errorf("%s fields type must is float64",k) return fmt.Errorf("%s fields type must is big.int", k)
}else if !(fields.FCheck.Fieldlen > 0) { } else if !(fields.FCheck.Fieldlen > 0) {
return fmt.Errorf("%s fields length must is greater than zero",k) return fmt.Errorf("%s fields length must is greater than zero", k)
} }
} }
if len(fields.PAuth.Extract.Roles) == 0 && len(fields.PAuth.Extract.Users) == 0 {
}
} }
return nil return nil
} }
func fieldCheckout(check *Checks, val interface{}) error {
func fieldCheckout(check *Checks,val interface{})error{
fType := reflect.TypeOf(val).String() fType := reflect.TypeOf(val).String()
switch check.FType { switch check.FType {
case "string": case "string":
if fType != "string"{ if fType != "string" {
return fmt.Errorf("fields type does not match the defined string type! ") return fmt.Errorf("fields type does not match the defined string type! ")
} }
if check.Must && (val == ""){ if check.Must && (val == "") {
return fmt.Errorf("fields can not be empty") return fmt.Errorf("fields can not be empty")
} }
value := val.(string) value := val.(string)
if len([]rune(value))>check.Fieldlen{ if len([]rune(value)) > check.Fieldlen {
return fmt.Errorf("fields length cannot be greater than %d ",check.Fieldlen) return fmt.Errorf("fields length cannot be greater than %d ", check.Fieldlen)
} }
case "int","int16","int32","int64","float32","float64": case "int", "int16", "int32", "int64", "float32", "float64":
if fType != "float64"{ if fType != "float64" {
return fmt.Errorf("fields type does not match the defined %s type! ",check.FType ) return fmt.Errorf("fields type does not match the defined %s type! ", check.FType)
} }
value := val.(float64) value := val.(float64)
if check.Must && (value == 0){ if check.Must && (value == 0) {
return fmt.Errorf("fields can not be 0") return fmt.Errorf("fields can not be 0")
} }
if check.Fieldlen !=0 && value < 0{ if check.Fieldlen != 0 && value < 0 {
return fmt.Errorf("fields cannot be negative") return fmt.Errorf("fields cannot be negative")
} }
case "time.Time": case "time.Time":
if fType != "string"{ if fType != "string" {
return fmt.Errorf("fields type does not match the defined time.Time type! ") return fmt.Errorf("fields type does not match the defined time.Time type! ")
} }
dateStr := reflect.ValueOf(val).String() dateStr := reflect.ValueOf(val).String()
if check.Must && dateStr == ""{ if check.Must && dateStr == "" {
return fmt.Errorf("fields cannot be empty") return fmt.Errorf("fields cannot be empty")
} }
if _ ,err := time.Parse("2006-01-02 15:04:05",dateStr);err != nil{ if _, err := time.Parse("2006-01-02 15:04:05", dateStr); err != nil {
return fmt.Errorf(err.Error()) return fmt.Errorf(err.Error())
} }
//if check.Must && (dateStr == "0001-01-01 00:00:00 +0000 UTC"|| dateStr == "0001-01-01T00:00:00Z"){ //if check.Must && (dateStr == "0001-01-01 00:00:00 +0000 UTC"|| dateStr == "0001-01-01T00:00:00Z"){
// return fmt.Errorf("fields cannot be initial value") // return fmt.Errorf("fields cannot be initial value")
//} //}
case "big.int":
if fType != "string" {
return fmt.Errorf("fields type does not match the defined big.int type! ")
}
number := new(big.Int)
dateStr := reflect.ValueOf(val).String()
_, ok := number.SetString(dateStr, 10)
if !ok {
return fmt.Errorf("parameter resolution failed ")
}
default: default:
fmt.Errorf("fields type no match! ") fmt.Errorf("fields type no match! ")
} }
return nil return nil
} }
func Constructor(capacity int) LRUCache{ func Constructor(capacity int) LRUCache {
lruCache := LRUCache{limit:capacity} lruCache := LRUCache{limit: capacity}
lruCache.HashMap = make(map[string]*Node, capacity) lruCache.HashMap = make(map[string]*Node, capacity)
return lruCache return lruCache
} }
func (l *LRUCache) Get(key string) []byte { func (l *LRUCache) Get(key string) *Schema {
if v,ok:= l.HashMap[key];ok { if v, ok := l.HashMap[key]; ok {
l.refreshNode(v) l.refreshNode(v)
return v.Value return v.Value
}else { } else {
return nil return nil
} }
} }
func (l *LRUCache) Put(key string, value []byte) { func (l *LRUCache) Put(key string, value *Schema) error {
if v,ok := l.HashMap[key];!ok{ if v, ok := l.HashMap[key]; !ok {
if len(l.HashMap) >= l.limit{ if len(l.HashMap) >= l.limit {
oldKey := l.removeNode(l.head) oldKey := l.removeNode(l.head)
delete(l.HashMap, oldKey) delete(l.HashMap, oldKey)
} }
node := Node{Key:key, Value:value} node := Node{Key: key, Value: value}
l.addNode(&node) l.addNode(&node)
l.HashMap[key] = &node l.HashMap[key] = &node
}else { } else {
v.Value = value v.Value = value
l.refreshNode(v) l.refreshNode(v)
} }
return nil
} }
func (l *LRUCache) refreshNode(node *Node){ func (l *LRUCache) refreshNode(node *Node) {
if node == l.end { if node == l.end {
return return
} }
...@@ -1287,21 +1712,21 @@ func (l *LRUCache) refreshNode(node *Node){ ...@@ -1287,21 +1712,21 @@ func (l *LRUCache) refreshNode(node *Node){
l.addNode(node) l.addNode(node)
} }
func (l *LRUCache) removeNode(node *Node) string{ func (l *LRUCache) removeNode(node *Node) string {
if node == l.end { if node == l.end {
l.end = l.end.pre l.end = l.end.pre
l.end.next = nil l.end.next = nil
}else if node == l.head { } else if node == l.head {
l.head = l.head.next l.head = l.head.next
l.head.pre = nil l.head.pre = nil
}else { } else {
node.pre.next = node.next node.pre.next = node.next
node.next.pre = node.pre node.next.pre = node.pre
} }
return node.Key return node.Key
} }
func (l *LRUCache) addNode(node *Node){ func (l *LRUCache) addNode(node *Node) {
if l.end != nil { if l.end != nil {
l.end.next = node l.end.next = node
node.pre = l.end node.pre = l.end
...@@ -1313,7 +1738,12 @@ func (l *LRUCache) addNode(node *Node){ ...@@ -1313,7 +1738,12 @@ func (l *LRUCache) addNode(node *Node){
} }
} }
func dividecalc(bint *big.Int, divide float64) (*big.Int, error) {
divide *= 1000000
value := new(big.Int).Mul(bint, big.NewInt(int64(divide)))
value.Div(value, big.NewInt(1000000))
return value, nil
}
func main() { func main() {
err := shim.Start(&GXHCC{}) err := shim.Start(&GXHCC{})
......
package main package main
import ( import (
"encoding/json"
"fmt" "fmt"
"github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/chaincode/shim"
"reflect"
"testing" "testing"
) )
...@@ -10,7 +12,7 @@ var ( ...@@ -10,7 +12,7 @@ var (
SchemaNew = `{"leadger_fields":{"abail":{"val":"0001-01-01T00:00:00Z","auth":{"read":{"users":{"Admin@org2.example.com":0},"roles": SchemaNew = `{"leadger_fields":{"abail":{"val":"0001-01-01T00:00:00Z","auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1584936259}},"issue":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}, {"Admin@org2.example.com":1584936259}},"issue":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},
"extrate":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"transfer":{"users":null,"roles":null}}, "extrate":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"transfer":{"users":null,"roles":null}},
"fcheck":{"ftype":"float64","must":false,"fieldlen":1}},"sabail":{"val":"0001-01-01T00:00:00Z","auth":{"read":{"users": "fcheck":{"ftype":"big.int","must":false,"fieldlen":1}},"sabail":{"val":"0001-01-01T00:00:00Z","auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"issue":{"users":{"Admin@org2.example.com":0},"roles": {"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"issue":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1584936259}},"extrate":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}, {"Admin@org2.example.com":1584936259}},"extrate":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},
"transfer":{"users":null,"roles":null}},"fcheck":null}},"storage_fields":{"common_name":{"val":"1","auth":{"read":{"users":null,"roles":null}, "transfer":{"users":null,"roles":null}},"fcheck":null}},"storage_fields":{"common_name":{"val":"1","auth":{"read":{"users":null,"roles":null},
...@@ -30,8 +32,8 @@ var ( ...@@ -30,8 +32,8 @@ var (
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":0}},"write":{"users":{"Admin@org2.example.com":0},"roles": {"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":0}},"write":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":0}}}}` {"Admin@org2.example.com":0}}}}`
merSchema = `{"leadger_fields":{"regular":{"val":6000,"auth":{"read":{"users":null,"roles":null},"issue":{"users":null,"roles":null},"extrate":{"users":null,"roles":null},"transfer":{"users":null, merSchema = `{"leadger_fields":{"regular":{"val":6000,"auth":{"read":{"users":null,"roles":null},"issue":{"users":null,"roles":null},"extrate":{"users":null,"roles":null},"transfer":{"users":null,
"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"rregular":{"val":6000,"auth":{"read":{"users":null,"roles":null},"issue":{"users":null,"roles":null},"extrate":{"users":null,"roles" "roles":null}},"fcheck":{"ftype":"big.int","must":false,"fieldlen":6}},"rregular":{"val":6000,"auth":{"read":{"users":null,"roles":null},"issue":{"users":null,"roles":null},"extrate":{"users":null,"roles"
:null},"transfer":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}}},"storage_fields":{"common_name":{"val":"1","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":null}, :null},"transfer":{"users":null,"roles":null}},"fcheck":{"ftype":"big.int","must":false,"fieldlen":6}}},"storage_fields":{"common_name":{"val":"1","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":null},
"acid":{"val":3,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles" "acid":{"val":3,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles"
:null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"actionid":{"val":1,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false, :null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"actionid":{"val":1,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,
"fieldlen":6}},"adiscounts":{"val":"0.8","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"aid":{"val":0,"auth":{"read": "fieldlen":6}},"adiscounts":{"val":"0.8","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"aid":{"val":0,"auth":{"read":
...@@ -62,7 +64,7 @@ null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"backup":{"val":{ ...@@ -62,7 +64,7 @@ null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"backup":{"val":{
"mno2": "05910005", "mno2": "05910005",
"indate": "2018/10/29 16:46:57", "indate": "2018/10/29 16:46:57",
"aid": 0, "aid": 0,
"regular": 6000, "regular": "60000000",
"adiscounts": 0.8, "adiscounts": 0.8,
"sdiscounts": 0.85, "sdiscounts": 0.85,
"distype": 16, "distype": 16,
...@@ -74,14 +76,14 @@ null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"backup":{"val":{ ...@@ -74,14 +76,14 @@ null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"backup":{"val":{
"did": 2, "did": 2,
"warmline": 600, "warmline": 600,
"cid": 0, "cid": 0,
"sregular": 6000, "sregular": 60000000,
"keywords": "test", "keywords": "test",
"paystatue": 1, "paystatue": 1,
"are": 1, "are": 1,
"marea": 1, "marea": 1,
"actionid": 1, "actionid": 1,
"tstatue": 1, "tstatue": 1,
"rregular": 6000, "rregular": "60000000",
"ssign": "2010-01-01 15:38:54", "ssign": "2010-01-01 15:38:54",
"firrenew": "2010-01-02 15:38:54", "firrenew": "2010-01-02 15:38:54",
"ordertel": "13444444444", "ordertel": "13444444444",
...@@ -125,7 +127,7 @@ null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"backup":{"val":{ ...@@ -125,7 +127,7 @@ null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"backup":{"val":{
"mno2": "05910005", "mno2": "05910005",
"indate": "2018/10/29 16:46:57", "indate": "2018/10/29 16:46:57",
"aid": 0, "aid": 0,
"regular": 6000, "regular": "60000000",
"adiscounts": 0.8, "adiscounts": 0.8,
"sdiscounts": 0.85, "sdiscounts": 0.85,
"distype": 16, "distype": 16,
...@@ -144,7 +146,7 @@ null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"backup":{"val":{ ...@@ -144,7 +146,7 @@ null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"backup":{"val":{
"marea": 1, "marea": 1,
"actionid": 1, "actionid": 1,
"tstatue": 1, "tstatue": 1,
"rregular": 6000, "rregular": "60000000",
"ssign": "2010-01-01 15:38:54", "ssign": "2010-01-01 15:38:54",
"firrenew": "2010-01-02 15:38:54", "firrenew": "2010-01-02 15:38:54",
"ordertel": "13444444444", "ordertel": "13444444444",
...@@ -190,10 +192,10 @@ null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"backup":{"val":{ ...@@ -190,10 +192,10 @@ null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"backup":{"val":{
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":0}},"write":{"users":{"Admin@org2.example.com":0},"roles": {"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":0}},"write":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":0}}}}` {"Admin@org2.example.com":0}}}}`
SchemaUpdate = `{"leadger_fields":{"abail22":{"val":"0001-01-01T00:00:00Z","auth":{"read":{"users":{"Admin@org2.example.com":0},"roles": SchemaUpdate = `{"leadger_fields":{"abail22":{"val":"0","auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1584936259}},"issue":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}, {"Admin@org2.example.com":1584936259}},"issue":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},
"extrate":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"transfer":{"users":null,"roles":null}}, "extrate":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"transfer":{"users":null,"roles":null}},
"fcheck":{"ftype":"float64","must":true,"fieldlen":1}},"sabail":{"val":"0001-01-01T00:00:00Z","auth":{"read":{"users": "fcheck":{"ftype":"big.int","must":true,"fieldlen":1}},"sabail":{"val":"0001-01-01T00:00:00Z","auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"issue":{"users":{"Admin@org2.example.com":0},"roles": {"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"issue":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1584936259}},"extrate":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}, {"Admin@org2.example.com":1584936259}},"extrate":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},
"transfer":{"users":null,"roles":null}},"fcheck":null}},"storage_fields":{"common_name":{"val":"1","auth":{"read":{"users":null,"roles":null}, "transfer":{"users":null,"roles":null}},"fcheck":null}},"storage_fields":{"common_name":{"val":"1","auth":{"read":{"users":null,"roles":null},
...@@ -301,10 +303,10 @@ func TestGXHPutData(t *testing.T){ ...@@ -301,10 +303,10 @@ func TestGXHPutData(t *testing.T){
} }
var ( var (
issueTx = `{"account_type":"alibusi","account_id":"1","action_amount":1000.123,"fund_type":"abail","back_up":{"account_type":"","account_id":"","action_amount":0,"fund_type":"","back_up":null}}` issueTx = `{"account_type":"alibusi","account_id":"1","action_amount":"1230","fund_type":"abail","back_up":{"account_type":"","account_id":"","action_amount":0,"fund_type":"","back_up":null}}`
extract = `{"account_type":"alibusi","account_id":"1","action_amount":100.123,"fund_type":"abail","back_up":{"account_type":"","account_id":"","action_amount":0,"fund_type":"","back_up":null}}` extract = `{"account_type":"alibusi","account_id":"1","action_amount":"123","fund_type":"abail","back_up":{"account_type":"","account_id":"","action_amount":0,"fund_type":"","back_up":null}}`
commontx = `{"sender_account":"alibusi","sender_id":"1","sender_funt":"abail","receiver_account":"alibusi","receiver_account_id":"2","receiver_funt":"abail","amount":100.123}` commontx = `{"sender_account":"alibusi","sender_id":"1","sender_funt":"abail","receiver_account":"alibusi","receiver_account_id":"2","receiver_funt":"abail","amount":"223"}`
merTx = `{"mid":"1","bid":"1","tamount":1805.01,"treposit":1698.83,"bereposit":6000,"afreposit":4301.17,"feerate":0.0055,"fee":9.93,"oamount":2123.54,"adiscounts":0.8,"sdiscounts":0.85,"nodisamount":0,"disamount":0,"perquisites":0} merTx = `{"mid":"1","bid":"1","tamount":"18050100","treposit":"16988320","bereposit":"60000000","afreposit":"43011700","feerate":0.0055,"fee":"99275","oamount":"21235400","adiscounts":0.8,"sdiscounts":0.85,"nodisamount":"0","disamount":"0","perquisites":"0"}
` `
) )
...@@ -337,7 +339,7 @@ func TestGXHIssueandExtract(t *testing.T){ ...@@ -337,7 +339,7 @@ func TestGXHIssueandExtract(t *testing.T){
fmt.Printf("Invoke status %d,message %s ,and payload %s \n", fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseBytx.Status,responseBytx.Message,string(responseBytx.Payload)) responseBytx.Status,responseBytx.Message,string(responseBytx.Payload))
fmt.Println() fmt.Println()
responseByget := stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("alibusi"),[]byte(inputUpdate)}) responseByget := stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("alibusi"),[]byte(`{"id":"1"}`)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n", fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget.Status,responseByget.Message,string(responseByget.Payload)) responseByget.Status,responseByget.Message,string(responseByget.Payload))
responseByget2 := stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("alibusi"),[]byte(`{"id":"2"}`)}) responseByget2 := stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("alibusi"),[]byte(`{"id":"2"}`)})
...@@ -348,13 +350,13 @@ func TestGXHIssueandExtract(t *testing.T){ ...@@ -348,13 +350,13 @@ func TestGXHIssueandExtract(t *testing.T){
/* /*
测试商户交易 测试商户交易
*/ */
//736288 590270 620798
func TestGXHmerTx(t *testing.T){ func TestGXHmerTx(t *testing.T){
stub := GXHmerTxinit() stub := GXHmerTxinit()
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("createTx"), []byte("transfer"),[]byte("merchants"),[]byte(merTx)}) responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("createTx"), []byte("transfer"),[]byte("merchants"),[]byte(merTx)})
if responseByPutschema.Status != 200{ if responseByPutschema.Status != 200{
fmt.Printf("schema init fail,err: %s",responseByPutschema.Message) fmt.Printf("schema init fail,err: %s",responseByPutschema.Message)
} }
fmt.Println()
responseByget2 := stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("merchants"),[]byte(`{"id":"1"}`)}) responseByget2 := stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("merchants"),[]byte(`{"id":"1"}`)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n", fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget2.Status,responseByget2.Message,string(responseByget2.Payload)) responseByget2.Status,responseByget2.Message,string(responseByget2.Payload))
...@@ -363,6 +365,8 @@ func TestGXHmerTx(t *testing.T){ ...@@ -363,6 +365,8 @@ func TestGXHmerTx(t *testing.T){
responseByget.Status,responseByget.Message,string(responseByget.Payload)) responseByget.Status,responseByget.Message,string(responseByget.Payload))
} }
func GXHmerTxinit()*shim.MockStub{ func GXHmerTxinit()*shim.MockStub{
cc := new(GXHCC) cc := new(GXHCC)
stub := shim.NewMockStub("GXHCC",cc) stub := shim.NewMockStub("GXHCC",cc)
...@@ -371,13 +375,13 @@ func GXHmerTxinit()*shim.MockStub{ ...@@ -371,13 +375,13 @@ func GXHmerTxinit()*shim.MockStub{
fmt.Println("========================================invoke schema put============================================") fmt.Println("========================================invoke schema put============================================")
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(SchemaNew)}) responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(SchemaNew)})
if responseByPutschema.Status != 200{ if responseByPutschema.Status != 200{
fmt.Printf("schema init fail,err: %s",responseByPutschema.Message) fmt.Printf("schema put alibusi fail,err: %s",responseByPutschema.Message)
return stub return stub
} }
fmt.Println()
responseBycreate := stub.MockInvoke("invoke1",[][]byte{[]byte("createAccount"), []byte("alibusi"),[]byte(inputarrary)}) responseBycreate := stub.MockInvoke("invoke1",[][]byte{[]byte("createAccount"), []byte("alibusi"),[]byte(inputarrary)})
if responseBycreate.Status != 200{ if responseBycreate.Status != 200{
fmt.Printf("createAccount init fail,err: %s",responseBycreate.Message) fmt.Printf("createAccount alibusi fail,err: %s",responseBycreate.Message)
return stub return stub
} }
fmt.Println() fmt.Println()
...@@ -385,15 +389,39 @@ func GXHmerTxinit()*shim.MockStub{ ...@@ -385,15 +389,39 @@ func GXHmerTxinit()*shim.MockStub{
fmt.Println("========================================invoke schema put============================================") fmt.Println("========================================invoke schema put============================================")
responseByMerschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("merchants"),[]byte(merSchema)}) responseByMerschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("merchants"),[]byte(merSchema)})
if responseByMerschema.Status != 200{ if responseByMerschema.Status != 200{
fmt.Printf("schema init fail,err: %s",responseByMerschema.Message) fmt.Printf("schema put merchants fail,err: %s",responseByMerschema.Message)
return stub return stub
} }
fmt.Println()
responseBycreateMer := stub.MockInvoke("invoke1",[][]byte{[]byte("createAccount"), []byte("merchants"),[]byte(merarrary)}) responseBycreateMer := stub.MockInvoke("invoke1",[][]byte{[]byte("createAccount"), []byte("merchants"),[]byte(merarrary)})
if responseBycreateMer.Status != 200{ if responseBycreateMer.Status != 200{
fmt.Printf("createAccount init fail,err: %s",responseBycreateMer.Message) fmt.Printf("createAccount merchants fail,err: %s",responseBycreateMer.Message)
return stub return stub
} }
return stub return stub
} }
func TestDeassign(t *testing.T) {
var m map[string]interface{}
err := json.Unmarshal([]byte(commontx),&m)
if err != nil{
t.Errorf(err.Error())
}
onwer,_ := m["sender_account"].(float64)
//fmt.Println(ok)
fmt.Println(onwer == 0)
}
//5958 5242 5600 5909
func BenchmarkBackUpCheck(b *testing.B) {
var m map[string]interface{}
err := json.Unmarshal([]byte(commontx),&m)
if err != nil{
fmt.Println(err.Error())
return
}
for i:=0;i<b.N ;i++ {
fmt.Println( reflect.DeepEqual(m["sender_account"] , m["receiver_account"]))
}
}
...@@ -4,6 +4,8 @@ import ( ...@@ -4,6 +4,8 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/chaincode/shim"
"math/big"
"strings"
"testing" "testing"
) )
...@@ -44,8 +46,8 @@ var ( ...@@ -44,8 +46,8 @@ var (
inputUpdate = `{"id":"1","aname":"alibusi","atype":100,"alinkman":10.34,"amob":"2006-01-02 15:04:05","backup": inputUpdate = `{"id":"1","aname":"alibusi","atype":100,"alinkman":10.34,"amob":"2006-01-02 15:04:05","backup":
{"aname":"alibusi","atype":"type"}}` {"aname":"alibusi","atype":"type"}}`
inputarrary = `[{"abail":0,"sabail":0,"id":"1","aname":"alibusi","atype":100,"alinkman":10.34,"amob":"2006-01-02 15:04:05","backup": inputarrary = `[{"abail":"0","sabail":"0","id":"1","aname":"alibusi","atype":100,"alinkman":10.34,"amob":"2006-01-02 15:04:05","backup":
{"aname":"alibusi","atype":"type"},"common_name":"admin"},{"abail":0,"sabail":0,"id":"2","aname":"alibusi","atype":100,"alinkman": {"aname":"alibusi","atype":"type"},"common_name":"admin"},{"abail":"0","sabail":"0","id":"2","aname":"alibusi","atype":100,"alinkman":
10.34,"amob":"2006-01-02 15:04:05","backup":{"aname":"alibusi","atype":"type"},"common_name":"admin"}]` 10.34,"amob":"2006-01-02 15:04:05","backup":{"aname":"alibusi","atype":"type"},"common_name":"admin"}]`
inputPutarray = `[{"id":"1","aname":"alibusi","atype":100,"alinkman":10.34,"amob":"2006-01-02 15:04:05","backup":{"aname":"alibusi", inputPutarray = `[{"id":"1","aname":"alibusi","atype":100,"alinkman":10.34,"amob":"2006-01-02 15:04:05","backup":{"aname":"alibusi",
"atype":"type"},"common_name":"admin"},{"id":"2","aname":"alibusi","atype":100,"alinkman":10.34,"amob":"2006-01-02 15:04:05","backup": "atype":"type"},"common_name":"admin"},{"id":"2","aname":"alibusi","atype":100,"alinkman":10.34,"amob":"2006-01-02 15:04:05","backup":
...@@ -276,3 +278,45 @@ func TestPut(t *testing.T){ ...@@ -276,3 +278,45 @@ func TestPut(t *testing.T){
} }
func TestDivide(t *testing.T){
testInt := big.NewInt(23456789000000)
i , err := dividecalc(testInt,float64(0.0056))
if err!=nil{
t.Error(err.Error())
}
fmt.Println(i)
}
//经过测试发现使用big.int 比直接使用float64 会有2500多倍的性能损失
func BenchmarkDivide(b *testing.B) {
for i:= 0 ;i < b.N ; i++ {
//testInt := big.NewInt(23456789)
//i := dividecalctest(testInt,float64(0.0056))
//if err!=nil{
// fmt.Println("happen err",err)
// return
//}
}
//for i:= 0 ;i < b.N ; i++ {
// a := float64(23456789)
// _ , err := testfunc(a,float64(0.0056))
// if err!=nil{
// fmt.Println("happen err",err)
// return
// }
// //fmt.Println(c)
//}
}
func testfunc(a,b float64)(float64,error){
str := fmt.Sprintf("%v", b)
strs := strings.Split(str, ".")
if len(strs[1]) > 6 {
return 0, fmt.Errorf("divide can only exist to six decimal places ")
}
//var mul int64
//length := len(strs[1])
// pow(10,int64(length))
return a*b,nil
}
package main
import (
"encoding/json"
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
)
func put(tablename string,PutDatas []map[string]interface{}, stub shim.ChaincodeStubInterface) (string, error) {
commonName, err := getCertificateCommonName(stub)
if err != nil {
return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
}
schema := &Schema{}
schema ,err = getSchema(tablename, stub)
if err != nil {
return "", err
}
if err := schema.AllWriteCheck( commonName, ""); err != nil {
return "", fmt.Errorf("write %s table fail,err: %s ", tablename, err)
}
if len(schema.LeadgerFields) != 0 {
return createAccount(tablename,PutDatas,schema,stub)
}else{
return putData(tablename, PutDatas, commonName, schema, stub)
}
}
/*
根据账户类型创建账本账户,由于我们这里有存储数据与账本数据两种,所以我们还需要在schema 部分标识不同的数据类型。
伪代码:
1:检查当前用户是否具有账户的总写(创建)权限
2:检查账户必备的属性,如Id,账户名,账户所属者,对应的是证书commonName
2:根据schema 标注的金额(账本)字段,和存证字段,分别进行数据的putState存储工作。其中在存证数据的Id 字段是标示字段。
3:完成账户创建工作
*/
func createAccount(tablename string,PutDatas []map[string]interface{},schema *Schema, stub shim.ChaincodeStubInterface) (string, error) {
for k, mapres := range PutDatas {
Id, ok := mapres["id"]
if !ok {
return "", fmt.Errorf("The id field must exist ")
}
_, ok = mapres["common_name"]
if !ok {
return "", fmt.Errorf("The common_name field must exist ")
}
err := schema.FieldsCheck(mapres)
if err != nil {
return "", fmt.Errorf("args index %d string, %s schema cheack fail,err : %s ", k, tablename, err)
}
storagemap, leadgermap := separateFields(schema, mapres, []string{"id", "common_name"})
key := StoragePrefix + "_" + tablename + "_" + Id.(string)
getResult, err := getState(key,stub)
if err != nil {
return "", fmt.Errorf("GetState %s data fail,please check your parameters ", key)
}
if getResult != nil {
return "", fmt.Errorf("%s data already exists and cannot be added", key)
}
if err := putState(key, storagemap,stub); err != nil {
return "", err
}
if err := putState(LeadgerPrefix+"_"+tablename+"_"+Id.(string), leadgermap,stub); err != nil {
return "", err
}
}
return fmt.Sprintf("create %s account success!", tablename), nil
}
/*
修改一个账户的存储数据,修改规则由Schema 控制,有些特殊数据在账本数据也使用,所以无法修改
*/
func updateStoreData(tablename string,updata map[string]interface{}, stub shim.ChaincodeStubInterface) (string, error) {
commonName, err := getCertificateCommonName(stub)
if err != nil {
return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
}
schema := &Schema{}
schema ,err = getSchema(tablename, stub)
if err != nil {
return "", err
}
Id, ok := updata["id"]
if !ok {
return "", fmt.Errorf("The id field must exist ")
}
_, ok = updata["common_name"]
if ok {
return "", fmt.Errorf("The common_name field cannot update ")
}
key := StoragePrefix + "_" + tablename + "_" + Id.(string)
allMap, err := getState(key, stub)
if err != nil {
return "", err
}
owner, ok := allMap["common_name"].(string)
if !ok {
return "", fmt.Errorf("common_name fields resolution failed ")
}
schema.AllWriteCheck(commonName, owner)
if err != nil{
err := schema.DataWriteCheck( updata, commonName,owner)
if err !=nil{
return "", err
}
}
if err := schema.FieldsFormatCheck(updata); err != nil {
return "", err
}
if err := Deassign(updata, allMap); err != nil {
return "", err
}
err = putState(key, allMap, stub)
if err != nil {
return "", err
}
return fmt.Sprintf("%s update data success!",tablename), nil
}
/*
查询数据,如果存在账本数据,与存证数据,则进行数据拼接,然后返回。
*/
func get(tablename string,parameters map[string]interface{}, stub shim.ChaincodeStubInterface) (string, error) {
commonName, err := getCertificateCommonName(stub)
if err != nil {
return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
}
Id, ok := parameters["id"]
if !ok {
return "", fmt.Errorf("The id field must exist ")
}
storageKey := StoragePrefix + "_" + tablename + "_" + Id.(string)
mapResult, err := getState(storageKey, stub)
if err != nil {
return "", err
}
leadgerKey := LeadgerPrefix + "_" + tablename + "_" + Id.(string)
leadgerResult, err := stub.GetState(leadgerKey)
if err != nil {
return "", fmt.Errorf("get %s data fail,please check your parameters ", leadgerKey)
}
schema := &Schema{}
schema ,err = getSchema(tablename, stub)
if err != nil {
return "", err
}
if leadgerResult != nil {
if err := json.Unmarshal(leadgerResult, &mapResult); err != nil {
return "", fmt.Errorf("The leadger original data Unmarshal fail err:%s ", err)
}
}
onwer, ok := mapResult["common_name"].(string)
if !ok {
return "", fmt.Errorf("common_name fields resolution failed ")
}
if err := schema.AllReadCheck( commonName, onwer); err != nil {
if filteredData, err := schema.ReadFiler( mapResult, commonName, onwer); err != nil {
return "", fmt.Errorf("get data authority filter fail, err: %s", err)
} else {
result, _ := json.Marshal(filteredData)
return string(result), nil
}
} else {
result, _ := json.Marshal(mapResult)
return string(result), nil
}
}
/*
有些特殊的putdata 数据是存在过滤条件的,此方法就是进行过滤
*/
func putData(filterName string, putDatas []map[string]interface{}, commonName string, schema *Schema, stub shim.ChaincodeStubInterface) (string, error) {
filterFunc := PutDataFilter[filterName]
if filterFunc == nil {
return "", fmt.Errorf("No matching filter operation method was found ! ")
}
str, err := filterFunc(putDatas, commonName, filterName, schema, stub)
if err != nil {
return "", fmt.Errorf("%s filter operation fail,err:%s ", filterName, err)
}
return str, nil
}
/*
在共享惠项目中当用户上传码数据时,存在对发行总数控制的要求。
*/
func codeFilter(putDatas []map[string]interface{}, commonName, tableName string, schema *Schema, stub shim.ChaincodeStubInterface) (string, error) {
sum := len(putDatas)
if sum == 0 {
return "", fmt.Errorf("put length cannot zero! ")
}
tid, ok := putDatas[0]["tid"].(string)
if !ok {
return "", fmt.Errorf("tid fields type must string! ")
}
dependData := "coutickets"
Stkey := StoragePrefix + "_" + dependData + "_" + tid
tmap, err := getState(Stkey, stub)
if err != nil {
return "", err
}
count, ok := tmap["surplusCount"].(float64) //剩余可发行数
if !ok {
return "", fmt.Errorf("surplusCount fields type must float64! ")
}
count -= float64(sum)
if count >= 0 {
tmap["surplusCount"] = count
} else {
return "", fmt.Errorf("The number of issues exceeds the total number of issues! ")
}
err = putState(Stkey, tmap, stub)
if err != nil {
return "", err
}
for k, mapres := range putDatas {
Id, ok := mapres["id"]
if !ok {
return "", fmt.Errorf("The id field must exist ")
}
_, ok = mapres["common_name"]
if !ok {
return "", fmt.Errorf("The common_name field must exist ")
}
err = schema.FieldsCheck(mapres)
if err != nil {
return "", fmt.Errorf("args index %d string, %s schema cheack fail,err : %s ", k, tableName, err)
}
key := StoragePrefix + "_" + tableName + "_" + Id.(string)
_, err := getState(key, stub)
if err != nil {
return "", err
}
err = putState(key, mapres, stub)
if err != nil {
return "", err
}
}
return fmt.Sprintf("%s data save success!", tableName), nil
}
func commanFilter(putDatas []map[string]interface{}, commonName, tableName string, schema *Schema, stub shim.ChaincodeStubInterface) (string, error) {
for k, mapres := range putDatas {
Id, ok := mapres["id"]
if !ok {
return "", fmt.Errorf("The id field must exist ")
}
_, ok = mapres["common_name"]
if !ok {
return "", fmt.Errorf("The common_name field must exist ")
}
err := schema.FieldsFormatCheck(mapres)
if err!= nil{
return "", fmt.Errorf("args index %d string, %s schema cheack fail,err : %s ", k, tableName, err)
}
key := StoragePrefix + "_" + tableName + "_" + Id.(string)
err = putState(key, mapres, stub)
if err != nil {
return "", err
}
}
return fmt.Sprintf("%s data save success!", tableName), nil
}
/*
券可用门店过滤表
*/
func ticketMerFilter(putDatas []map[string]interface{}, commonName, tableName string, schema *Schema, stub shim.ChaincodeStubInterface) (string, error) {
for k, mapres := range putDatas {
mid, ok := mapres["mid"]
if !ok {
return "", fmt.Errorf("The mid field must exist ")
}
tid, ok := mapres["tid"]
if !ok {
return "", fmt.Errorf("The tid field must exist ")
}
_, ok = mapres["common_name"]
if !ok {
return "", fmt.Errorf("The common_name field must exist ")
}
err := schema.FieldsFormatCheck(mapres)
if err!= nil{
return "", fmt.Errorf("args index %d string, %s schema cheack fail,err : %s ", k, tableName, err)
}
key := StoragePrefix + "_" + tableName + "_" + mid.(string) + "_" + tid.(string)
err = putState(key, mapres, stub)
if err != nil {
return "", err
}
}
return "", nil
}
\ No newline at end of file
package main
import (
"bytes"
"crypto/x509"
"encoding/json"
"math/big"
"encoding/pem"
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
"strconv"
"strings"
)
type GXHCC struct {
}
type AuthGroup struct {
Users map[string]int64 `json:"users"` //用户组权限,默认使用用户组。我们使用形如:“User1”:timestamp. key 表示用户或者角色,value 表示有效时间。我们使用格林威治时间时间戳
Roles map[string]int64 `json:"roles"` //角色组权限,
}
type Auth struct {
Read AuthGroup `json:"read"` // 字段的读权限,“”,不存在权限,
Write AuthGroup `json:"write"` //字段的写权限
}
type LeadgerAuth struct { // 账本数据除了读权限外
Read AuthGroup `json:"read"` // 字段的读权限,“”,不存在权限,
Issue AuthGroup `json:"issue"` //账本数据的发行权限,
Extract AuthGroup `json:"extrate"` //账本数据的提取权限,
Transfer AuthGroup `json:"transfer"` // 账本数据的转账权限,
}
type SchemaParameters struct {
Value interface{} `json:"val"` //默认值 这里特别说明一下如果这里是backUp 字段,我们不进行更深一步的校验,包括格式
PAuth Auth `json:"auth"`
FCheck *Checks `json:"fcheck"`
}
type SchemaLeadgerParameters struct {
Value interface{} `json:"val"` //默认值 这里特别说明一下如果这里是backUp 字段,我们不进行更深一步的校验,包括格式
PAuth LeadgerAuth `json:"auth"`
FCheck *Checks `json:"fcheck"`
}
type Checks struct {
FType string `json:"ftype"` //字段类型
Must bool `json:"must"` //是否必填
Fieldlen int `json:"fieldlen"` //字段长度(如果字段类型是string,表示字段长度,如果是数值类型用0,1表示数据正负)
}
type Schema struct {
LeadgerFields map[string]SchemaLeadgerParameters `json:"leadger_fields"` //账本字段
StorageFields map[string]SchemaParameters `json:"storage_fields"` //存证字段
SchemaAuth Auth `json:"schema_auth"` //schema 的写权限,主要是用在 schema update 部分
SAuth Auth `json:"auth"` //数据总的读权限
}
type Action struct {
AccountType string `json:"account_type"` //账户类型
AccountId string `json:"account_id"` //账户Id
ActionAmount string `json:"action_amount"` //这次的动作金额
FundType string `json:"fund_type"` //资金类型
BackUp interface{} `json:"back_up"` //备注信息
}
type TransferAccount struct {
AccountType string `json:"account_type"` //账户类型
AccountId string `json:"account_id"` //账户Id
FundType string `json:"fund_type"` //资金类型
}
type Node struct {
Key string
Value *Schema
pre *Node
next *Node
}
type LRUCache struct {
limit int
HashMap map[string]*Node
head *Node
end *Node
}
type Merchantsale struct {
Mid string `json:"mid"` //商户Id
Bid string `json:"bid"` // 分支机构id,也是一笔交易的接受者
Tamount string `json:"tamount"` //交易金额
Treposit string `json:"treposit"` //扣除预付金
Bereposit string `json:"bereposit"` //扣除前预付金
Afreposit string `json:"afreposit"` //扣除后预付金
Feerate float64 `json:"feerate"` // 手续费扣率
Free string `json:"free"` // 手续费
Oamount string `json:"oamount"` // 原始交易金额
Adiscounts float64 `json:"adiscounts"` //代理结算折扣
Sdiscounts float64 `json:"sdiscounts"` //消费折扣
Nodisamount string `json:"nodisamount"` //不打折金额
Disamount string `json:"disamount"` //打折金额
Perquisites string `json:"perquisites"` //额外收益
}
type OrderTx struct {
Oamount string `json:"oamount"` // 原始交易金额
Pamount string `json:"pamount"` // 支付金额
Odesc *OrderDescribe `json:"odesc"` //订单描述
Mid string `json:"mid"` //商户Id
Norate float64 `json:"norate"` //无预付金收益率
Outfree string `json:"outfree"` //付款方手续费
Infree string `json:"infree"` //收款方手续费
Partnersfree string `json:"partnersfree"` //订单合作方手续费
Free string `json:"free"` // 手续费
Pid string `json:"pid"` //合作方Id
}
type OrderDescribe struct {
Codes []string `json:"codes"` //码
TicketType int `json:"ticket_type"` //券类型,折扣券只能使用一次
Tid string `json:"tid"` //券Id
}
type CommonTx struct {
SenderAccountType string `json:"sender_account"`
SenderId string `json:"sender_id"`
SenderFunt string `json:"sender_funt"`
ReceiverAccountType string `json:"receiver_account"`
ReceiverId string `json:"receiver_id"`
ReceiverFunt string `json:"receiver_funt"`
Amount string `json:"amount"`
}
type transferTypes func(args []string, stub shim.ChaincodeStubInterface) error // 声明了一个函数类型
type putDataFilter func(putDatas []map[string]interface{}, name, tableName string, schema *Schema, stub shim.ChaincodeStubInterface) (string, error) // 声明了一个函数类型,这个函数类型主要是用于putdata 数据过滤使用
var (
defValue = "***" //查询用户权限不足的情况下默认返回值
StoragePrefix = "SGXH"
LeadgerPrefix = "LGXH"
IsUsers = true //是否启用用户权限,false 表示启用Roles
GxhSchema = "gxhSchema" //schema 存储前缀,为了实现复合主键使用。
InitSchemaLength = 12 //缓存的 schema 的长度
schemaCache = Constructor(InitSchemaLength)
updateTime = int64(60 * 60 * 12) //schema 更新时间间隔,默认是12小时
lastTime = int64(0)
transferType = initTransfer()
PutDataFilter = initPutData()
)
// Init does nothing for this cc
func (t *GXHCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success([]byte("gxhcc init successful! "))
}
/*
初始化我们要使用的交易执行方法
*/
func initTransfer() map[string]transferTypes {
transferType := make(map[string]transferTypes)
transferType["merchants"] = merchantsale
transferType["tickerorders"] = tickerorders
transferType["commontx"] = normalTransfer
return transferType
}
func initPutData() map[string]putDataFilter {
filter := make(map[string]putDataFilter)
filter["couticketcodes"] = codeFilter
filter["commonput"] = commanFilter
filter["coutcantm"] = ticketMerFilter
return filter
}
/*
处理缓存内容的方法,
*/
func initSchema(stub shim.ChaincodeStubInterface) error {
timeStamp, err := stub.GetTxTimestamp()
if err != nil {
return err
} else if timeStamp.GetSeconds() < lastTime+updateTime {
return nil
}
var values map[string]*Schema
values = make(map[string]*Schema)
schemaIterator, err := stub.GetStateByPartialCompositeKey(GxhSchema, nil)
if err != nil {
return err
}
defer schemaIterator.Close()
index := 1
for schemaIterator.HasNext() {
querykv, err := schemaIterator.Next()
if err != nil {
return err
}
fmt.Println("add cache key:", querykv.Key)
_, compisiteKeys, err := stub.SplitCompositeKey(querykv.Key)
if err != nil {
return err
}
scema := &Schema{}
err = json.Unmarshal(querykv.Value, scema)
if err != nil {
fmt.Sprintf("json unmarshal %s schema fail,err: %s \n", querykv.Key, err)
}
if schemaCache.Get(compisiteKeys[0]) != nil {
schemaCache.Put(compisiteKeys[0], scema)
fmt.Println("add cache key:", querykv.Key)
index++
if index > InitSchemaLength {
fmt.Println("cache data length :", len(schemaCache.HashMap))
return nil
}
} else {
values[compisiteKeys[0]] = scema
}
}
for len(schemaCache.HashMap) < InitSchemaLength {
for k, v := range values {
schemaCache.Put(k, v)
}
}
fmt.Println("cache data length :", len(schemaCache.HashMap))
lastTime = timeStamp.GetSeconds() //设置最新修改时间
return nil
}
// Invoke for this chaincode exposes
func (t *GXHCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
// get arguments and transient
functionName, args := stub.GetFunctionAndParameters()
var err error
err = initSchema(stub)
if err != nil {
return shim.Error(err.Error())
}
paths := splitPath(functionName)
return Router(paths,args,stub)
}
func Router(paths,args []string ,stub shim.ChaincodeStubInterface) pb.Response {
switch paths[0] {
case "schema":
return SchemaProcess(paths,args, stub)
case "put":
return putApi(args, stub)
case "update":
return updateApi(args, stub)
case "get":
return getApi(args, stub)
case "createTx":
return transactionProcess(paths,args, stub)
case "getCertCommonName":
return getCertNameApi(stub)
default:
return shim.Error(fmt.Sprintf("Unsupported function %s", paths[0]))
}
}
func putApi(args []string, stub shim.ChaincodeStubInterface)pb.Response{
if len(args) < 2 {
return shim.Error("put data operation expected more than 2 parameters! ")
}
var PutDatas []map[string]interface{}
err := json.Unmarshal([]byte(args[1]), &PutDatas)
if err != nil {
return shim.Error(fmt.Sprintf("%s table parameters Unmarshal fail,put string not json array, err:%s", args[0], err))
}
res, err := put(args[0],PutDatas,stub)
if err != nil {
return shim.Error(fmt.Sprintf("put function err: %s", err))
}
return shim.Success([]byte("gxhcc invoke successful:" + res))
}
func updateApi(args []string, stub shim.ChaincodeStubInterface)pb.Response{
if len(args) != 2 {
return shim.Error("update data operation expected 2 parameters! ")
}
var datas map[string]interface{}
if err := json.Unmarshal([]byte(args[1]), &datas); err != nil {
return shim.Error(fmt.Sprintf("%s table parameters Unmarshal fail,put string not json array, err:%s", args[0], err))
}
res, err := updateStoreData(args[0],datas,stub)
if err != nil {
return shim.Error(fmt.Sprintf("put function err: %s", err))
}
return shim.Success([]byte("gxhcc invoke successful:" + res))
}
func getApi(args []string, stub shim.ChaincodeStubInterface)pb.Response{
if len(args) != 2 {
return shim.Error("get data operation expected 2 parameters to function get!")
}
var datas map[string]interface{}
if err := json.Unmarshal([]byte(args[1]), &datas); err != nil {
return shim.Error(fmt.Sprintf("%s table parameters Unmarshal fail,put string not json array, err:%s", args[0], err))
}
res, err := get(args[0],datas,stub)
if err != nil {
return shim.Error(fmt.Sprintf("put function err: %s", err))
}
return shim.Success([]byte(res))
}
func getCertNameApi(stub shim.ChaincodeStubInterface)pb.Response{
res,err := getCertificateCommonName(stub)
if err != nil {
return shim.Error(fmt.Sprintf("get certificate common_name fail,err: %s", err))
}
return shim.Success([]byte("current user certificate common_name is:" + res))
}
func SchemaProcess(paths,args []string, stub shim.ChaincodeStubInterface) pb.Response {
switch paths[0] {
case "put":
return schemaPutApi(args, stub)
case "update":
return schemaUpdateApi(args, stub)
case "get":
return schemaGetApi(args, stub)
default:
return shim.Error(fmt.Sprintf("Unsupported schema function of %s", paths[0]))
}
}
/*
put
args 字段说明:
1:args[0]代表我们具体操作的表,
2:args[1:]后面的数据表示要记录到数据库的数据,每一个string 必须是json字符串,并且需要每一个json 字符串都必须包含id 字段
我们可以发现json字符串都被我们解析成了map[string]interface{}类型的map,其中key代表表模板的字段,interface可以是一个结构,我们当前将他看做我们表模板字段的初始值。
伪代码:
1:在创建schema data 时,我们必须检查金额字段的类型必须是float64,并且不能为负数。
*/
func schemaPutApi(args []string, stub shim.ChaincodeStubInterface)pb.Response{
if len(args) != 2 {
return shim.Error("Schema put operation expected 2 parameters!")
}
schema, err := NewSchema(args[1])
if err != nil {
return shim.Error("The parameters Unmarshal to a Schema structural fail,err: "+ err.Error())
}
result,err := schemaPut(args[0],schema,stub)
if err != nil{
return shim.Error(err.Error())
}
return shim.Success([]byte(result))
}
func schemaUpdateApi(args []string, stub shim.ChaincodeStubInterface)pb.Response{
if len(args) != 2 {
return shim.Error("Schema update operation expected 2 parameters!")
}
schema, err := NewSchema(args[1])
if err != nil {
return shim.Error("The parameters Unmarshal to a Schema structural fail,err: "+ err.Error())
}
result,err := schemaUpdate(args[0],schema,stub)
if err != nil{
return shim.Error(err.Error())
}
return shim.Success([]byte(result))
}
func schemaGetApi(args []string, stub shim.ChaincodeStubInterface)pb.Response{
if len(args) != 1 {
return shim.Error("Schema get operation expected 1 parameters!")
}
result,err := schemaGet(args[0],stub)
if err != nil{
return shim.Error(err.Error())
}
return shim.Success([]byte(result))
}
func schemaPut(schemaName string, schema *Schema,stub shim.ChaincodeStubInterface) (string, error) {
_, ok := schema.StorageFields["id"]
if !ok {
return "", fmt.Errorf("The id field must exist ")
}
_, ok = schema.StorageFields["common_name"]
if !ok {
return "", fmt.Errorf("The common_name field must exist ")
}
CompositeKey, err := stub.CreateCompositeKey(GxhSchema, []string{schemaName})
if err != nil {
return "", fmt.Errorf("the schema %s create comosite key fail,err : %s",schemaName, err)
}
if schemaCache.Get(schemaName) != nil {
return "", fmt.Errorf("the schema %s already exists and cannot be added", schemaName)
} else if value, _ := getBytes(CompositeKey,stub); value != nil {
return "", fmt.Errorf("the schema %s already exists and cannot be added", schemaName)
}
err = putState(CompositeKey, schema,stub)
if err != nil {
return "", fmt.Errorf("Schema PutState fail,err: %s ", err)
}
//schemaCache.Put(args[0], schema)
return fmt.Sprintf("%s schema put success!", schemaName), nil
}
/*
if update Schema 那么我们没有办法比较旧有的一个模板,
Schema 的 update,不支持部分修改,因为存在增加和删除某些字段的情况。
初版暂时只允许修改存储数据,金额字段暂时不允许修改
*/
func schemaUpdate(schemaName string, schema *Schema,stub shim.ChaincodeStubInterface) (string, error) {
schemaOld := &Schema{}
var err error
_, ok := schema.StorageFields["id"]
if !ok {
return "", fmt.Errorf("The id field must exist ")
}
_, ok = schema.StorageFields["common_name"]
if !ok {
return "", fmt.Errorf("The common_name field must exist ")
}
CompositeKey, err := stub.CreateCompositeKey(GxhSchema, []string{schemaName})
if err != nil {
return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", schemaName, err)
}
schemaOld,err = getSchema(schemaName, stub)
if err != nil {
return "", err
}
commonName, err := getCertificateCommonName(stub)
if err != nil {
return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
}
if err := schema.WriteCheck(commonName, ""); err != nil {
return "", fmt.Errorf("update %s schema fail,err: %s ", schemaName, err)
}
schema.LeadgerFields = schemaOld.LeadgerFields
err = putState(CompositeKey,schema,stub)
if err != nil {
return "", fmt.Errorf("%s schema data PutState fail,please try again ",schemaName)
}
return fmt.Sprintf("%s schema update success!", schemaName), err
}
func getSchema(name string, stub shim.ChaincodeStubInterface) (*Schema,error) {
schema := &Schema{}
if schema = schemaCache.Get(name); schema == nil {
CompositeKey, err := stub.CreateCompositeKey(GxhSchema, []string{name})
if err != nil {
return nil,fmt.Errorf("the schema %s create comosite key fail,err : %s", name, err)
}
ok, err := getObject(CompositeKey,schema,stub)
if !ok {
return nil,fmt.Errorf("%s schema data doesn't exist,please check your parameters ", name)
}
schemaCache.Put(name, schema)
}
return schema,nil
}
func schemaGet(args string, stub shim.ChaincodeStubInterface) (string, error) {
schema := &Schema{}
var result []byte
if schema = schemaCache.Get(args); schema == nil {
CompositeKey, err := stub.CreateCompositeKey(GxhSchema, []string{args})
if err != nil {
return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args, err)
}
bool, err := getObject(CompositeKey,schema,stub)
if err != nil {
return "",err
}
if !bool {
return "", fmt.Errorf("%s schema data doesn't exist,please check your parameters ", args)
}
schemaCache.Put(args, schema)
}
commonName, err := getCertificateCommonName(stub)
if err != nil {
return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
}
err = schema.WriteCheck( commonName, "")
if err != nil {
return "", err
}
result, _ = json.Marshal(schema)
return string(result), nil
}
/*
将字段根据账本数据,与存储数据分开
leadgers:参数表示我们需要在账本数据包含的字段,这些字段不属于账本数据。
*/
func separateFields(schema *Schema, checkmap map[string]interface{}, leadgers []string) (storagemap, leadgermap map[string]interface{}) {
storagemap = make(map[string]interface{})
leadgermap = make(map[string]interface{})
for k, _ := range schema.LeadgerFields {
leadgermap[k] = checkmap[k]
}
for _, v := range leadgers {
leadgermap[v] = checkmap[v]
}
for k, _ := range schema.StorageFields {
storagemap[k] = checkmap[k]
}
return
}
/*
重新赋值,并检查相应的格式是否正确
*/
func Deassign(upMap, result map[string]interface{}) error {
if len(upMap) > len(result) {
return fmt.Errorf("Deassign fail,reassigned data length greater than the original data length! ")
}
for k, v := range upMap {
if resultV, ok := result[k]; ok {
if resultMap, resultok := resultV.(map[string]interface{}); resultok {
if vMap, ok := v.(map[string]interface{}); !ok {
return fmt.Errorf("Deassign fail, format doesn't match! ")
} else {
Deassign(vMap, resultMap)
}
} else {
result[k] = v
}
} else {
return fmt.Errorf("Deassign fail %s key nonentity ", k)
}
}
return nil
}
func getMap(key string, stub shim.ChaincodeStubInterface) (map[string]interface{}, error) {
var resultmap map[string]interface{}
result, err := stub.GetState(key)
if err != nil {
return nil, fmt.Errorf("GetState %s data fail,err %s ", key, err)
}
if result == nil {
return nil, nil
}
err = json.Unmarshal(result, &resultmap)
if err != nil {
return nil, fmt.Errorf("json unmarshal leadger map fail,err: %s", err)
}
return resultmap, nil
}
func getState(key string, stub shim.ChaincodeStubInterface) (map[string]interface{}, error) {
var resultmap map[string]interface{}
result, err := stub.GetState(key)
if err != nil {
return nil, fmt.Errorf("GetState %s data fail,err %s ", key, err)
}
if result == nil {
return nil, nil
}
err = json.Unmarshal(result, &resultmap)
if err != nil {
return nil, fmt.Errorf("json unmarshal leadger map fail,err: %s", err)
}
return resultmap, nil
}
func getObject(key string, value interface{}, stub shim.ChaincodeStubInterface)( bool,error){
result, err := stub.GetState(key)
if err != nil {
return false,fmt.Errorf("GetState %s data fail,err %s ", key, err)
}
if result == nil {
return false,nil
}
err = json.Unmarshal(result, value)
if err != nil {
return false,fmt.Errorf("json unmarshal leadger map fail,err: %s", err)
}
return true,nil
}
func getBytes(key string, stub shim.ChaincodeStubInterface) ([]byte, error) {
result, err := stub.GetState(key)
if err != nil {
return nil, fmt.Errorf("GetState %s data fail,err %s ", key, err)
}
return result, nil
}
/*
不要进行[]byte 的marshal,
*/
func putState(key string, value interface{}, stub shim.ChaincodeStubInterface) error {
valueByte, err := json.Marshal(value)
if err != nil {
return fmt.Errorf(" %s json marshal data fail,err: %s", key, err)
}
err = stub.PutState(key, valueByte)
if err != nil {
return fmt.Errorf("putState %s data fail,err: %s", key, err)
}
return nil
}
/*
不要进行[]byte 的marshal,
*/
func putStateByte(key string, value []byte, stub shim.ChaincodeStubInterface) error {
err := stub.PutState(key, value)
if err != nil {
return fmt.Errorf("putState %s data fail,err: %s", key, err)
}
return nil
}
func getCertificateCommonName(stub shim.ChaincodeStubInterface) (string, error) {
return "Admin@org2.example.com", nil
creatorByte, _ := stub.GetCreator()
certStart := bytes.IndexAny(creatorByte, "-----BEGIN")
if certStart == -1 {
return "", fmt.Errorf("No certificate found ")
}
certText := creatorByte[certStart:]
bl, _ := pem.Decode(certText)
if bl == nil {
return "", fmt.Errorf("Could not decode the PEM structure ")
}
cert, err := x509.ParseCertificate(bl.Bytes)
if err != nil {
return "", fmt.Errorf("ParseCertificate failed")
}
return cert.Subject.CommonName, nil
}
func Decimal(value float64) float64 {
value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
return value
}
func Constructor(capacity int) LRUCache {
lruCache := LRUCache{limit: capacity}
lruCache.HashMap = make(map[string]*Node, capacity)
return lruCache
}
func (l *LRUCache) Get(key string) *Schema {
if v, ok := l.HashMap[key]; ok {
l.refreshNode(v)
return v.Value
} else {
return nil
}
}
func (l *LRUCache) Put(key string, value *Schema) error {
if v, ok := l.HashMap[key]; !ok {
if len(l.HashMap) >= l.limit {
oldKey := l.removeNode(l.head)
delete(l.HashMap, oldKey)
}
node := Node{Key: key, Value: value}
l.addNode(&node)
l.HashMap[key] = &node
} else {
v.Value = value
l.refreshNode(v)
}
return nil
}
func (l *LRUCache) refreshNode(node *Node) {
if node == l.end {
return
}
l.removeNode(node)
l.addNode(node)
}
func (l *LRUCache) removeNode(node *Node) string {
if node == l.end {
l.end = l.end.pre
l.end.next = nil
} else if node == l.head {
l.head = l.head.next
l.head.pre = nil
} else {
node.pre.next = node.next
node.next.pre = node.pre
}
return node.Key
}
func (l *LRUCache) addNode(node *Node) {
if l.end != nil {
l.end.next = node
node.pre = l.end
node.next = nil
}
l.end = node
if l.head == nil {
l.head = node
}
}
func dividecalc(bint *big.Int, divide float64) (*big.Int, error) {
divide *= 1000000
value := new(big.Int).Mul(bint, big.NewInt(int64(divide)))
value.Div(value, big.NewInt(1000000))
return value, nil
}
// "/" -> []
// "/admin" -> ["admin"]
// "/admin/" -> ["admin"]
// "/admin/users" -> ["admin", "users"]
func splitPath(key string) []string {
key = strings.Trim(key, "/ ")
if key == "" {
return []string{}
}
return strings.Split(key, "/")
}
func main() {
err := shim.Start(&GXHCC{})
if err != nil {
fmt.Printf("Error starting EncCC chaincode: %s", err)
}
}
package main
import (
"encoding/json"
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
"reflect"
"testing"
)
var (
SchemaNew = `{"leadger_fields":{"abail":{"val":"0001-01-01T00:00:00Z","auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1584936259}},"issue":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},
"extrate":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"transfer":{"users":null,"roles":null}},
"fcheck":{"ftype":"big.int","must":false,"fieldlen":1}},"sabail":{"val":"0001-01-01T00:00:00Z","auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"issue":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1584936259}},"extrate":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},
"transfer":{"users":null,"roles":null}},"fcheck":null}},"storage_fields":{"common_name":{"val":"1","auth":{"read":{"users":null,"roles":null},
"write":{"users":null,"roles":null}},"fcheck":null},"alinkman":{"val":10.34,"auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"write":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1584936259}}},"fcheck":{"ftype":"float64","must":true,"fieldlen":1}},"amob":{"val":"0001-01-01T00:00:00Z",
"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"write":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}},"fcheck":{"ftype":"time.Time","must":true,"fieldlen":0}},
"aname":{"val":"Aname","auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"write":
{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}},"fcheck":{"ftype":"string","must":true,"fieldlen":16}},
"atype":{"val":100,"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"write":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}},"fcheck":{"ftype":"int","must":true,"fieldlen":1}},"backup":
{"val":{"aname":"Aname","atype":"Atype"},"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},
"write":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}},"fcheck":null},"id":{"val":"1","auth":{"read":
{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":null}},"schema_auth":{"read":{"users":null,"roles":null},
"write":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":0}}},"auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":0}},"write":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":0}}}}`
merSchema = `{"leadger_fields":{"regular":{"val":6000,"auth":{"read":{"users":null,"roles":null},"issue":{"users":null,"roles":null},"extrate":{"users":null,"roles":null},"transfer":{"users":null,
"roles":null}},"fcheck":{"ftype":"big.int","must":false,"fieldlen":6}},"rregular":{"val":6000,"auth":{"read":{"users":null,"roles":null},"issue":{"users":null,"roles":null},"extrate":{"users":null,"roles"
:null},"transfer":{"users":null,"roles":null}},"fcheck":{"ftype":"big.int","must":false,"fieldlen":6}}},"storage_fields":{"common_name":{"val":"1","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":null},
"acid":{"val":3,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles"
:null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"actionid":{"val":1,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,
"fieldlen":6}},"adiscounts":{"val":"0.8","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"aid":{"val":0,"auth":{"read":
{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"are":{"val":1,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":
null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"backup":{"val":{},"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":null},"cid":{"val":0,"auth":{"read":
{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"cosperson":{"val":100,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,
"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"did":{"val":2,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,
"fieldlen":6}},"dineraprice":{"val":80,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"dinerprice":{"val":100,"auth":
{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"dinersprice":{"val":90,"auth":{"read":{"users":null,"roles":null},"write":
{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"distype":{"val":16,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":
"float64","must":false,"fieldlen":6}},"esign":{"val":"2010-12-31 15:38:54","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}}
,"fid":{"val":4,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"firrenew":{"val":"2010-01-02 15:38:54","auth":{"read":
{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"haver":{"val":1,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"id":{"val":"1","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":false,"fieldlen":6}},"indate":{"val":"2018/10/29 16:46:57","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"ischain":{"val":1,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"isset":{"val":1,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"issnp":{"val":1,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"keywords":{"val":"test","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"licence":{"val":"103451015521","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"linedate":{"val":"2010-01-02 15:38:54","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"mact":{"val":"123456","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"mactname":{"val":"联系人1","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"maddr":{"val":"测试地址1","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"marea":{"val":1,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"mbtype":{"val":1,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"mdiposit":{"val":"中国银行","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"mlinkman":{"val":"联系人1","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"mlinkmob":{"val":"18555555555","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"mname":{"val":"测试连锁店1","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"mno":{"val":"59118600000005","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"mno2":{"val":"05910005","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"msubtype":{"val":10,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"mtype":{"val":9,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"murl":{"val":"http://www.baidu.com","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"ordertel":{"val":"13444444444","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"paystatue":{"val":1,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"perquisites":{"val":3,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"persales":{"val":100,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"pname":{"val":"8820180008552970","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"ppass":{"val":"152820","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"relevel":{"val":5,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"retype":{"val":0,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"sdiscounts":{"val":"0.85","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"shophours":{"val":"24小时营业","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"sregular":{"val":6000,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"ssign":{"val":"2010-01-01 15:38:54","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"string","must":true,"fieldlen":160}},"statue":{"val":0,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"supperaprice":{"val":90,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"supperprice":{"val":120,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"suppersprice":{"val":110,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"tstatue":{"val":1,"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}},"warmline":{"val":"600","auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":{"ftype":"float64","must":false,"fieldlen":6}}},"schema_auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}},"auth":{"read":{"users":null,"roles":null},"write":{"users":null,"roles":null}}}
`
merarrary = `[{
"id": "1",
"mname": "测试连锁店1",
"maddr": "测试地址1",
"mlinkman": "联系人1",
"mlinkmob": "18555555555",
"mtype": 9,
"mact": "123456",
"mdiposit": "中国银行",
"mactname": "联系人1",
"licence": "103451015521",
"murl": "http://www.baidu.com",
"mno": "59118600000005",
"mno2": "05910005",
"indate": "2018/10/29 16:46:57",
"aid": 0,
"regular": "60000000",
"adiscounts": 0.8,
"sdiscounts": 0.85,
"distype": 16,
"msubtype": 10,
"ischain": 1,
"cosperson": 100,
"statue": 0,
"retype": 0,
"did": 2,
"warmline": 600,
"cid": 0,
"sregular": 60000000,
"keywords": "test",
"paystatue": 1,
"are": 1,
"marea": 1,
"actionid": 1,
"tstatue": 1,
"rregular": "60000000",
"ssign": "2010-01-01 15:38:54",
"firrenew": "2010-01-02 15:38:54",
"ordertel": "13444444444",
"shophours": "24小时营业",
"persales": 100,
"linedate": "2010-01-02 15:38:54",
"issnp": 1,
"esign": "2010-12-31 15:38:54",
"fid": 4,
"acid": 3,
"pname": "8820180008552970",
"ppass": "152820",
"isset": 1,
"haver": 1,
"dinerprice": 100,
"dinersprice": 90,
"dineraprice": 80,
"supperprice": 120,
"suppersprice": 110,
"supperaprice": 90,
"common_name":"",
"perquisites": 3,
"relevel": 5,
"mbtype": 1,
"backup": {}
},{
"id": "2",
"mname": "测试连锁店1",
"maddr": "测试地址1",
"mlinkman": "联系人1",
"mlinkmob": "18555555555",
"mtype": 9,
"mact": "123456",
"mdiposit": "中国银行",
"mactname": "联系人1",
"licence": "103451015521",
"murl": "http://www.baidu.com",
"mno": "59118600000005",
"mno2": "05910005",
"indate": "2018/10/29 16:46:57",
"aid": 0,
"regular": "60000000",
"adiscounts": 0.8,
"sdiscounts": 0.85,
"distype": 16,
"msubtype": 10,
"ischain": 1,
"cosperson": 100,
"statue": 0,
"retype": 0,
"did": 2,
"warmline": 600,
"cid": 0,
"sregular": 6000,
"keywords": "test",
"paystatue": 1,
"are": 1,
"marea": 1,
"actionid": 1,
"tstatue": 1,
"rregular": "60000000",
"ssign": "2010-01-01 15:38:54",
"firrenew": "2010-01-02 15:38:54",
"ordertel": "13444444444",
"shophours": "24小时营业",
"persales": 100,
"linedate": "2010-01-02 15:38:54",
"issnp": 1,
"esign": "2010-12-31 15:38:54",
"fid": 4,
"acid": 3,
"pname": "8820180008552970",
"ppass": "152820",
"isset": 1,
"haver": 1,
"dinerprice": 100,
"dinersprice": 90,
"dineraprice": 80,
"supperprice": 120,
"suppersprice": 110,
"supperaprice": 90,
"common_name":"",
"perquisites": 3,
"relevel": 5,
"mbtype": 1,
"backup": {}
}]`
SchemaPutNew = `{"leadger_fields":{},"storage_fields":{"common_name":{"val":"1","auth":{"read":{"users":null,"roles":null},
"write":{"users":null,"roles":null}},"fcheck":null},"alinkman":{"val":10.34,"auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"write":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1584936259}}},"fcheck":{"ftype":"float64","must":true,"fieldlen":1}},"amob":{"val":"0001-01-01T00:00:00Z",
"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"write":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}},"fcheck":{"ftype":"time.Time","must":true,"fieldlen":0}},
"aname":{"val":"Aname","auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"write":
{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}},"fcheck":{"ftype":"string","must":true,"fieldlen":16}},
"atype":{"val":100,"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"write":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}},"fcheck":{"ftype":"int","must":true,"fieldlen":1}},"backup":
{"val":{"aname":"Aname","atype":"Atype"},"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},
"write":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}},"fcheck":null},"id":{"val":"1","auth":{"read":
{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":null}},"schema_auth":{"read":{"users":null,"roles":null},
"write":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":0}}},"auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":0}},"write":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":0}}}}`
SchemaUpdate = `{"leadger_fields":{"abail22":{"val":"0","auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1584936259}},"issue":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},
"extrate":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"transfer":{"users":null,"roles":null}},
"fcheck":{"ftype":"big.int","must":true,"fieldlen":1}},"sabail":{"val":"0001-01-01T00:00:00Z","auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"issue":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1584936259}},"extrate":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},
"transfer":{"users":null,"roles":null}},"fcheck":null}},"storage_fields":{"common_name":{"val":"1","auth":{"read":{"users":null,"roles":null},
"write":{"users":null,"roles":null}},"fcheck":null},"alinkmanNew":{"val":10.34,"auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"write":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1584936259}}},"fcheck":{"ftype":"float64","must":true,"fieldlen":1}},"amob":{"val":"0001-01-01T00:00:00Z",
"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"write":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}},"fcheck":{"ftype":"time.Time","must":true,"fieldlen":0}},
"aname":{"val":"Aname","auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"write":
{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}},"fcheck":{"ftype":"string","must":true,"fieldlen":6}},
"atype":{"val":100,"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},"write":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}},"fcheck":{"ftype":"int","must":true,"fieldlen":1}},"backup":
{"val":{"aname":"Aname","atype":"Atype"},"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}},
"write":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1584936259}}},"fcheck":null},"id":{"val":"1","auth":{"read":
{"users":null,"roles":null},"write":{"users":null,"roles":null}},"fcheck":null}},"schema_auth":{"read":{"users":null,"roles":null},
"write":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":0}}},"auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":0}},"write":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":0}}}}`
)
func TestGXHSchemaPut(t *testing.T){
cc := new(GXHCC)
stub := shim.NewMockStub("GXHCC",cc)
stub.MockInit("init",nil)
fmt.Println("========================================invoke schema put============================================")
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(SchemaNew)})
fmt.Printf("Invoke status %d,message %s and payload %s\n",
responseByPutschema.Status,responseByPutschema.Message,string(responseByPutschema.Payload))
fmt.Println()
fmt.Println("========================================invoke schema get============================================")
responseByget := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("get"),[]byte("alibusi")})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget.Status,responseByget.Message,string(responseByget.Payload))
fmt.Println()
fmt.Println("========================================invoke schema update============================================")
responseByupdate := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("update"),[]byte("alibusi"),[]byte(SchemaUpdate)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByupdate.Status,responseByupdate.Message,string(responseByupdate.Payload))
fmt.Println("========================================invoke schema get============================================")
responseByget2 := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("get"),[]byte("alibusi")})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget2.Status,responseByget2.Message,string(responseByget2.Payload))
fmt.Println()
}
func TestGXHCreateAccount(t *testing.T){
cc := new(GXHCC)
stub := shim.NewMockStub("GXHCC",cc)
stub.MockInit("init",nil)
fmt.Println()
fmt.Println("========================================invoke schema put============================================")
fmt.Println()
fmt.Println()
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(SchemaNew)})
fmt.Printf("Invoke status %d,message %s and payload %s\n",
responseByPutschema.Status,responseByPutschema.Message,string(responseByPutschema.Payload))
fmt.Println()
fmt.Println("========================================invoke createAccount============================================")
fmt.Println()
fmt.Println()
responseBycreate := stub.MockInvoke("invoke1",[][]byte{[]byte("createAccount"), []byte("alibusi"),[]byte(inputarrary)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseBycreate.Status,responseBycreate.Message,string(responseBycreate.Payload))
fmt.Println()
fmt.Println()
fmt.Println("========================================invoke updateStoreData============================================")
fmt.Println()
fmt.Println()
responseByputData := stub.MockInvoke("invoke1",[][]byte{[]byte("upStoreData"), []byte("alibusi"),[]byte(inputUpdate)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByputData.Status,responseByputData.Message,string(responseByputData.Payload))
fmt.Println()
fmt.Println()
fmt.Println("========================================invoke get============================================")
fmt.Println()
fmt.Println()
responseByget := stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("alibusi"),[]byte(inputUpdate)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget.Status,responseByget.Message,string(responseByget.Payload))
}
func TestGXHPutData(t *testing.T){
cc := new(GXHCC)
stub := shim.NewMockStub("GXHCC",cc)
stub.MockInit("init",nil)
fmt.Println()
fmt.Println("========================================invoke schema put============================================")
fmt.Println()
fmt.Println()
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(SchemaPutNew)})
fmt.Printf("Invoke status %d,message %s and payload %s\n",
responseByPutschema.Status,responseByPutschema.Message,string(responseByPutschema.Payload))
fmt.Println()
fmt.Println("========================================invoke putData============================================")
fmt.Println()
fmt.Println()
responseByputData := stub.MockInvoke("invoke1",[][]byte{[]byte("putData"), []byte("alibusi"),[]byte(inputPutarray)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByputData.Status,responseByputData.Message,string(responseByputData.Payload))
fmt.Println()
}
var (
issueTx = `{"account_type":"alibusi","account_id":"1","action_amount":"1230","fund_type":"abail","back_up":{"account_type":"","account_id":"","action_amount":0,"fund_type":"","back_up":null}}`
extract = `{"account_type":"alibusi","account_id":"1","action_amount":"123","fund_type":"abail","back_up":{"account_type":"","account_id":"","action_amount":0,"fund_type":"","back_up":null}}`
commontx = `{"sender_account":"alibusi","sender_id":"1","sender_funt":"abail","receiver_account":"alibusi","receiver_account_id":"2","receiver_funt":"abail","amount":"223"}`
merTx = `{"mid":"1","bid":"1","tamount":"18050100","treposit":"16988320","bereposit":"60000000","afreposit":"43011700","feerate":0.0055,"fee":"99275","oamount":"21235400","adiscounts":0.8,"sdiscounts":0.85,"nodisamount":"0","disamount":"0","perquisites":"0"}
`
)
func TestGXHIssueandExtract(t *testing.T){
cc := new(GXHCC)
stub := shim.NewMockStub("GXHCC",cc)
stub.MockInit("init",nil)
fmt.Println()
fmt.Println("========================================invoke schema put============================================")
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(SchemaNew)})
if responseByPutschema.Status != 200{
t.Errorf("schema init fail,err: %s",responseByPutschema.Message)
}
fmt.Println()
responseBycreate := stub.MockInvoke("invoke1",[][]byte{[]byte("createAccount"), []byte("alibusi"),[]byte(inputarrary)})
if responseBycreate.Status != 200{
t.Errorf("createAccount init fail,err: %s",responseBycreate.Message)
}
fmt.Println()
responseByIssue := stub.MockInvoke("invoke1",[][]byte{[]byte("createTx"), []byte("issue"),[]byte(issueTx)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByIssue.Status,responseByIssue.Message,string(responseByIssue.Payload))
fmt.Println()
responseByextract := stub.MockInvoke("invoke1",[][]byte{[]byte("createTx"), []byte("extract"),[]byte(extract)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByextract.Status,responseByextract.Message,string(responseByextract.Payload))
fmt.Println()
fmt.Println()
responseBytx := stub.MockInvoke("invoke1",[][]byte{[]byte("createTx"), []byte("transfer"),[]byte("commontx"),[]byte(commontx)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseBytx.Status,responseBytx.Message,string(responseBytx.Payload))
fmt.Println()
responseByget := stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("alibusi"),[]byte(`{"id":"1"}`)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget.Status,responseByget.Message,string(responseByget.Payload))
responseByget2 := stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("alibusi"),[]byte(`{"id":"2"}`)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget2.Status,responseByget2.Message,string(responseByget2.Payload))
}
/*
测试商户交易
*/
//736288 590270 620798
func TestGXHmerTx(t *testing.T){
stub := GXHmerTxinit()
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("createTx"), []byte("transfer"),[]byte("merchants"),[]byte(merTx)})
if responseByPutschema.Status != 200{
fmt.Printf("schema init fail,err: %s",responseByPutschema.Message)
}
responseByget2 := stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("merchants"),[]byte(`{"id":"1"}`)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget2.Status,responseByget2.Message,string(responseByget2.Payload))
responseByget := stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("alibusi"),[]byte(`{"id":"1"}`)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget.Status,responseByget.Message,string(responseByget.Payload))
}
func GXHmerTxinit()*shim.MockStub{
cc := new(GXHCC)
stub := shim.NewMockStub("GXHCC",cc)
stub.MockInit("init",nil)
fmt.Println()
fmt.Println("========================================invoke schema put============================================")
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(SchemaNew)})
if responseByPutschema.Status != 200{
fmt.Printf("schema put alibusi fail,err: %s",responseByPutschema.Message)
return stub
}
responseBycreate := stub.MockInvoke("invoke1",[][]byte{[]byte("createAccount"), []byte("alibusi"),[]byte(inputarrary)})
if responseBycreate.Status != 200{
fmt.Printf("createAccount alibusi fail,err: %s",responseBycreate.Message)
return stub
}
fmt.Println()
fmt.Println()
fmt.Println("========================================invoke schema put============================================")
responseByMerschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("merchants"),[]byte(merSchema)})
if responseByMerschema.Status != 200{
fmt.Printf("schema put merchants fail,err: %s",responseByMerschema.Message)
return stub
}
responseBycreateMer := stub.MockInvoke("invoke1",[][]byte{[]byte("createAccount"), []byte("merchants"),[]byte(merarrary)})
if responseBycreateMer.Status != 200{
fmt.Printf("createAccount merchants fail,err: %s",responseBycreateMer.Message)
return stub
}
return stub
}
func TestDeassign(t *testing.T) {
var m map[string]interface{}
err := json.Unmarshal([]byte(commontx),&m)
if err != nil{
t.Errorf(err.Error())
}
onwer,_ := m["sender_account"].(float64)
//fmt.Println(ok)
fmt.Println(onwer == 0)
}
//5958 5242 5600 5909
func BenchmarkBackUpCheck(b *testing.B) {
var m map[string]interface{}
err := json.Unmarshal([]byte(commontx),&m)
if err != nil{
fmt.Println(err.Error())
return
}
for i:=0;i<b.N ;i++ {
fmt.Println( reflect.DeepEqual(m["sender_account"] , m["receiver_account"]))
}
}
package main
import (
"encoding/json"
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
"math/big"
"strings"
"testing"
)
var schema = `{"fields":{"alinkman":{"val":"Alinkman","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}},"amob":{"val":"Amob","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}},"aname":{"val":"Aname","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}},"atype":{"val":"Atype","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}},"backup":{"val":{"aname":"Aname","atype":"Atype"},"auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":
{"admin":0},"roles":{"admin":1582972202}}}},"id":{"val":"1","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}}},"schema_auth":{"read":{"users":null,"roles":null},"write":{"users":{"admin":0},"roles":{"admin":0}}},"auth":{"read":{"users":
{"admin":0},"roles":{"admin":0}},"write":{"users":{"admin":0},"roles":{"admin":1582972202}}}}
`
var schema2 = `{"fields":{"alinkman":{"val":"Alinkman","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}},"amob":{"val":"Amob","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}},"aname":{"val":"Aname","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}},"atype":{"val":"Atype","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}},"backup":{"val":{"aname":"Aname","atype":"Atype"},"auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":
{"admin":0},"roles":{"admin":1582972202}}}},"id":{"val":"1","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}}},"schema_auth":{"read":{"users":null,"roles":null},"write":{"users":{"admin":0},"roles":{"admin":1582972202}}},"auth":{"read":{"users":
{"admin":0},"roles":{"admin":0}},"write":{"users":{"admin":0},"roles":{"admin":0}}}}
`
var schema3 = `{"fields":{"alinkman":{"val":"Alinkman","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}},"amob":{"val":"Amob","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}},"aname":{"val":"Aname","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}},"atype":{"val":"Atype","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}},"backup":{"val":{"aname":"Aname","atype":"Atype"},"auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":
{"admin":0},"roles":{"admin":1582972202}}}},"id":{"val":"1","auth":{"read":{"users":{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":
{"admin":1582972202}}}}},"schema_auth":{"read":{"users":null,"roles":null},"write":{"users":{"admin":0},"roles":{"admin":1582972202}}},"auth":{"read":{"users":
{"admin":0},"roles":{"admin":1582972202}},"write":{"users":{"admin":0},"roles":{"admin":0}}}}
`
/*
以下部分是增加权限内容的测试
*/
var (
inputUpdate = `{"id":"1","aname":"alibusi","atype":100,"alinkman":10.34,"amob":"2006-01-02 15:04:05","backup":
{"aname":"alibusi","atype":"type"}}`
inputarrary = `[{"abail":"0","sabail":"0","id":"1","aname":"alibusi","atype":100,"alinkman":10.34,"amob":"2006-01-02 15:04:05","backup":
{"aname":"alibusi","atype":"type"},"common_name":"admin"},{"abail":"0","sabail":"0","id":"2","aname":"alibusi","atype":100,"alinkman":
10.34,"amob":"2006-01-02 15:04:05","backup":{"aname":"alibusi","atype":"type"},"common_name":"admin"}]`
inputPutarray = `[{"id":"1","aname":"alibusi","atype":100,"alinkman":10.34,"amob":"2006-01-02 15:04:05","backup":{"aname":"alibusi",
"atype":"type"},"common_name":"admin"},{"id":"2","aname":"alibusi","atype":100,"alinkman":10.34,"amob":"2006-01-02 15:04:05","backup":
{"aname":"alibusi","atype":"type"},"common_name":"admin"}]`
)
func TestGXHSchemaAuth(t *testing.T){
cc := new(GXHCC)
stub := shim.NewMockStub("GXHCC",cc)
stub.MockInit("init",nil)
fmt.Println()
fmt.Println("========================================invoke schema put============================================")
fmt.Println()
fmt.Println()
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(schema)})
fmt.Printf("Invoke status %d,message %s and payload %s\n",
responseByPutschema.Status,responseByPutschema.Message,string(responseByPutschema.Payload))
fmt.Println()
fmt.Println("========================================invoke schema get============================================")
fmt.Println()
fmt.Println()
responseByget := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("get"),[]byte("alibusi")})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget.Status,responseByget.Message,string(responseByget.Payload))
fmt.Println()
fmt.Println("========================================invoke schema update============================================")
fmt.Println()
fmt.Println()
responseByupdate := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("update"),[]byte("alibusi"),[]byte(schema)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByupdate.Status,responseByupdate.Message,string(responseByupdate.Payload))
}
/*
测试使用table 数据构建 schema
*/
func TestGXHSchemaAuthBytable(t *testing.T){
cc := new(GXHCC)
stub := shim.NewMockStub("GXHCC",cc)
stub.MockInit("init",nil)
fmt.Println()
fmt.Println("========================================invoke schema put============================================")
fmt.Println()
fmt.Println()
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(inputUpdate)})
fmt.Printf("Invoke status %d,message %s and payload %s\n",
responseByPutschema.Status,responseByPutschema.Message,string(responseByPutschema.Payload))
fmt.Println()
fmt.Println("========================================invoke schema get============================================")
fmt.Println()
fmt.Println()
responseByget := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("get"),[]byte("alibusi")})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget.Status,responseByget.Message,string(responseByget.Payload))
fmt.Println()
fmt.Println("========================================invoke schema update============================================")
fmt.Println()
fmt.Println()
responseByupdate := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("update"),[]byte("alibusi"),[]byte(inputUpdate)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByupdate.Status,responseByupdate.Message,string(responseByupdate.Payload))
}
func TestGXHDataPutAuth(t *testing.T){
cc := new(GXHCC)
stub := shim.NewMockStub("GXHCC",cc)
stub.MockInit("init",nil)
fmt.Println()
fmt.Println("========================================invoke schema put============================================")
fmt.Println()
fmt.Println()
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(schema3)})
//使用schema 数据测试过期时间err,schema right data,使用schema3 测试读取字段时的过滤
fmt.Printf("Invoke status %d,message %s and payload %s\n",
responseByPutschema.Status,responseByPutschema.Message,string(responseByPutschema.Payload))
responseByget := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("get"),[]byte("alibusi")})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget.Status,responseByget.Message,string(responseByget.Payload))
fmt.Println()
fmt.Println("========================================invoke data put============================================")
fmt.Println()
fmt.Println()
responseByPut := stub.MockInvoke("invoke1",[][]byte{[]byte("put"), []byte("alibusi"),[]byte(inputarrary)})
fmt.Printf("Invoke status %d,message %s ,and payload %s\n",
responseByPut.Status,responseByPut.Message,string(responseByPut.Payload))
responseByget = stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("alibusi"),[]byte(`{"id":"1"}`)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget.Status,responseByget.Message,string(responseByget.Payload))
fmt.Println()
fmt.Println("========================================invoke data update============================================")
fmt.Println()
fmt.Println()
responseByUpdate := stub.MockInvoke("invoke1",[][]byte{[]byte("update"), []byte("alibusi"),[]byte(inputUpdate)})
fmt.Printf("Invoke status %d,message %s ,and payload %s\n",
responseByUpdate.Status,responseByUpdate.Message,string(responseByUpdate.Payload))
responseByget2 := stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("alibusi"),[]byte(`{"id":"1"}`)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget2.Status,responseByget2.Message,string(responseByget2.Payload))
}
var testData = `{"float64":10.33,"int":10,"string":"我中国人a!","time.Time":"2020-03-06 18:30:07.49752435 +0800 CST m=+0.000270574","struct":{}}`
func TestFieldCheck(t *testing.T){
var testmap map[string]interface{}
json.Unmarshal([]byte(testData),&testmap)
err := fieldCheckout(nil,testmap["struct"])
if err != nil{
t.Error(err)
}
intC := &Checks{
FType:"int",
Must:true,
Fieldlen:1,
}
err = fieldCheckout(intC,testmap["int"])
if err != nil{
t.Error(err)
}
floatC := &Checks{
FType:"float64",
Must:true,
Fieldlen:1,
}
err = fieldCheckout(floatC,testmap["float64"])
if err != nil{
t.Error(err)
}
stringC := &Checks{
FType:"string",
Must:true,
Fieldlen:6,
}
err = fieldCheckout(stringC,testmap["string"])
if err != nil{
t.Error(err)
}
timeC := &Checks{
FType:"time.Time",
Must:true,
Fieldlen:1,
}
err = fieldCheckout(timeC,testmap["time.Time"])
if err != nil{
t.Error(err)
}
}
var schemaCheck = `{"fields":{"alinkman":{"val":10.34,"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1583501961}},"write":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1583501961}}},"fcheck":{"ftype":"float64","must":true,"fieldlen":1}},
"amob":{"val":"0001-01-01T00:00:00Z","auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":
{"Admin@org2.example.com":1583501961}},"write":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":
1583501961}}},"fcheck":{"ftype":"time.Time","must":true,"fieldlen":0}},"aname":{"val":"Aname","auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}},"write":{"users":{"Admin@org2.example.com":0},
"roles":{"Admin@org2.example.com":1583501961}}},"fcheck":{"ftype":"string","must":true,"fieldlen":16}},"atype":{"val":100,
"auth":{"read":{"users":{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}},"write":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}}},"fcheck":{"ftype":"int",
"must":true,"fieldlen":1}},"backup":{"val":{"aname":"Aname","atype":"Atype"},"auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}},"write":{"users":{"Admin@org2.example.com":0},
"roles":{"Admin@org2.example.com":1583501961}}},"fcheck":null},"id":{"val":"1","auth":{"read":{"users":null,"roles":null},
"write":{"users":null,"roles":null}},"fcheck":null}},"schema_auth":{"read":{"users":null,"roles":null},"write":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":1583501961}}},"auth":{"read":{"users":
{"Admin@org2.example.com":0},"roles":{"Admin@org2.example.com":0}},"write":{"users":{"Admin@org2.example.com":0},
"roles":{"Admin@org2.example.com":0}}}}
`
var (
inputC = `{"id":"1","aname":"alibusi","atype":1000,"alinkman":1.233,
"amob":"new1234567890","backup":{"aname":"alibusi","atype":"type"}}`
inputCs = `[{
"id": "1",
"aname": "alibusi",
"atype": 102,
"alinkman": 10.34,
"amob": "0001-01-01 00:00:00 + UTC",
"backup": {
"aname": "alibusi",
"atype": "type"
}
}, {
"id": "2",
"aname": "alibusi",
"atype": 102,
"alinkman": 10.34,
"amob": "0001-01-01 00:00:00 + UTC",
"backup": {
"aname": "alibusi",
"atype": "type"
}
}]`
)
/*
本测试主要进行data put,update的测试操作,主要进行fieldcheck 的测试。
*/
func TestPut(t *testing.T){
cc := new(GXHCC)
stub := shim.NewMockStub("GXHCC",cc)
stub.MockInit("init",nil)
fmt.Println()
fmt.Println("========================================invoke schema put============================================")
fmt.Println()
fmt.Println()
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("put"),[]byte("alibusi"),[]byte(inputC)})
//使用schema 数据测试过期时间err,schema right data,使用schema3 测试读取字段时的过滤
fmt.Printf("Invoke status %d,message %s and payload %s\n",
responseByPutschema.Status,responseByPutschema.Message,string(responseByPutschema.Payload))
responseByget := stub.MockInvoke("invoke1",[][]byte{[]byte("schema"), []byte("get"),[]byte("alibusi")})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget.Status,responseByget.Message,string(responseByget.Payload))
fmt.Println()
fmt.Println("========================================invoke data put============================================")
fmt.Println()
fmt.Println()
responseByPut := stub.MockInvoke("invoke1",[][]byte{[]byte("put"), []byte("alibusi"),[]byte(inputCs)})
fmt.Printf("Invoke status %d,message %s ,and payload %s\n",
responseByPut.Status,responseByPut.Message,string(responseByPut.Payload))
responseByget = stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("alibusi"),[]byte(`{"id":"1"}`)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget.Status,responseByget.Message,string(responseByget.Payload))
fmt.Println()
fmt.Println("========================================invoke data update============================================")
fmt.Println()
fmt.Println()
responseByUpdate := stub.MockInvoke("invoke1",[][]byte{[]byte("update"), []byte("alibusi"),[]byte(inputC)})
fmt.Printf("Invoke status %d,message %s ,and payload %s\n",
responseByUpdate.Status,responseByUpdate.Message,string(responseByUpdate.Payload))
responseByget2 := stub.MockInvoke("invoke1",[][]byte{[]byte("get"), []byte("alibusi"),[]byte(`{"id":"1"}`)})
fmt.Printf("Invoke status %d,message %s ,and payload %s \n",
responseByget2.Status,responseByget2.Message,string(responseByget2.Payload))
}
func TestDivide(t *testing.T){
testInt := big.NewInt(23456789000000)
i , err := dividecalc(testInt,float64(0.0056))
if err!=nil{
t.Error(err.Error())
}
fmt.Println(i)
}
//经过测试发现使用big.int 比直接使用float64 会有2500多倍的性能损失
func BenchmarkDivide(b *testing.B) {
for i:= 0 ;i < b.N ; i++ {
//testInt := big.NewInt(23456789)
//i := dividecalctest(testInt,float64(0.0056))
//if err!=nil{
// fmt.Println("happen err",err)
// return
//}
}
//for i:= 0 ;i < b.N ; i++ {
// a := float64(23456789)
// _ , err := testfunc(a,float64(0.0056))
// if err!=nil{
// fmt.Println("happen err",err)
// return
// }
// //fmt.Println(c)
//}
}
func testfunc(a,b float64)(float64,error){
str := fmt.Sprintf("%v", b)
strs := strings.Split(str, ".")
if len(strs[1]) > 6 {
return 0, fmt.Errorf("divide can only exist to six decimal places ")
}
//var mul int64
//length := len(strs[1])
// pow(10,int64(length))
return a*b,nil
}
package main
import (
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
"testing"
)
func TestInvokeTable(t *testing.T){
cc := new(GXHCC)
stub := shim.NewMockStub("GXHCC",cc)
stub.MockInit("init",nil)
responseByPutschema := stub.MockInvoke("invoke1",[][]byte{[]byte("InvokeTable"), []byte("alibusi"),[]byte(inputC)})
fmt.Printf("Invoke status %d,message %s and payload %s\n",
responseByPutschema.Status,responseByPutschema.Message,string(responseByPutschema.Payload))
}
package main
import (
"encoding/json"
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
"math/big"
"reflect"
)
func transactionProcess(paths, args []string, stub shim.ChaincodeStubInterface) pb.Response {
switch paths[0] {
case "issue": //进行账户金额发行(无中生有)
return issueApi(args, stub)
case "extract": //提取账户金额(直接减去)
return extractApi(args, stub)
case "transfer": // 一笔普通转账
return transferApi(args, stub)
default:
return shim.Error(fmt.Sprintf("Unsupported schema function of %s", paths[0]))
}
}
func issueApi(args []string, stub shim.ChaincodeStubInterface) pb.Response {
if len(args) != 1 {
return shim.Error("issue operation expected 1 parameters ! ")
}
action := &Action{}
err := json.Unmarshal([]byte(args[0]), action)
if err != nil {
return shim.Error(fmt.Sprintf("json unmarshal Action structure fail,err: %s", err))
}
res, err := funtOperation(action, stub, true)
if err != nil {
return shim.Error(fmt.Sprintf("issue operation err: %s", err))
}
return shim.Success([]byte("extract " + res))
}
func extractApi(args []string, stub shim.ChaincodeStubInterface) pb.Response {
if len(args) != 1 {
return shim.Error("extract operation expected 1 parameters ! ")
}
action := &Action{}
err := json.Unmarshal([]byte(args[0]), action)
if err != nil {
return shim.Error(fmt.Sprintf("json unmarshal Action structure fail,err: %s", err))
}
res, err := funtOperation(action, stub, false)
if err != nil {
return shim.Error(fmt.Sprintf("extract operation err: %s", err))
}
return shim.Success([]byte("extract " + res))
}
func transferApi(args []string, stub shim.ChaincodeStubInterface) pb.Response {
txFunc := transferType[args[0]]
if txFunc == nil {
return shim.Error(fmt.Sprintf("No matching transfer operation method was found ! "))
}
err := txFunc(args[1:], stub)
if err != nil {
return shim.Error(fmt.Sprintf("%s transfer operation fail,err:%s ", args[0], err))
}
return pb.Response{}
}
/*
账户金额发现,核心是在对应的schema 找到有发行的权利。
1:金额字段也就是(账本字段数据)都有发行标示
2:发行交易可以存在多个字段,但只要保证我们要求的字段存在就可以。账户类型,Id,发行金额(大于0)
*/
func funtOperation(action *Action, stub shim.ChaincodeStubInterface, isIssue bool) (string, error) {
commonName, err := getCertificateCommonName(stub)
if err != nil {
return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
}
schema := &Schema{}
schema, err = getSchema(action.AccountType, stub)
if err != nil {
return "", err
}
leadgerKey := LeadgerPrefix + "_" + action.AccountType + "_" + action.AccountId
leadgermap, err := getState(leadgerKey, stub)
if err != nil {
return "", err
}
onwer, ok := leadgermap["common_name"].(string)
if isIssue {
err := schema.AuthorityCheck(schema.LeadgerFields[action.FundType].PAuth.Issue, commonName, onwer)
if err != nil {
return "", fmt.Errorf("%s field issue permission check does not match, err: %s ", action.FundType, err)
}
} else {
err := schema.AuthorityCheck(schema.LeadgerFields[action.FundType].PAuth.Extract, commonName, onwer)
if err != nil {
return "", fmt.Errorf("%s field extract permission check does not match, err: %s ", action.FundType, err)
}
}
funt, ok := leadgermap[action.FundType].(string)
funtAmount, ok := new(big.Int).SetString(funt, 10)
if !ok {
return "", fmt.Errorf("%s parameter resolution to big.int failed ", action.FundType)
}
actionAmount, ok := new(big.Int).SetString(action.ActionAmount, 10)
if !ok {
return "", fmt.Errorf("action_amount parameter resolution to big.int failed ")
}
sum := new(big.Int)
if isIssue {
sum = sum.Add(funtAmount, actionAmount)
} else {
if funtAmount.Cmp(actionAmount) == -1 {
return "", fmt.Errorf("The current amount is less than the withdrawal amount and cannot be extracted ")
}
sum = sum.Sub(funtAmount, actionAmount)
}
leadgermap[action.FundType] = sum.String()
leadgerResult, _ := json.Marshal(leadgermap)
err = stub.PutState(leadgerKey, leadgerResult)
if err != nil {
return "", fmt.Errorf("putState %s data fail,err: %s", leadgerKey, err)
}
return "transaction successful!", nil
}
/*
*/
func normalTransfer(args []string, stub shim.ChaincodeStubInterface) error {
if len(args) != 1 {
return nil
}
tx := &CommonTx{}
err := json.Unmarshal([]byte(args[0]), tx)
if err != nil {
fmt.Errorf("CommonTx structure json unmarshal fail,err : %s ", err)
}
sender := &TransferAccount{
tx.SenderAccountType,
tx.SenderId,
tx.SenderFunt,
}
receiver := &TransferAccount{
tx.ReceiverAccountType,
tx.ReceiverId,
tx.ReceiverFunt,
}
commonName, err := getCertificateCommonName(stub)
if err != nil {
return nil
}
amount, ok := new(big.Int).SetString(tx.Amount, 10)
if !ok {
return fmt.Errorf("amount parameter resolution to big.int failed ")
}
return transfer(amount, sender, receiver, commonName, stub)
}
/*
当增加一条交易记录的时候,我们需要根据交易记录实现,
1.预付金的计算,2.计算分成,3.预付金的变化。分成的计算
*/
func merchantsale(args []string, stub shim.ChaincodeStubInterface) error {
commanName, err := getCertificateCommonName(stub)
if err != nil {
return err
}
senderaccountType := "merchants"
receiverAccountType := "alibusi"
mer := &Merchantsale{}
err = json.Unmarshal([]byte(args[0]), mer)
if err != nil {
return fmt.Errorf("Merchantsale struct json unmarshal fail,err : %s ", err)
}
sender := &TransferAccount{
senderaccountType,
mer.Mid,
"regular",
}
receiver := &TransferAccount{
receiverAccountType,
mer.Bid,
"abail",
}
rtreposit, ok := new(big.Int).SetString(mer.Treposit, 10)
if !ok {
return fmt.Errorf("Treposit parameter resolution to big.int failed ")
}
//errinfo := make(chan error)
err = transfer(rtreposit, sender, receiver, commanName, stub)
if err != nil {
return err
}
//1.计算预付金 这部分待定
treposit := new(big.Int)
nodisamount, ok := new(big.Int).SetString(mer.Nodisamount, 10)
if !ok {
return fmt.Errorf("Nodisamount parameter resolution to big.int failed ")
}
disamount, ok := new(big.Int).SetString(mer.Disamount, 10)
if !ok {
return fmt.Errorf("Disamount parameter resolution to big.int failed ")
}
oamount, ok := new(big.Int).SetString(mer.Oamount, 10)
if !ok {
return fmt.Errorf("Oamount parameter resolution to big.int failed ")
}
if nodisamount.Cmp(big.NewInt(0)) == 0 || disamount.Cmp(big.NewInt(0)) == 0 { //如果打折金额与不打折金额任一为0,则认为全部打折
treposit, err = dividecalc(oamount, mer.Adiscounts)
if err != nil {
return err
}
} else {
distre, err := dividecalc(disamount, mer.Adiscounts) //计算打折部分的金额
if err != nil {
return err
}
treposit = new(big.Int).Add(nodisamount, distre)
}
if treposit.Cmp(rtreposit) != 0 {
return fmt.Errorf("treposit calculation fail ")
}
rfee, ok := new(big.Int).SetString(mer.Free, 10)
if !ok {
return fmt.Errorf("Fee parameter resolution to big.int failed ")
}
tamount, ok := new(big.Int).SetString(mer.Tamount, 10)
if !ok {
return fmt.Errorf("Tamount parameter resolution to big.int failed ")
}
fee, err := dividecalc(tamount, mer.Feerate)
if err != nil {
return err
}
if fee.Cmp(rfee) != 0 {
return fmt.Errorf("fee calculation fail ")
}
profit := new(big.Int).Sub(tamount, new(big.Int).Add(rfee, rtreposit)) //计算分成
if profit.Cmp(big.NewInt(0)) == -1 {
return fmt.Errorf("profit is negative ")
}
//进行分成数据
err = dividesTransaction(mer.Mid, treposit, stub)
if err != nil {
return err
}
return err
}
/*
共享惠订单交易
*/
func tickerorders(args []string, stub shim.ChaincodeStubInterface) error {
/*
由于共享惠还没有进行确定的订单交易所以这部分先进行伪代码的记录
1:计算实际支付是否正确,
2:计算手续费总和是否正确
3:计算利润
4:是否需要进行商户金额的清分(待定)//待办
5:合作方分成
6:最终分成
*/
//commanName, err := getCertificateCommonName(stub)
//if err != nil {
// return err
//}
ticketcanName := "coutcantm"
ticketName := "coutickets"
codeName := "couticketcodes"
oTx := &OrderTx{}
err := json.Unmarshal([]byte(args[0]), oTx)
if err != nil {
return fmt.Errorf("OrderTx struct json unmarshal fail,err : %s ", err)
}
tickMerKey := StoragePrefix + "_" + ticketcanName + "_" + oTx.Mid + "_" + oTx.Odesc.Tid //券可用门店key
tickM, err := getState(tickMerKey, stub)
if err != nil {
return err
}
tickKey := StoragePrefix + "_" + ticketName + "_" + oTx.Odesc.Tid //券key
tick, err := getState(tickKey, stub)
if err != nil {
return err
}
resid, _ := tickM["resid"].(float64) //剩余可用码数
discount, _ := tick["discount"].(float64) //得到券面值
fieldkeys := []string{"status"} // 码状态
var checkvalue, upvalue []interface{}
if resid == 0 {
return fmt.Errorf("The current merchant has been unable to use the %s ticket ", oTx.Odesc.Tid)
}
oamount, ok := new(big.Int).SetString(oTx.Oamount, 10)
if !ok {
return fmt.Errorf("Oamount parameter resolution to big.int failed ")
}
pamount, ok := new(big.Int).SetString(oTx.Pamount, 10)
if !ok {
return fmt.Errorf("Pamount parameter resolution to big.int failed ")
}
outfree, ok := new(big.Int).SetString(oTx.Outfree, 10)
if !ok {
return fmt.Errorf("Outfree parameter resolution to big.int failed ")
}
infree, ok := new(big.Int).SetString(oTx.Infree, 10)
if !ok {
return fmt.Errorf("Infree parameter resolution to big.int failed ")
}
partnersfree, ok := new(big.Int).SetString(oTx.Partnersfree, 10)
if !ok {
return fmt.Errorf("Partnersfree parameter resolution to big.int failed ")
}
free, ok := new(big.Int).SetString(oTx.Free, 10)
if !ok {
return fmt.Errorf("Free parameter resolution to big.int failed ")
}
if oTx.Odesc.TicketType == 1 { //如果是折扣券则只能使用一张券
if len(oTx.Odesc.Codes) > 1 {
return fmt.Errorf("Only one coupon can be used ")
}
codeKey := StoragePrefix + "_" + codeName + "_" + oTx.Odesc.Codes[0]
checkvalue[0] = float64(1)
upvalue[0] = float64(2)
_, err = checkandUpdate(codeKey, fieldkeys, checkvalue, upvalue, stub)
if err != nil {
return err
}
camount, _ := dividecalc(oamount, discount)
if camount.Cmp(pamount) != 0 {
return fmt.Errorf("pamount calculation fail ")
}
} else {
for i, v := range oTx.Odesc.Codes {
codeKey := StoragePrefix + "_" + codeName + "_" + v
checkvalue[i] = float64(1)
upvalue[i] = float64(2)
_, err = checkandUpdate(codeKey, fieldkeys, checkvalue, upvalue, stub)
if err != nil {
return err
}
}
length := int64(len(oTx.Odesc.Codes))
disint := int64(discount) //将discount 转化为整数
camount := new(big.Int).Sub(oamount, big.NewInt(disint*length))
if camount.Cmp(pamount) != 0 {
return fmt.Errorf("pamount calculation fail ")
}
}
cfree := new(big.Int).Add(new(big.Int).Add(outfree, infree), partnersfree)
if free.Cmp(cfree) != 0 {
return fmt.Errorf("free calculation fail ")
}
income := new(big.Int).Sub(pamount, free)
treposit, err := dividecalc(income, oTx.Norate)
if err != nil {
return err
}
receiver := &TransferAccount{
AccountType: "coupartners",
AccountId: oTx.Pid,
FundType: "benefit",
}
err = transfer(partnersfree, nil, receiver, "", stub)
if err != nil {
return err
}
//netincome := new(big.Int).Sub(income,treposit)
err = dividesTransaction(oTx.Mid, treposit, stub)
if err != nil {
return err
}
return nil
}
/*
根据商户Id,进行分成交易
*/
func dividesTransaction(mid string, treposit *big.Int, stub shim.ChaincodeStubInterface) error {
merkey := StoragePrefix + "_" + "merchants" + "_" + mid
mermap, err := getState(merkey, stub)
if err != nil {
return err
}
aid, ok := mermap["aid"].(string) //得到代理商Id
if !ok {
return fmt.Errorf("aid parameter resolution to string failed ")
}
bid, ok := mermap["bid"].(string) //得到分支机构Id
if !ok {
return fmt.Errorf("Free parameter resolution to string failed ")
}
acid, ok := mermap["acid"].(string) //得到加盟商Id
if !ok {
return fmt.Errorf("Free parameter resolution to string failed ")
}
fid, ok := mermap["fid"].(string) //得到保理
if !ok {
return fmt.Errorf("Free parameter resolution to string failed ")
}
asdiscounts, err := divide(aid, treposit, stub)
if err != nil {
return err
}
bsdiscounts, err := divide(bid, treposit, stub)
if err != nil {
return err
}
acsdiscounts, err := divide(acid, treposit, stub)
if err != nil {
return err
}
fsdiscounts, err := divide(fid, treposit, stub)
if err != nil {
return err
}
if asdiscounts+bsdiscounts+acsdiscounts+fsdiscounts > 1 {
return fmt.Errorf("The divide proportion must not exceed 1 ")
}
return nil
}
func divide(id string, treposit *big.Int, stub shim.ChaincodeStubInterface) (float64, error) {
akey := StoragePrefix + "_" + "alibusi" + "_" + id
amap, err := getState(akey, stub)
if err != nil {
return 0, err
}
sdiscounts, ok := amap["sdiscounts"].(float64)
if !ok {
return 0, fmt.Errorf("sdiscounts parameter resolution to float64 failed ")
}
adivide, err := dividecalc(treposit, sdiscounts)
if err != nil {
return 0, err
}
areceiver := &TransferAccount{
AccountType: "alibusi",
AccountId: id,
FundType: "amount",
}
return sdiscounts, transfer(adivide, nil, areceiver, "", stub)
}
/*
特别说明interface 不能是引用类型
*/
func checkandUpdate(key string, fieldkeys []string, checkvalue, upvalue []interface{}, stub shim.ChaincodeStubInterface) (map[string]interface{}, error) {
valueMap, err := getState(key, stub)
if err != nil {
return nil, err
}
for i, fk := range fieldkeys {
if !reflect.DeepEqual(valueMap[fk], checkvalue[i]) {
return nil, fmt.Errorf("%s not the expected field value", fk)
} else {
valueMap[fk] = upvalue[i]
}
}
value, err := json.Marshal(valueMap)
if err != nil {
return nil, err
}
err = stub.PutState(key, value)
if err != nil {
return nil, err
}
return valueMap, nil
}
/*
实现普通的转账操作
*/
func transfer(amount *big.Int, sender, receiver *TransferAccount, commonName string, stub shim.ChaincodeStubInterface) error {
var err error
if amount.Cmp(big.NewInt(0)) == -1 {
err = fmt.Errorf("transfer limit must greater than 0 ")
return err
}
if sender != nil {
senderSchema := &Schema{}
senderSchema ,err= getSchema(sender.AccountType, stub)
if err != nil {
return err
}
senderKey := LeadgerPrefix + "_" + sender.AccountType + "_" + sender.AccountId
senderleadgermap, err := getState(senderKey, stub)
if err != nil {
return err
}
onwer, ok := senderleadgermap["common_name"].(string)
err = senderSchema.AuthorityCheck(senderSchema.LeadgerFields[sender.FundType].PAuth.Transfer, commonName, onwer)
if err !=nil {
err = fmt.Errorf("%s field issue permission check does not match, err: %s ", sender.FundType, err)
return err
}
fundstr := senderleadgermap[sender.FundType].(string)
fund, ok := new(big.Int).SetString(fundstr, 10)
if !ok {
err = fmt.Errorf("%s parameter resolution to big.int failed ", sender.FundType)
return err
}
if fund.Cmp(amount) == -1 {
err = fmt.Errorf("The current amount is less than the withdrawal amount and cannot be extracted ")
return err
}
fund.Sub(fund, amount)
senderleadgermap[sender.FundType] = fund.String()
err = putState(senderKey, senderleadgermap, stub)
if err != nil {
return err
}
}
if receiver != nil {
receiverKey := LeadgerPrefix + "_" + receiver.AccountType + "_" + receiver.AccountId
receiverleadgermap, err := getState(receiverKey, stub)
if err != nil {
return err
}
rfundstr := receiverleadgermap[receiver.FundType].(string)
rfund, ok := new(big.Int).SetString(rfundstr, 10)
if !ok {
err = fmt.Errorf("%s parameter resolution to big.int failed ", receiver.FundType)
return err
}
rfund.Add(rfund, amount)
receiverleadgermap[receiver.FundType] = rfund.String()
err = putState(receiverKey, receiverleadgermap, stub)
if err != nil {
return err
}
}
return nil
}
package main
import (
"encoding/json"
"fmt"
"math/big"
"reflect"
"time"
)
func NewSchema(arg string) (*Schema, error) {
schema := &Schema{
LeadgerFields: make(map[string]SchemaLeadgerParameters),
StorageFields: make(map[string]SchemaParameters),
}
var argMap map[string]interface{}
if err := json.Unmarshal([]byte(arg), &argMap); err != nil {
return nil, err
}
if (argMap["storage_fields"] != nil || argMap["leadger_fields"] != nil) && argMap["schema_auth"] != nil && argMap["auth"] != nil {
if err := json.Unmarshal([]byte(arg), schema); err != nil {
return nil, err
}
//检查schema leadger字段
err := leadgerFieldsCheck(&schema.LeadgerFields)
if err != nil {
return nil, err
}
return schema, nil
}
for k, v := range argMap { //假设用户只传递了map类型的信息,我们则默认它全部都是存储字段
schema.StorageFields[k] = SchemaParameters{
Value: v,
PAuth: Auth{},
}
}
return schema, nil
}
func leadgerFieldsCheck(leadgerFields *map[string]SchemaLeadgerParameters) error {
for k, fields := range *leadgerFields {
if fields.FCheck == nil {
fields.FCheck = &Checks{
FType: "big.int",
Must: false,
Fieldlen: 1,
}
} else {
if fields.FCheck.FType != "big.int" {
return fmt.Errorf("%s fields type must is big.int", k)
} else if !(fields.FCheck.Fieldlen > 0) {
return fmt.Errorf("%s fields length must is greater than zero", k)
}
}
if len(fields.PAuth.Extract.Roles) == 0 && len(fields.PAuth.Extract.Users) == 0 {
}
}
return nil
}
/*
schema 权限检查,权限组是否满足权限
*/
func (schema *Schema) AuthorityCheck(authority AuthGroup, name, owner string) error {
var auths map[string]int64
if IsUsers {
auths = authority.Users
} else {
auths = authority.Roles
}
if len(auths) == 0 {
return nil
}
for k, v := range auths {
if k == name || (k == "owner" && name == owner) {
if v == 0 || v > time.Now().Unix() {
return nil
} else {
return fmt.Errorf("%s user permission period ", name)
}
}
}
return fmt.Errorf("%s user does not have permission", name)
}
/*
schema 写权限检查,权限组是否满足权限
*/
func (schema *Schema) WriteCheck(name, owner string) error {
return schema.AuthorityCheck(schema.SchemaAuth.Write,name,owner)
}
/*
schema 对应数据总写权限检查,权限组是否满足权限
*/
func (schema *Schema) AllWriteCheck(name, owner string) error {
return schema.AuthorityCheck(schema.SAuth.Write,name,owner)
}
/*
数据的写权限检查
*/
func (schema *Schema) DataWriteCheck(checks map[string]interface{}, commonName, owner string) error{
//if err := schema.WriteCheck(commonName,owner) ; err != nil{
// return nil
//}
for k, _ := range checks {
if schemaV, ok := schema.StorageFields[k]; !ok {
return fmt.Errorf("inexistence %s field! ",k)
} else {
if err := schema.AuthorityCheck(schemaV.PAuth.Write, commonName, owner); err != nil {
return fmt.Errorf("%s field authority check fail, %s ",k,err)
}
}
}
return nil
}
/*
schema 读权限检查,权限组是否满足权限
*/
func (schema *Schema) ReadCheck(name, owner string) error {
return schema.AuthorityCheck(schema.SchemaAuth.Read,name,owner)
}
/*
schema 对应数据总读权限检查,权限组是否满足权限
*/
func (schema *Schema) AllReadCheck(name, owner string) error {
return schema.AuthorityCheck(schema.SAuth.Read,name,owner)
}
/*
schema 读过滤
*/
func (schema *Schema) ReadFiler(checks map[string]interface{}, commonName, owner string) (map[string]interface{}, error) {
//if err := schema.ReadCheck(commonName,owner) ; err != nil{
// return checks, nil
//}
for k, schemaV := range schema.StorageFields {
if err := schema.AuthorityCheck(schemaV.PAuth.Read, commonName, owner); err != nil {
checks[k] = defValue
}
}
for k, schemaV := range schema.LeadgerFields {
if err := schema.AuthorityCheck(schemaV.PAuth.Read, commonName, owner); err != nil {
checks[k] = defValue
}
}
return checks, nil
}
func (schema *Schema) DataReadCheck(checks map[string]interface{}, commonName, owner string) error{
//if err := schema.WriteCheck(commonName,owner) ; err != nil{
// return nil
//}
for k, _ := range checks {
if schemaV, ok := schema.StorageFields[k]; !ok {
return fmt.Errorf("inexistence %s field! ",k)
} else {
if err := schema.AuthorityCheck(schemaV.PAuth.Read, commonName, owner); err != nil {
return fmt.Errorf("%s field authority check fail, %s ",k,err)
}
}
}
return nil
}
/*
进行Schema 字段的格式匹配
*/
func (schema *Schema)SchemaMatched(checks map[string]interface{})error{
if len(schema.StorageFields)+len(schema.LeadgerFields) != len(checks) {
return fmt.Errorf("field length is less than the schema field length ! ")
}
for k, v := range schema.StorageFields {
if schemaV, ok := checks[k]; !ok {
return fmt.Errorf("There is no input storage field %s ", k)
} else {
if parameterS, ok := v.Value.(map[string]interface{}); ok {
if parameterC, ok := schemaV.(map[string]interface{}); !ok {
return fmt.Errorf("The input field %s does not match the output field format ", k)
} else {
err := backUpCheck(parameterS, parameterC)
if err != nil {
return err
}
}
}
}
}
for k, _ := range schema.LeadgerFields {
if _, ok := checks[k]; !ok {
return fmt.Errorf("There is no input leadger field %s ", k)
}
}
return nil
}
func backUpCheck(backUp map[string]interface{}, checkmap map[string]interface{}) error {
if len(backUp) != len(checkmap) {
return fmt.Errorf("The input backup field length is less than the schema backup field length ! ")
}
for k, _ := range checkmap {
if _, ok := backUp[k]; !ok {
return fmt.Errorf("There is no input backup field %s ", k)
}
}
return nil
}
func (schema *Schema)FieldsCheck(checks map[string]interface{})error{
for k, schemaV := range schema.StorageFields {
if _, ok := checks[k]; !ok {
return fmt.Errorf("There is no input storage field %s ", k)
}
if schemaV.FCheck != nil && schemaV.FCheck.FType != "" {
if err := schema.fieldCheckout(schemaV.FCheck, checks[k]); err != nil {
return fmt.Errorf("%s field check err:%s ", k, err)
}
}
}
for k, schemaV := range schema.LeadgerFields {
if _, ok := checks[k]; !ok {
return fmt.Errorf("There is no input storage field %s ", k)
}
if schemaV.FCheck != nil && schemaV.FCheck.FType != "" {
if err := schema.fieldCheckout(schemaV.FCheck, checks[k]); err != nil {
return fmt.Errorf("%s field check err:%s ", k, err)
}
}
}
return nil
}
func (schema *Schema)FieldsFormatCheck(checks map[string]interface{})error{
for k, _ := range checks{
fcheck := &Checks{}
sfield,ok := schema.StorageFields[k]
if ok{
fcheck = sfield.FCheck
}else{
lfield,ok := schema.LeadgerFields[k]
if !ok{
return fmt.Errorf("%s field check inexistence in schema", k, )
}
fcheck = lfield.FCheck
}
if fcheck != nil && fcheck.FType != "" && checks[k] != nil {
if err := schema.fieldCheckout(fcheck, checks[k]); err != nil {
return fmt.Errorf("%s field check err:%s ", k, err)
}
}
}
return nil
}
func (schema *Schema)fieldCheckout(check *Checks, val interface{}) error {
fType := reflect.TypeOf(val).String()
switch check.FType {
case "string":
if fType != "string" {
return fmt.Errorf("fields type does not match the defined string type! ")
}
if check.Must && (val == "") {
return fmt.Errorf("fields can not be empty")
}
value := val.(string)
if len([]rune(value)) > check.Fieldlen {
return fmt.Errorf("fields length cannot be greater than %d ", check.Fieldlen)
}
case "int", "int16", "int32", "int64", "float32", "float64":
if fType != "float64" {
return fmt.Errorf("fields type does not match the defined %s type! ", check.FType)
}
value := val.(float64)
if check.Must && (value == 0) {
return fmt.Errorf("fields can not be 0")
}
if check.Fieldlen != 0 && value < 0 {
return fmt.Errorf("fields cannot be negative")
}
case "time.Time":
if fType != "string" {
return fmt.Errorf("fields type does not match the defined time.Time type! ")
}
dateStr := reflect.ValueOf(val).String()
if check.Must && dateStr == "" {
return fmt.Errorf("fields cannot be empty")
}
if _, err := time.Parse("2006-01-02 15:04:05", dateStr); err != nil {
return fmt.Errorf(err.Error())
}
//if check.Must && (dateStr == "0001-01-01 00:00:00 +0000 UTC"|| dateStr == "0001-01-01T00:00:00Z"){
// return fmt.Errorf("fields cannot be initial value")
//}
case "big.int":
if fType != "string" {
return fmt.Errorf("fields type does not match the defined big.int type! ")
}
number := new(big.Int)
dateStr := reflect.ValueOf(val).String()
_, ok := number.SetString(dateStr, 10)
if !ok {
return fmt.Errorf("parameter resolution failed ")
}
case "object","struct":
if fType != "map[string]interface {}" {
return fmt.Errorf("fields type does not match the defined big.int type! ")
}
default:
fmt.Errorf("fields type no match! ")
}
return nil
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment