Duke
1 year ago
2 changed files with 0 additions and 289 deletions
@ -1,257 +0,0 @@ |
|||||
package main |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"flag" |
|
||||
"fmt" |
|
||||
"net" |
|
||||
"os" |
|
||||
"os/signal" |
|
||||
"syscall" |
|
||||
"time" |
|
||||
|
|
||||
"github.com/sirupsen/logrus" |
|
||||
"google.golang.org/grpc" |
|
||||
"google.golang.org/grpc/credentials" |
|
||||
"google.golang.org/grpc/peer" |
|
||||
"google.golang.org/grpc/reflection" |
|
||||
|
|
||||
"git.hush.is/hush/lightwalletd/common" |
|
||||
"git.hush.is/hush/lightwalletd/frontend" |
|
||||
"git.hush.is/hush/lightwalletd/walletrpc" |
|
||||
) |
|
||||
|
|
||||
var log *logrus.Entry |
|
||||
var logger = logrus.New() |
|
||||
|
|
||||
func init() { |
|
||||
logger.SetFormatter(&logrus.TextFormatter{ |
|
||||
//DisableColors: true, |
|
||||
FullTimestamp: true, |
|
||||
DisableLevelTruncation: true, |
|
||||
}) |
|
||||
|
|
||||
log = logger.WithFields(logrus.Fields{ |
|
||||
"app": "frontend-grpc", |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// TODO stream logging |
|
||||
|
|
||||
func LoggingInterceptor() grpc.ServerOption { |
|
||||
return grpc.UnaryInterceptor(logInterceptor) |
|
||||
} |
|
||||
|
|
||||
func logInterceptor( |
|
||||
ctx context.Context, |
|
||||
req interface{}, |
|
||||
info *grpc.UnaryServerInfo, |
|
||||
handler grpc.UnaryHandler, |
|
||||
) (interface{}, error) { |
|
||||
reqLog := loggerFromContext(ctx) |
|
||||
start := time.Now() |
|
||||
|
|
||||
resp, err := handler(ctx, req) |
|
||||
|
|
||||
entry := reqLog.WithFields(logrus.Fields{ |
|
||||
"method": info.FullMethod, |
|
||||
"duration": time.Since(start), |
|
||||
"error": err, |
|
||||
}) |
|
||||
|
|
||||
if err != nil { |
|
||||
entry.Error("call failed") |
|
||||
} else { |
|
||||
entry.Info("method called") |
|
||||
} |
|
||||
|
|
||||
return resp, err |
|
||||
} |
|
||||
|
|
||||
func loggerFromContext(ctx context.Context) *logrus.Entry { |
|
||||
// TODO: anonymize the addresses. cryptopan? |
|
||||
if peerInfo, ok := peer.FromContext(ctx); ok { |
|
||||
return log.WithFields(logrus.Fields{"peer_addr": peerInfo.Addr}) |
|
||||
} |
|
||||
return log.WithFields(logrus.Fields{"peer_addr": "unknown"}) |
|
||||
} |
|
||||
|
|
||||
type Options struct { |
|
||||
bindAddr string `json:"bind_address,omitempty"` |
|
||||
tlsCertPath string `json:"tls_cert_path,omitempty"` |
|
||||
tlsKeyPath string `json:"tls_cert_key,omitempty"` |
|
||||
noTLS bool `json:no_tls,omitempty` |
|
||||
logLevel uint64 `json:"log_level,omitempty"` |
|
||||
logPath string `json:"log_file,omitempty"` |
|
||||
hush3ConfPath string `json:"hush3_conf,omitempty"` |
|
||||
cacheSize int `json:"hush3_conf,omitempty"` |
|
||||
} |
|
||||
|
|
||||
func main() { |
|
||||
var version = "0.1.1" // set version number |
|
||||
|
|
||||
opts := &Options{} |
|
||||
flag.StringVar(&opts.bindAddr, "bind-addr", "127.0.0.1:9067", "the address to listen on") |
|
||||
flag.StringVar(&opts.tlsCertPath, "tls-cert", "", "the path to a TLS certificate (optional)") |
|
||||
flag.StringVar(&opts.tlsKeyPath, "tls-key", "", "the path to a TLS key file (optional)") |
|
||||
flag.BoolVar(&opts.noTLS, "no-tls", false, "Disable TLS, serve un-encrypted traffic.") |
|
||||
flag.Uint64Var(&opts.logLevel, "log-level", uint64(logrus.InfoLevel), "log level (logrus 1-7)") |
|
||||
flag.StringVar(&opts.logPath, "log-file", "", "log file to write to") |
|
||||
flag.StringVar(&opts.hush3ConfPath, "conf-file", "", "conf file to pull RPC creds from") |
|
||||
flag.IntVar(&opts.cacheSize, "cache-size", 40000, "number of blocks to hold in the cache") |
|
||||
|
|
||||
// creating --version as a requirement of help2man |
|
||||
if len(os.Args) > 1 && (os.Args[1] == "--version" || os.Args[1] == "-v") { |
|
||||
fmt.Printf("Hush lightwalletd version " + version + "\n") |
|
||||
os.Exit(0) |
|
||||
} |
|
||||
|
|
||||
// TODO prod metrics |
|
||||
// TODO support config from file and env vars |
|
||||
flag.Parse() |
|
||||
|
|
||||
if opts.hush3ConfPath == "" { |
|
||||
flag.Usage() |
|
||||
os.Exit(1) |
|
||||
} |
|
||||
|
|
||||
if !opts.noTLS && (opts.tlsCertPath == "" || opts.tlsKeyPath == "") { |
|
||||
println("Please specify a TLS certificate/key to use. You can use a self-signed certificate.") |
|
||||
println("See https://git.hush.is/hush/lightwalletd/src/branch/master/README.md#running-your-own-sdl-lightwalletd") |
|
||||
os.Exit(1) |
|
||||
} |
|
||||
|
|
||||
if opts.logPath != "" { |
|
||||
// instead write parsable logs for logstash/splunk/etc |
|
||||
output, err := os.OpenFile(opts.logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) |
|
||||
if err != nil { |
|
||||
log.WithFields(logrus.Fields{ |
|
||||
"error": err, |
|
||||
"path": opts.logPath, |
|
||||
}).Fatal("couldn't open log file") |
|
||||
} |
|
||||
defer output.Close() |
|
||||
logger.SetOutput(output) |
|
||||
logger.SetFormatter(&logrus.JSONFormatter{}) |
|
||||
} |
|
||||
|
|
||||
logger.SetLevel(logrus.Level(opts.logLevel)) |
|
||||
|
|
||||
// gRPC initialization |
|
||||
var server *grpc.Server |
|
||||
|
|
||||
if !opts.noTLS && (opts.tlsCertPath != "" && opts.tlsKeyPath != "") { |
|
||||
transportCreds, err := credentials.NewServerTLSFromFile(opts.tlsCertPath, opts.tlsKeyPath) |
|
||||
if err != nil { |
|
||||
log.WithFields(logrus.Fields{ |
|
||||
"cert_file": opts.tlsCertPath, |
|
||||
"key_path": opts.tlsKeyPath, |
|
||||
"error": err, |
|
||||
}).Fatal("couldn't load TLS credentials") |
|
||||
} |
|
||||
server = grpc.NewServer(grpc.Creds(transportCreds), LoggingInterceptor()) |
|
||||
} else { |
|
||||
server = grpc.NewServer(LoggingInterceptor()) |
|
||||
} |
|
||||
|
|
||||
// Enable reflection for debugging |
|
||||
if opts.logLevel >= uint64(logrus.WarnLevel) { |
|
||||
reflection.Register(server) |
|
||||
} |
|
||||
|
|
||||
// Initialize Hush RPC client. Right now (Jan 2018) this is only for |
|
||||
// sending transactions, but in the future it could back a different type |
|
||||
// of block streamer. |
|
||||
|
|
||||
rpcClient, err := frontend.NewZRPCFromConf(opts.hush3ConfPath) |
|
||||
if err != nil { |
|
||||
log.WithFields(logrus.Fields{ |
|
||||
"error": err, |
|
||||
}).Warn("HUSH3.conf failed, will try empty credentials for rpc") |
|
||||
|
|
||||
rpcClient, err = frontend.NewZRPCFromCreds("127.0.0.1:18031", "", "") |
|
||||
|
|
||||
if err != nil { |
|
||||
log.WithFields(logrus.Fields{ |
|
||||
"error": err, |
|
||||
}).Warn("couldn't start rpc conn. won't be able to send transactions") |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Get the sapling activation height from the RPC |
|
||||
saplingHeight, blockHeight, chainName, branchID, difficulty, longestchain, notarized, err := common.GetSaplingInfo(rpcClient) |
|
||||
if err != nil { |
|
||||
log.WithFields(logrus.Fields{ |
|
||||
"error": err, |
|
||||
}).Warn("Unable to get sapling activation height") |
|
||||
} |
|
||||
|
|
||||
log.Info("Got sapling height ", saplingHeight, " chain ", chainName, " branchID ", branchID, " difficulty ", difficulty, longestchain, " longestchain ", notarized, " notarized ") |
|
||||
|
|
||||
// Get the Coinsupply from the RPC |
|
||||
result, coin, height, supply, zfunds, total, err := common.GetCoinsupply(rpcClient) |
|
||||
if err != nil { |
|
||||
log.WithFields(logrus.Fields{ |
|
||||
"error": err, |
|
||||
}).Warn("Unable to get coinsupply") |
|
||||
} |
|
||||
|
|
||||
log.Info(" result ", result, " coin ", coin, " height", height, "supply", supply, "zfunds", zfunds, "total", total) |
|
||||
|
|
||||
// Initialize the cache |
|
||||
cache := common.NewBlockCache(opts.cacheSize) |
|
||||
|
|
||||
stopChan := make(chan bool, 1) |
|
||||
|
|
||||
// Start the block cache importer at latestblock - 100k(cache size) |
|
||||
cacheStart := blockHeight - opts.cacheSize |
|
||||
if cacheStart < saplingHeight { |
|
||||
cacheStart = saplingHeight |
|
||||
} |
|
||||
|
|
||||
go common.BlockIngestor(rpcClient, cache, log, stopChan, cacheStart) |
|
||||
|
|
||||
// Compact transaction service initialization |
|
||||
service, err := frontend.NewSQLiteStreamer(rpcClient, cache, log) |
|
||||
if err != nil { |
|
||||
log.WithFields(logrus.Fields{ |
|
||||
"error": err, |
|
||||
}).Fatal("couldn't create SQL backend") |
|
||||
} |
|
||||
defer service.(*frontend.SqlStreamer).GracefulStop() |
|
||||
|
|
||||
// Register service |
|
||||
walletrpc.RegisterCompactTxStreamerServer(server, service) |
|
||||
|
|
||||
// Start listening |
|
||||
listener, err := net.Listen("tcp", opts.bindAddr) |
|
||||
if err != nil { |
|
||||
log.WithFields(logrus.Fields{ |
|
||||
"bind_addr": opts.bindAddr, |
|
||||
"error": err, |
|
||||
}).Fatal("couldn't create listener") |
|
||||
} |
|
||||
|
|
||||
// Signal handler for graceful stops |
|
||||
signals := make(chan os.Signal, 1) |
|
||||
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) |
|
||||
go func() { |
|
||||
s := <-signals |
|
||||
log.WithFields(logrus.Fields{ |
|
||||
"signal": s.String(), |
|
||||
}).Info("caught signal, stopping gRPC server") |
|
||||
// Stop the server |
|
||||
server.GracefulStop() |
|
||||
// Stop the block ingestor |
|
||||
stopChan <- true |
|
||||
}() |
|
||||
|
|
||||
log.Infof("Starting gRPC server on %s", opts.bindAddr) |
|
||||
|
|
||||
err = server.Serve(listener) |
|
||||
if err != nil { |
|
||||
log.WithFields(logrus.Fields{ |
|
||||
"error": err, |
|
||||
}).Fatal("gRPC server exited") |
|
||||
} |
|
||||
} |
|
@ -1,32 +0,0 @@ |
|||||
// Copyright 2021 The Hush developers |
|
||||
// Released under the GPLv3 |
|
||||
package main |
|
||||
|
|
||||
import ( |
|
||||
"os" |
|
||||
"testing" |
|
||||
) |
|
||||
|
|
||||
// TestFileExists checks whether or not the file exists |
|
||||
func TestFileExists(t *testing.T) { |
|
||||
if fileExists("nonexistent-file") { |
|
||||
t.Fatal("fileExists unexpected success") |
|
||||
} |
|
||||
// If the path exists but is a directory, should return false |
|
||||
if fileExists(".") { |
|
||||
t.Fatal("fileExists unexpected success") |
|
||||
} |
|
||||
// The following file should exist, it's what's being tested |
|
||||
if !fileExists("main.go") { |
|
||||
t.Fatal("fileExists failed") |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// fileExists checks if file exists and is not directory to prevent further errors |
|
||||
func fileExists(filename string) bool { |
|
||||
info, err := os.Stat(filename) |
|
||||
if os.IsNotExist(err) { |
|
||||
return false |
|
||||
} |
|
||||
return !info.IsDir() |
|
||||
} |
|
Loading…
Reference in new issue