laconicd/testutil/network/util.go
Federico Kunze Küllmer d068f5b331
server: logger handler (#343)
* Problem: verbose logs display with FATAL option (fix #320)
add my script

increase amount for metamask

add run

amount ok

hide log

show info

my logger

hook log

revive eth log

tidy up

use suplog

log replace ok

removed suplog

tidy up

tidy up

fix compile

remove sh

tidy up

tidy up

* logger handler

* fix

* fix eth log override (#371)

remove redundant log

tidy up

* log test

* c++

Co-authored-by: jongwhan lee <jonghwan@crypto.com>
Co-authored-by: Jongwhan Lee <51560997+leejw51crypto@users.noreply.github.com>
2021-08-19 16:55:13 +00:00

279 lines
7.7 KiB
Go

package network
import (
"encoding/json"
"fmt"
"net/http"
"path/filepath"
"strings"
"time"
jsonrpc "github.com/ethereum/go-ethereum/rpc"
"github.com/gorilla/mux"
"github.com/improbable-eng/grpc-web/go/grpcweb"
"github.com/rs/cors"
tmos "github.com/tendermint/tendermint/libs/os"
"github.com/tendermint/tendermint/node"
"github.com/tendermint/tendermint/p2p"
pvm "github.com/tendermint/tendermint/privval"
"github.com/tendermint/tendermint/proxy"
"github.com/tendermint/tendermint/rpc/client/local"
"github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
"github.com/cosmos/cosmos-sdk/server/api"
servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/tharsis/ethermint/ethereum/rpc"
ethsrv "github.com/tharsis/ethermint/server"
ethermint "github.com/tharsis/ethermint/types"
)
func startInProcess(cfg Config, val *Validator) error {
logger := val.Ctx.Logger
tmCfg := val.Ctx.Config
tmCfg.Instrumentation.Prometheus = false
nodeKey, err := p2p.LoadOrGenNodeKey(tmCfg.NodeKeyFile())
if err != nil {
return fmt.Errorf("failed to load or generate node key: %w", err)
}
app := cfg.AppConstructor(*val)
genDocProvider := node.DefaultGenesisDocProviderFunc(tmCfg)
tmNode, err := node.NewNode(
tmCfg,
pvm.LoadOrGenFilePV(tmCfg.PrivValidatorKeyFile(), tmCfg.PrivValidatorStateFile()),
nodeKey,
proxy.NewLocalClientCreator(app),
genDocProvider,
node.DefaultDBProvider,
node.DefaultMetricsProvider(tmCfg.Instrumentation),
logger.With("module", val.Moniker),
)
if err != nil {
return fmt.Errorf("failed to create node: %w", err)
}
if err := tmNode.Start(); err != nil {
return fmt.Errorf("failed to start node: %w", err)
}
val.tmNode = tmNode
if val.RPCAddress != "" {
val.RPCClient = local.New(tmNode)
}
// We'll need a RPC client if the validator exposes a gRPC or REST endpoint.
if val.APIAddress != "" || val.AppConfig.GRPC.Enable {
val.ClientCtx = val.ClientCtx.
WithClient(val.RPCClient)
// Add the tx service in the gRPC router.
app.RegisterTxService(val.ClientCtx)
// Add the tendermint queries service in the gRPC router.
app.RegisterTendermintService(val.ClientCtx)
}
if val.APIAddress != "" {
apiSrv := api.New(val.ClientCtx, logger.With("module", "api-server"))
app.RegisterAPIRoutes(apiSrv, val.AppConfig.API)
errCh := make(chan error)
go func() {
if err := apiSrv.Start(val.AppConfig.Config); err != nil {
errCh <- err
}
}()
select {
case err := <-errCh:
return fmt.Errorf("failed to start API server: %w", err)
case <-time.After(5 * time.Second): // assume server started successfully
}
val.api = apiSrv
}
if val.AppConfig.GRPC.Enable {
grpcSrv, err := servergrpc.StartGRPCServer(val.ClientCtx, app, val.AppConfig.GRPC.Address)
if err != nil {
return fmt.Errorf("failed to start gRPC server: %w", err)
}
val.grpc = grpcSrv
}
if val.AppConfig.JSONRPC.Enable {
tmEndpoint := "/websocket"
tmRPCAddr := val.Ctx.Config.RPC.ListenAddress
tmWsClient := ethsrv.ConnectTmWS(tmRPCAddr, tmEndpoint, val.Ctx.Logger)
val.jsonRPC = jsonrpc.NewServer()
rpcAPIArr := val.AppConfig.JSONRPC.API
apis := rpc.GetRPCAPIs(val.Ctx, val.ClientCtx, tmWsClient, rpcAPIArr)
for _, api := range apis {
if err := val.jsonRPC.RegisterName(api.Namespace, api.Service); err != nil {
return fmt.Errorf("failed to register JSON-RPC namespace %s: %w", api.Namespace, err)
}
}
r := mux.NewRouter()
r.HandleFunc("/", val.jsonRPC.ServeHTTP).Methods("POST")
if val.grpc != nil {
grpcWeb := grpcweb.WrapServer(val.grpc)
ethsrv.MountGRPCWebServices(r, grpcWeb, grpcweb.ListGRPCResources(val.grpc), val.Ctx.Logger)
}
handlerWithCors := cors.New(cors.Options{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{
http.MethodHead,
http.MethodGet,
http.MethodPost,
http.MethodPut,
http.MethodPatch,
http.MethodDelete,
},
AllowedHeaders: []string{"*"},
AllowCredentials: false,
OptionsPassthrough: false,
})
httpSrv := &http.Server{
Addr: strings.TrimPrefix(val.AppConfig.JSONRPC.Address, "tcp://"), // FIXME: timeouts
// Addr: val.AppConfig.JSONRPC.RPCAddress, // FIXME: address has too many colons
Handler: handlerWithCors.Handler(r),
}
httpSrvDone := make(chan struct{}, 1)
errCh := make(chan error)
go func() {
if err := httpSrv.ListenAndServe(); err != nil {
if err == http.ErrServerClosed {
close(httpSrvDone)
return
}
errCh <- err
}
}()
select {
case err := <-errCh:
return fmt.Errorf("JSON-RPC go routine failed to start: %w", err)
case <-time.After(1 * time.Second): // assume EVM RPC server started successfully
}
}
return nil
}
func collectGenFiles(cfg Config, vals []*Validator, outputDir string) error {
genTime := tmtime.Now()
for i := 0; i < cfg.NumValidators; i++ {
tmCfg := vals[i].Ctx.Config
nodeDir := filepath.Join(outputDir, vals[i].Moniker, "ethermintd")
gentxsDir := filepath.Join(outputDir, "gentxs")
tmCfg.Moniker = vals[i].Moniker
tmCfg.SetRoot(nodeDir)
initCfg := genutiltypes.NewInitConfig(cfg.ChainID, gentxsDir, vals[i].NodeID, vals[i].PubKey)
genFile := tmCfg.GenesisFile()
genDoc, err := types.GenesisDocFromFile(genFile)
if err != nil {
return fmt.Errorf("failed to create genesis doc: %w", err)
}
appState, err := genutil.GenAppStateFromConfig(cfg.Codec, cfg.TxConfig,
tmCfg, initCfg, *genDoc, banktypes.GenesisBalancesIterator{})
if err != nil {
return fmt.Errorf("failed to create app state: %w", err)
}
// overwrite each validator's genesis file to have a canonical genesis time
if err := genutil.ExportGenesisFileWithTime(genFile, cfg.ChainID, nil, appState, genTime); err != nil {
return fmt.Errorf("failed to export genesis: %w", err)
}
}
return nil
}
func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalances []banktypes.Balance, genFiles []string) error {
// set the accounts in the genesis state
var authGenState authtypes.GenesisState
cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[authtypes.ModuleName], &authGenState)
accounts, err := authtypes.PackAccounts(genAccounts)
if err != nil {
return err
}
authGenState.Accounts = accounts
cfg.GenesisState[authtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&authGenState)
// set the balances in the genesis state
var bankGenState banktypes.GenesisState
cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[banktypes.ModuleName], &bankGenState)
bankGenState.Balances = genBalances
cfg.GenesisState[banktypes.ModuleName] = cfg.Codec.MustMarshalJSON(&bankGenState)
var stakingGenState stakingtypes.GenesisState
cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[stakingtypes.ModuleName], &stakingGenState)
stakingGenState.Params.BondDenom = ethermint.AttoPhoton
cfg.GenesisState[stakingtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&stakingGenState)
appGenStateJSON, err := json.MarshalIndent(cfg.GenesisState, "", " ")
if err != nil {
return err
}
genDoc := types.GenesisDoc{
ChainID: cfg.ChainID,
AppState: appGenStateJSON,
Validators: nil,
}
// generate empty genesis files for each validator and save
for i := 0; i < cfg.NumValidators; i++ {
if err := genDoc.SaveAs(genFiles[i]); err != nil {
return err
}
}
return nil
}
func writeFile(name string, dir string, contents []byte) error {
writePath := filepath.Join(dir)
file := filepath.Join(writePath, name)
err := tmos.EnsureDir(writePath, 0755)
if err != nil {
return err
}
return tmos.WriteFile(file, contents, 0644)
}