ceremonyclient/client/cmd/root.go
2024-10-14 16:44:03 -07:00

173 lines
3.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cmd
import (
"bytes"
"crypto/tls"
"encoding/hex"
"fmt"
"os"
"strings"
"github.com/cloudflare/circl/sign/ed448"
"github.com/multiformats/go-multiaddr"
mn "github.com/multiformats/go-multiaddr/net"
"github.com/spf13/cobra"
"golang.org/x/crypto/sha3"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"source.quilibrium.com/quilibrium/monorepo/node/config"
)
var configDirectory string
var signatureCheck bool = true
var NodeConfig *config.Config
var simulateFail bool
var LightNode bool = false
var DryRun bool = false
var rootCmd = &cobra.Command{
Use: "qclient",
Short: "Quilibrium RPC Client",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
if signatureCheck {
ex, err := os.Executable()
if err != nil {
panic(err)
}
b, err := os.ReadFile(ex)
if err != nil {
fmt.Println(
"Error encountered during signature check are you running this " +
"from source? (use --signature-check=false)",
)
panic(err)
}
checksum := sha3.Sum256(b)
digest, err := os.ReadFile(ex + ".dgst")
if err != nil {
fmt.Println("Digest file not found")
os.Exit(1)
}
parts := strings.Split(string(digest), " ")
if len(parts) != 2 {
fmt.Println("Invalid digest file format")
os.Exit(1)
}
digestBytes, err := hex.DecodeString(parts[1][:64])
if err != nil {
fmt.Println("Invalid digest file format")
os.Exit(1)
}
if !bytes.Equal(checksum[:], digestBytes) {
fmt.Println("Invalid digest for node")
os.Exit(1)
}
count := 0
for i := 1; i <= len(config.Signatories); i++ {
signatureFile := fmt.Sprintf(ex+".dgst.sig.%d", i)
sig, err := os.ReadFile(signatureFile)
if err != nil {
continue
}
pubkey, _ := hex.DecodeString(config.Signatories[i-1])
if !ed448.Verify(pubkey, digest, sig, "") {
fmt.Printf("Failed signature check for signatory #%d\n", i)
os.Exit(1)
}
count++
}
if count < len(config.Signatories)/2+len(config.Signatories)%2 {
fmt.Printf("Quorum on signatures not met")
os.Exit(1)
}
fmt.Println("Signature check passed")
} else {
fmt.Println("Signature check bypassed, be sure you know what you're doing")
}
_, err := os.Stat(configDirectory)
if os.IsNotExist(err) {
fmt.Printf("config directory doesn't exist: %s\n", configDirectory)
os.Exit(1)
}
NodeConfig, err = config.LoadConfig(configDirectory, "", false)
if err != nil {
fmt.Printf("invalid config directory: %s\n", configDirectory)
os.Exit(1)
}
if NodeConfig.ListenGRPCMultiaddr == "" {
fmt.Println("gRPC not enabled, using light node")
LightNode = true
}
},
}
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
func GetGRPCClient() (*grpc.ClientConn, error) {
addr := "rpc.quilibrium.com:8337"
credentials := credentials.NewTLS(&tls.Config{InsecureSkipVerify: false})
if !LightNode {
ma, err := multiaddr.NewMultiaddr(NodeConfig.ListenGRPCMultiaddr)
if err != nil {
panic(err)
}
_, addr, err = mn.DialArgs(ma)
if err != nil {
panic(err)
}
credentials = insecure.NewCredentials()
}
return grpc.Dial(
addr,
grpc.WithTransportCredentials(
credentials,
),
grpc.WithDefaultCallOptions(
grpc.MaxCallSendMsgSize(600*1024*1024),
grpc.MaxCallRecvMsgSize(600*1024*1024),
),
)
}
func init() {
rootCmd.PersistentFlags().StringVar(
&configDirectory,
"config",
".config/",
"config directory (default is .config/)",
)
rootCmd.PersistentFlags().BoolVar(
&DryRun,
"dry-run",
false,
"runs the command (if applicable) without actually mutating state (printing effect output)",
)
rootCmd.PersistentFlags().BoolVar(
&signatureCheck,
"signature-check",
true,
"bypass signature check (not recommended for binaries)",
)
}