forked from hyperledger-archives/fabric-chaincode-evm
/
main.go
175 lines (144 loc) · 5.41 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"go.uber.org/zap"
"github.com/hyperledger/fabric-chaincode-evm/fab3"
"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
"github.com/hyperledger/fabric-sdk-go/pkg/client/ledger"
"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var fab3Cmd = &cobra.Command{
Use: "fab3",
Short: "fab3 is a web3 provider used to interact with the EVM chaincode on a Fabric Network. The flags provided will be honored over the corresponding environment variables.",
Long: "fab3 is a web3 provider used to interact with the EVM chaincode on a Fabric Network. The flags provided will be honored over the corresponding environment variables.",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
err := checkFlags()
if err != nil {
return err
}
// At this point all of our flags have been validated
// Usage no longer needs to be provided for the errors that follow
cmd.SilenceUsage = true
return runFab3(cmd, args)
},
}
var cfg, user, org, ch, ccid string
var port int
// InitFlags sets up the flags and environment variables for Fab3
func initFlags() {
viper.SetEnvPrefix("FAB3")
viper.BindEnv("config")
viper.BindEnv("user")
viper.BindEnv("org")
viper.BindEnv("channel")
viper.BindEnv("ccid")
viper.BindEnv("port")
fab3Cmd.PersistentFlags().StringVarP(&cfg, "config", "c", "",
"Path to a compatible Fabric SDK Go config file. This flag is required if FAB3_CONFIG is not set.")
viper.BindPFlag("config", fab3Cmd.PersistentFlags().Lookup("config"))
fab3Cmd.PersistentFlags().StringVarP(&user, "user", "u", "",
"User identity being used for the proxy (Matches the users' names in the crypto-config directory specified in the config). This flag is required if FAB3_USER is not set.")
viper.BindPFlag("user", fab3Cmd.PersistentFlags().Lookup("user"))
fab3Cmd.PersistentFlags().StringVarP(&org, "org", "o", "",
"Organization of the specified user. This flag is required if FAB3_ORG is not set.")
viper.BindPFlag("org", fab3Cmd.PersistentFlags().Lookup("org"))
fab3Cmd.PersistentFlags().StringVarP(&ch, "channel", "C", "",
"Channel to be used for the transactions. This flag is required if FAB3_CHANNEL is not set.")
viper.BindPFlag("channel", fab3Cmd.PersistentFlags().Lookup("channel"))
//CCID defaults to "evmcc" if FAB3_CCID is not set or `-i,-ccid` is not provided
fab3Cmd.PersistentFlags().StringVarP(&ccid, "ccid", "i", "evmcc",
"ID of the EVM Chaincode deployed in your fabric network. The CCID to be used in by fab3 can also be set by the FAB3_CCID environment variable.")
viper.BindPFlag("ccid", fab3Cmd.PersistentFlags().Lookup("ccid"))
//Port defaults to 5000 if PORT is not set or `-p,-port` is not provided
fab3Cmd.PersistentFlags().IntVarP(&port, "port", "p", 5000,
"Port that Fab3 will be running on. The listening port can also be set by the FAB3_PORT environment variable.")
viper.BindPFlag("port", fab3Cmd.PersistentFlags().Lookup("port"))
}
// Viper takes care of precedence of Flags and Environment variables
// Flag values are taken over environment variables
// Both CCID and Port have defaults so do not need to be provided.
func checkFlags() error {
cfg = viper.GetString("config")
if cfg == "" {
return fmt.Errorf("Missing config. Please use flag --config or set FAB3_CONFIG")
}
user = viper.GetString("user")
if user == "" {
return fmt.Errorf("Missing user. Please use flag --user or set FAB3_USER")
}
org = viper.GetString("org")
if org == "" {
return fmt.Errorf("Missing org. Please use flag --org or set FAB3_ORG")
}
ch = viper.GetString("channel")
if ch == "" {
return fmt.Errorf("Missing channel. Please use flag --channel or set FAB3_CHANNEL")
}
ccid = viper.GetString("ccid")
port = viper.GetInt("port")
return nil
}
// Runs Fab3
// Will exit gracefully for errors and signal interrupts
func runFab3(cmd *cobra.Command, args []string) error {
sdk, err := fabsdk.New(config.FromFile(cfg))
if err != nil {
return fmt.Errorf("Failed to create Fabric SDK Client: %s\n", err)
}
clientChannelContext := sdk.ChannelContext(ch, fabsdk.WithUser(user), fabsdk.WithOrg(org))
client, err := channel.New(clientChannelContext)
if err != nil {
sdk.Close()
return fmt.Errorf("Failed to create Fabric SDK Channel Client: %s\n", err)
}
ledger, err := ledger.New(clientChannelContext)
if err != nil {
sdk.Close()
return fmt.Errorf("Failed to create Fabric SDK Ledger Client: %s\n", err)
}
rawLogger, err := zap.NewProduction()
if err != nil {
sdk.Close()
return fmt.Errorf("Failed to create logger: %s\n", err)
}
logger := rawLogger.Named("fab3").Sugar()
ethService := fab3.NewEthService(client, ledger, ch, ccid, logger)
proxy := fab3.NewFab3(ethService, port)
errChan := make(chan error, 1)
go func() {
errChan <- proxy.Start()
}()
logger.Infow("Starting Fab3", "port", port)
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
select {
case err = <-errChan:
case <-signalChan:
logger.Info("Received termination signal")
err = proxy.Shutdown()
}
sdk.Close()
if err != nil {
logger.Infow("Fab3 exited with error", "error", err)
return err
}
logger.Info("Fab3 exited")
return nil
}
func main() {
initFlags()
if fab3Cmd.Execute() != nil {
os.Exit(1)
}
}