Skip to content

Commit dd01f13

Browse files
authored
Add add-trusted-peer command to config (#48)
* 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
1 parent 4f7b8e2 commit dd01f13

File tree

6 files changed

+189
-37
lines changed

6 files changed

+189
-37
lines changed

cmd/config/addtrustedpeer.go

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package config
2+
3+
import (
4+
"encoding/hex"
5+
"net"
6+
"path"
7+
"strconv"
8+
9+
"github.com/chia-network/go-chia-libs/pkg/config"
10+
"github.com/chia-network/go-chia-libs/pkg/peerprotocol"
11+
"github.com/chia-network/go-modules/pkg/slogs"
12+
"github.com/spf13/cobra"
13+
"github.com/spf13/viper"
14+
15+
"github.com/chia-network/chia-tools/internal/utils"
16+
)
17+
18+
var (
19+
skipConfirm bool
20+
)
21+
22+
// addTrustedPeerCmd Adds a trusted peer to the config
23+
var addTrustedPeerCmd = &cobra.Command{
24+
Use: "add-trusted-peer",
25+
Short: "Adds a trusted peer to the config file",
26+
Example: `chia-tools config add-trusted-peer 1.2.3.4
27+
28+
# The following version will also override the port to use when connecting to this peer
29+
chia-tools config add-trusted-peer 1.2.3.4 18444`,
30+
Run: func(cmd *cobra.Command, args []string) {
31+
chiaRoot, err := config.GetChiaRootPath()
32+
if err != nil {
33+
slogs.Logr.Fatal("Unable to determine CHIA_ROOT", "error", err)
34+
}
35+
36+
// 1: Peer IP
37+
// 2: Optional, port
38+
if len(args) < 1 || len(args) > 2 {
39+
slogs.Logr.Fatal("Unexpected number of arguments provided")
40+
}
41+
42+
cfgPath := viper.GetString("config")
43+
if cfgPath == "" {
44+
// Use default chia root
45+
cfgPath = path.Join(chiaRoot, "config", "config.yaml")
46+
}
47+
48+
cfg, err := config.LoadConfigAtRoot(cfgPath, chiaRoot)
49+
if err != nil {
50+
slogs.Logr.Fatal("error loading chia config", "error", err)
51+
}
52+
53+
peer := args[0]
54+
port := cfg.FullNode.Port
55+
if len(args) > 1 {
56+
port64, err := strconv.ParseUint(args[1], 10, 16)
57+
if err != nil {
58+
slogs.Logr.Fatal("Invalid port provided")
59+
}
60+
port = uint16(port64)
61+
}
62+
63+
ip := net.ParseIP(peer)
64+
if ip == nil {
65+
slogs.Logr.Fatal("Invalid IP address", "id", peer)
66+
}
67+
slogs.Logr.Info("Attempting to get peer id", "peer", peer, "port", port)
68+
69+
keypair, err := cfg.FullNode.SSL.LoadPublicKeyPair(chiaRoot)
70+
if err != nil {
71+
slogs.Logr.Fatal("Error loading certs from CHIA_ROOT", "CHIA_ROOT", chiaRoot, "error", err)
72+
}
73+
if keypair == nil {
74+
slogs.Logr.Fatal("Error loading certs from CHIA_ROOT", "CHIA_ROOT", chiaRoot, "error", "keypair was nil")
75+
}
76+
conn, err := peerprotocol.NewConnection(
77+
&ip,
78+
peerprotocol.WithPeerPort(port),
79+
peerprotocol.WithNetworkID(*cfg.SelectedNetwork),
80+
peerprotocol.WithPeerKeyPair(*keypair),
81+
)
82+
if err != nil {
83+
slogs.Logr.Fatal("Error creating connection", "error", err)
84+
}
85+
peerID, err := conn.PeerID()
86+
if err != nil {
87+
slogs.Logr.Fatal("Error getting peer id", "error", err)
88+
}
89+
peerIDStr := hex.EncodeToString(peerID[:])
90+
slogs.Logr.Info("peer id received", "peer", peerIDStr)
91+
if !utils.ConfirmAction("Would you like trust this peer? (y/N)", skipConfirm) {
92+
slogs.Logr.Error("Cancelled")
93+
}
94+
cfg.Wallet.TrustedPeers[peerIDStr] = "Does_not_matter"
95+
96+
peerToAdd := config.Peer{
97+
Host: ip.String(),
98+
Port: port,
99+
}
100+
101+
foundPeer := false
102+
for idx, peer := range cfg.Wallet.FullNodePeers {
103+
if peer.Host == ip.String() {
104+
foundPeer = true
105+
cfg.Wallet.FullNodePeers[idx] = peerToAdd
106+
}
107+
}
108+
if !foundPeer {
109+
cfg.Wallet.FullNodePeers = append(cfg.Wallet.FullNodePeers, peerToAdd)
110+
}
111+
112+
err = cfg.Save()
113+
if err != nil {
114+
slogs.Logr.Fatal("error saving config", "error", err)
115+
}
116+
117+
slogs.Logr.Info("Added trusted peer. Restart your chia services for the configuration to take effect")
118+
},
119+
}
120+
121+
func init() {
122+
addTrustedPeerCmd.Flags().BoolVarP(&skipConfirm, "yes", "y", false, "Skip confirmation")
123+
configCmd.AddCommand(addTrustedPeerCmd)
124+
}

cmd/config/config.go

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package config
22

33
import (
44
"github.com/spf13/cobra"
5+
"github.com/spf13/viper"
56

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

1516
func init() {
17+
configCmd.PersistentFlags().String("config", "", "existing config file to use (default is to look in $CHIA_ROOT)")
18+
cobra.CheckErr(viper.BindPFlag("config", configCmd.PersistentFlags().Lookup("config")))
19+
1620
cmd.RootCmd.AddCommand(configCmd)
1721
}

cmd/config/edit.go

+6-8
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,22 @@ import (
1313
var editCmd = &cobra.Command{
1414
Use: "edit",
1515
Short: "Edit an existing chia configuration file",
16-
Example: `chia-tools config edit ~/.chia/mainnet/config/config.yaml --set full_node.port=58444 --set full_node.target_peer_count=10
16+
Example: `chia-tools config edit --config ~/.chia/mainnet/config/config.yaml --set full_node.port=58444 --set full_node.target_peer_count=10
1717
1818
# The following version will discover the config file by inspecting CHIA_ROOT or using the default CHIA_ROOT
1919
chia-tools config edit --set full_node.port=58444 --set full_node.target_peer_count=10`,
2020
Run: func(cmd *cobra.Command, args []string) {
21-
var cfgPath string
22-
2321
chiaRoot, err := config.GetChiaRootPath()
2422
if err != nil {
2523
slogs.Logr.Fatal("Unable to determine CHIA_ROOT", "error", err)
2624
}
2725

28-
if len(args) > 1 {
26+
if len(args) > 0 {
2927
slogs.Logr.Fatal("Unexpected number of arguments provided")
30-
} else if len(args) == 1 {
31-
// Use the provided config path
32-
cfgPath = args[0]
33-
} else {
28+
}
29+
30+
cfgPath := viper.GetString("config")
31+
if cfgPath == "" {
3432
// Use default chia root
3533
cfgPath = path.Join(chiaRoot, "config", "config.yaml")
3634
}

cmd/network/switch.go

+27-15
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ func init() {
4343

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

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

103104
previousSettings := retainedSettings{
104-
DNSServers: cfg.FullNode.DNSServers,
105-
BootstrapPeers: cfg.Seeder.BootstrapPeers,
106-
StaticPeers: cfg.Seeder.StaticPeers,
107-
FullNodePeers: cfg.FullNode.FullNodePeers,
105+
DNSServers: cfg.FullNode.DNSServers,
106+
BootstrapPeers: cfg.Seeder.BootstrapPeers,
107+
StaticPeers: cfg.Seeder.StaticPeers,
108+
FullNodePeers: cfg.FullNode.FullNodePeers,
109+
WalletFullNodePeers: cfg.Wallet.FullNodePeers,
108110
}
109111
marshalled, err := json.Marshal(previousSettings)
110112
if err != nil {
@@ -174,6 +176,7 @@ func SwitchNetwork(networkName string, checkForRunningNode bool) {
174176
dnsIntroducerHosts := []string{"dns-introducer.chia.net"}
175177
fullNodePort := uint16(8444)
176178
var fullnodePeers []config.Peer
179+
var walletFullNodePeers []config.Peer
177180
peersFilePath := "db/peers.dat"
178181
walletPeersFilePath := "wallet/db/wallet_peers.dat"
179182
bootstrapPeers := []string{"node.chia.net"}
@@ -202,6 +205,9 @@ func SwitchNetwork(networkName string, checkForRunningNode bool) {
202205
if len(settingsToRestore.FullNodePeers) > 0 {
203206
fullnodePeers = settingsToRestore.FullNodePeers
204207
}
208+
if len(settingsToRestore.WalletFullNodePeers) > 0 {
209+
walletFullNodePeers = settingsToRestore.WalletFullNodePeers
210+
}
205211
}
206212

207213
if introFlag := viper.GetString("switch-introducer"); introFlag != "" {
@@ -247,13 +253,8 @@ func SwitchNetwork(networkName string, checkForRunningNode bool) {
247253
Port: fullNodePort,
248254
},
249255
},
250-
"wallet.dns_servers": dnsIntroducerHosts,
251-
"wallet.full_node_peers": []config.Peer{
252-
{
253-
Host: "localhost",
254-
Port: fullNodePort,
255-
},
256-
},
256+
"wallet.dns_servers": dnsIntroducerHosts,
257+
"wallet.full_node_peers": ensureAtLeastLocalPeer(walletFullNodePeers, fullNodePort),
257258
"wallet.introducer_peer.host": introducerHost,
258259
"wallet.introducer_peer.port": fullNodePort,
259260
"wallet.wallet_peers_file_path": walletPeersFilePath,
@@ -286,6 +287,17 @@ func SwitchNetwork(networkName string, checkForRunningNode bool) {
286287
slogs.Logr.Info("Complete")
287288
}
288289

290+
func ensureAtLeastLocalPeer(peers []config.Peer, port uint16) []config.Peer {
291+
if len(peers) == 0 {
292+
peers = append(peers, config.Peer{
293+
Host: "localhost",
294+
Port: port,
295+
})
296+
}
297+
298+
return peers
299+
}
300+
289301
func isConnectionRefused(err error) bool {
290302
var netErr *net.OpError
291303
if errors.As(err, &netErr) {

cmd/root.go

+7-14
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/chia-network/go-modules/pkg/slogs"
1212
)
1313

14-
var cfgFile string
1514
var (
1615
gitVersion string
1716
buildTime string
@@ -37,26 +36,20 @@ func init() {
3736
cobra.OnInitialize(initConfig)
3837
cobra.OnInitialize(InitLogs)
3938

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

4543
// initConfig reads in config file and ENV variables if set.
4644
func initConfig() {
47-
if cfgFile != "" {
48-
// Use config file from the flag.
49-
viper.SetConfigFile(cfgFile)
50-
} else {
51-
// Find home directory.
52-
home, err := os.UserHomeDir()
53-
cobra.CheckErr(err)
45+
// Find home directory.
46+
home, err := os.UserHomeDir()
47+
cobra.CheckErr(err)
5448

55-
// Search config in home directory with name ".chia-tools" (without extension).
56-
viper.AddConfigPath(home)
57-
viper.SetConfigType("yaml")
58-
viper.SetConfigName(".chia-tools")
59-
}
49+
// Search config in home directory with name ".chia-tools" (without extension).
50+
viper.AddConfigPath(home)
51+
viper.SetConfigType("yaml")
52+
viper.SetConfigName(".chia-tools")
6053

6154
viper.SetEnvPrefix("CHIA_TOOLS")
6255
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))

internal/utils/confirm.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package utils
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"os"
7+
"strings"
8+
)
9+
10+
// ConfirmAction waits for the user to confirm with "yes" or "y"
11+
func ConfirmAction(prompt string, skipConfirm bool) bool {
12+
// Easy support for -y type flags to skip confirmation
13+
if skipConfirm {
14+
return true
15+
}
16+
fmt.Printf("%s ", prompt)
17+
reader := bufio.NewReader(os.Stdin)
18+
response, _ := reader.ReadString('\n')
19+
response = strings.TrimSpace(strings.ToLower(response))
20+
return response == "yes" || response == "y"
21+
}

0 commit comments

Comments
 (0)