Skip to content

Commit

Permalink
Add add-trusted-peer command to config (#48)
Browse files Browse the repository at this point in the history
* Remove the global --config flag for chia-tools config and instead use it for the config subcommand to point to the chia config

* Add trusted peer command

* Add support for skipping confirmation with -y or --yes

* Allow specifying port

* Fix port logic, and log the port we're using

* Save wallet full_node_peers when swapping networks, and ensure we never have an empty list of peers

* Add port override example
  • Loading branch information
cmmarslender authored Dec 10, 2024
1 parent 4f7b8e2 commit dd01f13
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 37 deletions.
124 changes: 124 additions & 0 deletions cmd/config/addtrustedpeer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package config

import (
"encoding/hex"
"net"
"path"
"strconv"

"github.com/chia-network/go-chia-libs/pkg/config"
"github.com/chia-network/go-chia-libs/pkg/peerprotocol"
"github.com/chia-network/go-modules/pkg/slogs"
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/chia-network/chia-tools/internal/utils"
)

var (
skipConfirm bool
)

// addTrustedPeerCmd Adds a trusted peer to the config
var addTrustedPeerCmd = &cobra.Command{
Use: "add-trusted-peer",
Short: "Adds a trusted peer to the config file",
Example: `chia-tools config add-trusted-peer 1.2.3.4
# The following version will also override the port to use when connecting to this peer
chia-tools config add-trusted-peer 1.2.3.4 18444`,
Run: func(cmd *cobra.Command, args []string) {
chiaRoot, err := config.GetChiaRootPath()
if err != nil {
slogs.Logr.Fatal("Unable to determine CHIA_ROOT", "error", err)
}

// 1: Peer IP
// 2: Optional, port
if len(args) < 1 || len(args) > 2 {
slogs.Logr.Fatal("Unexpected number of arguments provided")
}

cfgPath := viper.GetString("config")
if cfgPath == "" {
// Use default chia root
cfgPath = path.Join(chiaRoot, "config", "config.yaml")
}

cfg, err := config.LoadConfigAtRoot(cfgPath, chiaRoot)
if err != nil {
slogs.Logr.Fatal("error loading chia config", "error", err)
}

peer := args[0]
port := cfg.FullNode.Port
if len(args) > 1 {
port64, err := strconv.ParseUint(args[1], 10, 16)
if err != nil {
slogs.Logr.Fatal("Invalid port provided")
}
port = uint16(port64)
}

ip := net.ParseIP(peer)
if ip == nil {
slogs.Logr.Fatal("Invalid IP address", "id", peer)
}
slogs.Logr.Info("Attempting to get peer id", "peer", peer, "port", port)

keypair, err := cfg.FullNode.SSL.LoadPublicKeyPair(chiaRoot)
if err != nil {
slogs.Logr.Fatal("Error loading certs from CHIA_ROOT", "CHIA_ROOT", chiaRoot, "error", err)
}
if keypair == nil {
slogs.Logr.Fatal("Error loading certs from CHIA_ROOT", "CHIA_ROOT", chiaRoot, "error", "keypair was nil")
}
conn, err := peerprotocol.NewConnection(
&ip,
peerprotocol.WithPeerPort(port),
peerprotocol.WithNetworkID(*cfg.SelectedNetwork),
peerprotocol.WithPeerKeyPair(*keypair),
)
if err != nil {
slogs.Logr.Fatal("Error creating connection", "error", err)
}
peerID, err := conn.PeerID()
if err != nil {
slogs.Logr.Fatal("Error getting peer id", "error", err)
}
peerIDStr := hex.EncodeToString(peerID[:])
slogs.Logr.Info("peer id received", "peer", peerIDStr)
if !utils.ConfirmAction("Would you like trust this peer? (y/N)", skipConfirm) {
slogs.Logr.Error("Cancelled")
}
cfg.Wallet.TrustedPeers[peerIDStr] = "Does_not_matter"

peerToAdd := config.Peer{
Host: ip.String(),
Port: port,
}

foundPeer := false
for idx, peer := range cfg.Wallet.FullNodePeers {
if peer.Host == ip.String() {
foundPeer = true
cfg.Wallet.FullNodePeers[idx] = peerToAdd
}
}
if !foundPeer {
cfg.Wallet.FullNodePeers = append(cfg.Wallet.FullNodePeers, peerToAdd)
}

err = cfg.Save()
if err != nil {
slogs.Logr.Fatal("error saving config", "error", err)
}

slogs.Logr.Info("Added trusted peer. Restart your chia services for the configuration to take effect")
},
}

func init() {
addTrustedPeerCmd.Flags().BoolVarP(&skipConfirm, "yes", "y", false, "Skip confirmation")
configCmd.AddCommand(addTrustedPeerCmd)
}
4 changes: 4 additions & 0 deletions cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package config

import (
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/chia-network/chia-tools/cmd"
)
Expand All @@ -13,5 +14,8 @@ var configCmd = &cobra.Command{
}

func init() {
configCmd.PersistentFlags().String("config", "", "existing config file to use (default is to look in $CHIA_ROOT)")
cobra.CheckErr(viper.BindPFlag("config", configCmd.PersistentFlags().Lookup("config")))

cmd.RootCmd.AddCommand(configCmd)
}
14 changes: 6 additions & 8 deletions cmd/config/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,22 @@ import (
var editCmd = &cobra.Command{
Use: "edit",
Short: "Edit an existing chia configuration file",
Example: `chia-tools config edit ~/.chia/mainnet/config/config.yaml --set full_node.port=58444 --set full_node.target_peer_count=10
Example: `chia-tools config edit --config ~/.chia/mainnet/config/config.yaml --set full_node.port=58444 --set full_node.target_peer_count=10
# The following version will discover the config file by inspecting CHIA_ROOT or using the default CHIA_ROOT
chia-tools config edit --set full_node.port=58444 --set full_node.target_peer_count=10`,
Run: func(cmd *cobra.Command, args []string) {
var cfgPath string

chiaRoot, err := config.GetChiaRootPath()
if err != nil {
slogs.Logr.Fatal("Unable to determine CHIA_ROOT", "error", err)
}

if len(args) > 1 {
if len(args) > 0 {
slogs.Logr.Fatal("Unexpected number of arguments provided")
} else if len(args) == 1 {
// Use the provided config path
cfgPath = args[0]
} else {
}

cfgPath := viper.GetString("config")
if cfgPath == "" {
// Use default chia root
cfgPath = path.Join(chiaRoot, "config", "config.yaml")
}
Expand Down
42 changes: 27 additions & 15 deletions cmd/network/switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ func init() {

// retainedSettings are the settings we want to keep track of when switching networks so we can swap back to them in the future
type retainedSettings struct {
DNSServers []string `json:"dns_servers"`
BootstrapPeers []string `json:"bootstrap_peers"`
StaticPeers []string `json:"static_peers"`
FullNodePeers []config.Peer `json:"full_node_peers"`
DNSServers []string `json:"dns_servers"`
BootstrapPeers []string `json:"bootstrap_peers"`
StaticPeers []string `json:"static_peers"`
FullNodePeers []config.Peer `json:"full_node_peers"`
WalletFullNodePeers []config.Peer `json:"wallet_full_node_peers"`
}

// SwitchNetwork implements the logic to swap networks
Expand Down Expand Up @@ -101,10 +102,11 @@ func SwitchNetwork(networkName string, checkForRunningNode bool) {
}

previousSettings := retainedSettings{
DNSServers: cfg.FullNode.DNSServers,
BootstrapPeers: cfg.Seeder.BootstrapPeers,
StaticPeers: cfg.Seeder.StaticPeers,
FullNodePeers: cfg.FullNode.FullNodePeers,
DNSServers: cfg.FullNode.DNSServers,
BootstrapPeers: cfg.Seeder.BootstrapPeers,
StaticPeers: cfg.Seeder.StaticPeers,
FullNodePeers: cfg.FullNode.FullNodePeers,
WalletFullNodePeers: cfg.Wallet.FullNodePeers,
}
marshalled, err := json.Marshal(previousSettings)
if err != nil {
Expand Down Expand Up @@ -174,6 +176,7 @@ func SwitchNetwork(networkName string, checkForRunningNode bool) {
dnsIntroducerHosts := []string{"dns-introducer.chia.net"}
fullNodePort := uint16(8444)
var fullnodePeers []config.Peer
var walletFullNodePeers []config.Peer
peersFilePath := "db/peers.dat"
walletPeersFilePath := "wallet/db/wallet_peers.dat"
bootstrapPeers := []string{"node.chia.net"}
Expand Down Expand Up @@ -202,6 +205,9 @@ func SwitchNetwork(networkName string, checkForRunningNode bool) {
if len(settingsToRestore.FullNodePeers) > 0 {
fullnodePeers = settingsToRestore.FullNodePeers
}
if len(settingsToRestore.WalletFullNodePeers) > 0 {
walletFullNodePeers = settingsToRestore.WalletFullNodePeers
}
}

if introFlag := viper.GetString("switch-introducer"); introFlag != "" {
Expand Down Expand Up @@ -247,13 +253,8 @@ func SwitchNetwork(networkName string, checkForRunningNode bool) {
Port: fullNodePort,
},
},
"wallet.dns_servers": dnsIntroducerHosts,
"wallet.full_node_peers": []config.Peer{
{
Host: "localhost",
Port: fullNodePort,
},
},
"wallet.dns_servers": dnsIntroducerHosts,
"wallet.full_node_peers": ensureAtLeastLocalPeer(walletFullNodePeers, fullNodePort),
"wallet.introducer_peer.host": introducerHost,
"wallet.introducer_peer.port": fullNodePort,
"wallet.wallet_peers_file_path": walletPeersFilePath,
Expand Down Expand Up @@ -286,6 +287,17 @@ func SwitchNetwork(networkName string, checkForRunningNode bool) {
slogs.Logr.Info("Complete")
}

func ensureAtLeastLocalPeer(peers []config.Peer, port uint16) []config.Peer {
if len(peers) == 0 {
peers = append(peers, config.Peer{
Host: "localhost",
Port: port,
})
}

return peers
}

func isConnectionRefused(err error) bool {
var netErr *net.OpError
if errors.As(err, &netErr) {
Expand Down
21 changes: 7 additions & 14 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/chia-network/go-modules/pkg/slogs"
)

var cfgFile string
var (
gitVersion string
buildTime string
Expand All @@ -37,26 +36,20 @@ func init() {
cobra.OnInitialize(initConfig)
cobra.OnInitialize(InitLogs)

RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.chia-tools.yaml)")
RootCmd.PersistentFlags().String("log-level", "info", "The log-level for the application, can be one of info, warn, error, debug.")
cobra.CheckErr(viper.BindPFlag("log-level", RootCmd.PersistentFlags().Lookup("log-level")))
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := os.UserHomeDir()
cobra.CheckErr(err)
// Find home directory.
home, err := os.UserHomeDir()
cobra.CheckErr(err)

// Search config in home directory with name ".chia-tools" (without extension).
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".chia-tools")
}
// Search config in home directory with name ".chia-tools" (without extension).
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".chia-tools")

viper.SetEnvPrefix("CHIA_TOOLS")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
Expand Down
21 changes: 21 additions & 0 deletions internal/utils/confirm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package utils

import (
"bufio"
"fmt"
"os"
"strings"
)

// ConfirmAction waits for the user to confirm with "yes" or "y"
func ConfirmAction(prompt string, skipConfirm bool) bool {
// Easy support for -y type flags to skip confirmation
if skipConfirm {
return true
}
fmt.Printf("%s ", prompt)
reader := bufio.NewReader(os.Stdin)
response, _ := reader.ReadString('\n')
response = strings.TrimSpace(strings.ToLower(response))
return response == "yes" || response == "y"
}

0 comments on commit dd01f13

Please sign in to comment.