@@ -2,21 +2,36 @@ package main
22
33import (
44 "context"
5+ "encoding/json"
56 "fmt"
67 "os"
8+ "os/signal"
9+ "syscall"
710
811 "cosmossdk.io/log"
912 "github.com/CosmWasm/wasmd/app"
1013 "github.com/CosmWasm/wasmd/x/wasm/keeper"
1114 wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
15+ rpchttp "github.com/cometbft/cometbft/rpc/client/http"
1216 dbm "github.com/cosmos/cosmos-db"
1317 "github.com/cosmos/cosmos-sdk/baseapp"
18+ "github.com/cosmos/cosmos-sdk/client"
19+ "github.com/cosmos/cosmos-sdk/codec"
20+ cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
1421 "github.com/cosmos/cosmos-sdk/server"
22+ srvconfig "github.com/cosmos/cosmos-sdk/server/config"
23+ servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
1524 "github.com/cosmos/cosmos-sdk/testutil/sims"
1625 sdk "github.com/cosmos/cosmos-sdk/types"
26+ "github.com/cosmos/cosmos-sdk/x/auth/tx"
27+ "golang.org/x/sync/errgroup"
28+ "google.golang.org/grpc"
29+ "google.golang.org/grpc/credentials/insecure"
1730
1831 "github.com/consideritdone/landslidevm"
32+ "github.com/consideritdone/landslidevm/utils/ids"
1933 "github.com/consideritdone/landslidevm/vm"
34+ vmtypes "github.com/consideritdone/landslidevm/vm/types"
2035)
2136
2237func main () {
@@ -40,8 +55,158 @@ func WasmCreator() vm.AppCreator {
4055 cfg .SetBech32PrefixForConsensusNode (app .Bech32PrefixConsAddr , app .Bech32PrefixConsPub )
4156 cfg .SetAddressVerifier (wasmtypes .VerifyAddressLen ())
4257 cfg .Seal ()
43- wasmApp := app .NewWasmApp (logger , db , nil , true , sims .NewAppOptionsWithFlagHome (os .TempDir ()), []keeper.Option {}, baseapp .SetChainID ("landslide-test" ))
58+
59+ srvCfg := * srvconfig .DefaultConfig ()
60+ grpcCfg := srvCfg .GRPC
61+ var vmCfg vmtypes.VmConfig
62+ vmCfg .SetDefaults ()
63+ if len (config .ConfigBytes ) > 0 {
64+ if err := json .Unmarshal (config .ConfigBytes , & vmCfg ); err != nil {
65+ return nil , fmt .Errorf ("failed to unmarshal config %s: %w" , string (config .ConfigBytes ), err )
66+ }
67+ // set the grpc port, if it is set to 0, disable gRPC
68+ if vmCfg .GRPCPort > 0 {
69+ grpcCfg .Address = fmt .Sprintf ("127.0.0.1:%d" , vmCfg .GRPCPort )
70+ } else {
71+ grpcCfg .Enable = false
72+ }
73+ }
74+
75+ if err := vmCfg .Validate (); err != nil {
76+ return nil , err
77+ }
78+ chainID := vmCfg .NetworkName
79+
80+ var wasmApp = app .NewWasmApp (
81+ logger ,
82+ db ,
83+ nil ,
84+ true ,
85+ sims .NewAppOptionsWithFlagHome (os .TempDir ()),
86+ []keeper.Option {},
87+ baseapp .SetChainID (chainID ),
88+ )
89+
90+ // early return if gRPC is disabled
91+ if ! grpcCfg .Enable {
92+ return server .NewCometABCIWrapper (wasmApp ), nil
93+ }
94+
95+ interfaceRegistry := wasmApp .InterfaceRegistry ()
96+ marshaller := codec .NewProtoCodec (interfaceRegistry )
97+ clientCtx := client.Context {}.
98+ WithCodec (marshaller ).
99+ WithLegacyAmino (makeCodec ()).
100+ WithTxConfig (tx .NewTxConfig (marshaller , tx .DefaultSignModes )).
101+ WithInterfaceRegistry (interfaceRegistry ).
102+ WithChainID (chainID )
103+
104+ avaChainID , err := ids .ToID (config .ChainId )
105+ if err != nil {
106+ return nil , err
107+ }
108+
109+ rpcURI := fmt .Sprintf (
110+ "http://127.0.0.1:%d/ext/bc/%s/rpc" ,
111+ vmCfg .RPCPort ,
112+ avaChainID ,
113+ )
114+
115+ clientCtx = clientCtx .WithNodeURI (rpcURI )
116+ rpcclient , err := rpchttp .New (rpcURI , "/websocket" )
117+ if err != nil {
118+ return nil , err
119+ }
120+ clientCtx = clientCtx .WithClient (rpcclient )
121+
122+ // use the provided clientCtx to register the services
123+ wasmApp .RegisterTxService (clientCtx )
124+ wasmApp .RegisterTendermintService (clientCtx )
125+ wasmApp .RegisterNodeService (clientCtx , srvconfig.Config {})
126+
127+ maxSendMsgSize := grpcCfg .MaxSendMsgSize
128+ if maxSendMsgSize == 0 {
129+ maxSendMsgSize = srvconfig .DefaultGRPCMaxSendMsgSize
130+ }
131+
132+ maxRecvMsgSize := grpcCfg .MaxRecvMsgSize
133+ if maxRecvMsgSize == 0 {
134+ maxRecvMsgSize = srvconfig .DefaultGRPCMaxRecvMsgSize
135+ }
136+
137+ // if gRPC is enabled, configure gRPC client for gRPC gateway
138+ grpcClient , err := grpc .Dial (
139+ grpcCfg .Address ,
140+ grpc .WithTransportCredentials (insecure .NewCredentials ()),
141+ grpc .WithDefaultCallOptions (
142+ grpc .ForceCodec (codec .NewProtoCodec (clientCtx .InterfaceRegistry ).GRPCCodec ()),
143+ grpc .MaxCallRecvMsgSize (maxRecvMsgSize ),
144+ grpc .MaxCallSendMsgSize (maxSendMsgSize ),
145+ ),
146+ )
147+ if err != nil {
148+ return nil , err
149+ }
150+
151+ clientCtx = clientCtx .WithGRPCClient (grpcClient )
152+ logger .Debug ("gRPC client assigned to client context" , "target" , grpcCfg .Address )
153+
154+ g , ctx := getCtx (logger , false )
155+
156+ grpcSrv , err := servergrpc .NewGRPCServer (clientCtx , wasmApp , grpcCfg )
157+ if err != nil {
158+ return nil , err
159+ }
160+
161+ // Start the gRPC server in a goroutine. Note, the provided ctx will ensure
162+ // that the server is gracefully shut down.
163+ g .Go (func () error {
164+ return servergrpc .StartGRPCServer (ctx , logger .With ("module" , "grpc-server" ), grpcCfg , grpcSrv )
165+ })
44166
45167 return server .NewCometABCIWrapper (wasmApp ), nil
46168 }
47169}
170+
171+ // custom tx codec
172+ func makeCodec () * codec.LegacyAmino {
173+ cdc := codec .NewLegacyAmino ()
174+ sdk .RegisterLegacyAminoCodec (cdc )
175+ cryptocodec .RegisterCrypto (cdc )
176+ return cdc
177+ }
178+
179+ func getCtx (logger log.Logger , block bool ) (* errgroup.Group , context.Context ) {
180+ ctx , cancelFn := context .WithCancel (context .Background ())
181+ g , ctx := errgroup .WithContext (ctx )
182+ // listen for quit signals so the calling parent process can gracefully exit
183+ listenForQuitSignals (g , block , cancelFn , logger )
184+ return g , ctx
185+ }
186+
187+ // listenForQuitSignals listens for SIGINT and SIGTERM. When a signal is received,
188+ // the cleanup function is called, indicating the caller can gracefully exit or
189+ // return.
190+ //
191+ // Note, the blocking behavior of this depends on the block argument.
192+ // The caller must ensure the corresponding context derived from the cancelFn is used correctly.
193+ func listenForQuitSignals (g * errgroup.Group , block bool , cancelFn context.CancelFunc , logger log.Logger ) {
194+ sigCh := make (chan os.Signal , 1 )
195+ signal .Notify (sigCh , syscall .SIGINT , syscall .SIGTERM )
196+
197+ f := func () {
198+ sig := <- sigCh
199+ cancelFn ()
200+
201+ logger .Info ("caught signal" , "signal" , sig .String ())
202+ }
203+
204+ if block {
205+ g .Go (func () error {
206+ f ()
207+ return nil
208+ })
209+ } else {
210+ go f ()
211+ }
212+ }
0 commit comments