-
Notifications
You must be signed in to change notification settings - Fork 1
/
activity.go
145 lines (130 loc) · 4.37 KB
/
activity.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package invokechaincode
import (
"encoding/json"
"fmt"
"github.com/TIBCOSoftware/flogo-lib/core/activity"
"github.com/TIBCOSoftware/flogo-lib/core/data"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/pkg/errors"
"github.com/yxuco/flogo-enterprise-app/fabric/common"
)
const (
ivChaincode = "chaincodeName"
ivChannel = "channelID"
ivTransaction = "transactionName"
ivParameters = "parameters"
ovCode = "code"
ovMessage = "message"
ovResult = "result"
)
// Create a new logger
var log = shim.NewLogger("activity-fabric-invokechaincode")
func init() {
common.SetChaincodeLogLevel(log)
}
// FabricChaincodeActivity is a stub for executing Hyperledger Fabric invoke-chaincode operations
type FabricChaincodeActivity struct {
metadata *activity.Metadata
}
// NewActivity creates a new FabricChaincodeActivity
func NewActivity(metadata *activity.Metadata) activity.Activity {
return &FabricChaincodeActivity{metadata: metadata}
}
// Metadata implements activity.Activity.Metadata
func (a *FabricChaincodeActivity) Metadata() *activity.Metadata {
return a.metadata
}
// Eval implements activity.Activity.Eval
func (a *FabricChaincodeActivity) Eval(ctx activity.Context) (done bool, err error) {
// check input args
ccName, ok := ctx.GetInput(ivChaincode).(string)
if !ok || ccName == "" {
log.Error("chaincode name is not specified\n")
ctx.SetOutput(ovCode, 400)
ctx.SetOutput(ovMessage, "chaincode name is not specified")
return false, errors.New("chaincode name is not specified")
}
log.Debugf("chaincode name: %s\n", ccName)
channelID := ""
if channelID, ok = ctx.GetInput(ivChannel).(string); !ok {
log.Info("channel ID is not specified\n")
}
log.Debugf("channel ID: %s\n", channelID)
// extract transaction name and parameters
args, err := constructChaincodeArgs(ctx)
if err != nil {
ctx.SetOutput(ovCode, 400)
ctx.SetOutput(ovMessage, err.Error())
return false, err
}
// get chaincode stub
stub, err := common.GetChaincodeStub(ctx)
if err != nil || stub == nil {
ctx.SetOutput(ovCode, 500)
ctx.SetOutput(ovMessage, err.Error())
return false, err
}
// invoke chaincode
response := stub.InvokeChaincode(ccName, args, channelID)
ctx.SetOutput(ovCode, response.GetStatus())
ctx.SetOutput(ovMessage, response.GetMessage())
jsonBytes := response.GetPayload()
if jsonBytes == nil {
log.Debugf("no data returned by invoking chaincode\n")
return true, nil
}
var value interface{}
if err := json.Unmarshal(jsonBytes, &value); err != nil {
log.Errorf("failed to unmarshal chaincode response %+v, error: %+v\n", jsonBytes, err)
return true, nil
}
if result, ok := ctx.GetOutput(ovResult).(*data.ComplexObject); ok && result != nil {
log.Debugf("set activity output result: %+v\n", value)
result.Value = value
ctx.SetOutput(ovResult, result)
}
return true, nil
}
func constructChaincodeArgs(ctx activity.Context) ([][]byte, error) {
var result [][]byte
// transaction name from input
txnName, ok := ctx.GetInput(ivTransaction).(string)
if !ok || txnName == "" {
log.Error("transaction name is not specified\n")
return nil, errors.New("transaction name is not specified")
}
log.Debugf("transaction name: %s\n", txnName)
result = append(result, []byte(txnName))
// extract parameter definitions from metadata
paramObj, ok := ctx.GetInput(ivParameters).(*data.ComplexObject)
if !ok {
log.Debug("parameter is not a complex object\n")
return result, nil
}
paramIndex, err := common.OrderedParameters([]byte(paramObj.Metadata))
if err != nil {
log.Errorf("failed to extract parameter definition from metadata: %+v\n", err)
return result, nil
}
if paramIndex == nil || len(paramIndex) == 0 {
log.Debug("no parameter defined in metadata\n")
return result, nil
}
// extract parameter values in the order of parameter index
paramValue, ok := paramObj.Value.(map[string]interface{})
if !ok {
log.Debugf("parameter value of type %T is not a JSON object\n", paramObj.Value)
return result, nil
}
for _, p := range paramIndex {
// TODO: assuming string params here to be consistent with implementaton of trigger and chaincode-shim
// should change all places to use []byte for best portability
param := ""
if v, ok := paramValue[p.Name]; ok && v != nil {
param = fmt.Sprintf("%v", v)
log.Debugf("add chaincode parameter: %s=%s", p.Name, param)
}
result = append(result, []byte(param))
}
return result, nil
}