github.com/kotalco/kotal@v0.3.0/clients/ethereum/nethermind_client.go (about) 1 package ethereum 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strings" 7 8 ethereumv1alpha1 "github.com/kotalco/kotal/apis/ethereum/v1alpha1" 9 "github.com/kotalco/kotal/controllers/shared" 10 corev1 "k8s.io/api/core/v1" 11 ) 12 13 const ( 14 // NethermindHomeDir is nethermind docker image home directory 15 NethermindHomeDir = "/home/nethermind" 16 ) 17 18 // NethermindClient is nethermind client 19 // https://github.com/NethermindEth/nethermind 20 type NethermindClient struct { 21 *ParityGenesis 22 node *ethereumv1alpha1.Node 23 } 24 25 // HomeDir returns besu client home directory 26 func (n *NethermindClient) HomeDir() string { 27 return NethermindHomeDir 28 } 29 30 func (n *NethermindClient) Command() []string { 31 return nil 32 } 33 34 func (n *NethermindClient) Env() []corev1.EnvVar { 35 return nil 36 } 37 38 // Args returns command line arguments required for client run 39 // NOTE: 40 // - Network ID can be set in genesis config 41 func (n *NethermindClient) Args() (args []string) { 42 43 node := n.node 44 45 args = append(args, NethermindDataPath, shared.PathData(n.HomeDir())) 46 args = append(args, NethermindP2PPort, fmt.Sprintf("%d", node.Spec.P2PPort)) 47 args = append(args, NethermindLogging, strings.ToUpper(string(node.Spec.Logging))) 48 49 if node.Spec.NodePrivateKeySecretName != "" { 50 // use enode private key in binary format 51 // that has been converted using nethermind_convert_enode_privatekey.sh script 52 args = append(args, NethermindNodePrivateKey, fmt.Sprintf("%s/kotal_nodekey", shared.PathData(n.HomeDir()))) 53 } 54 55 if len(node.Spec.StaticNodes) != 0 { 56 args = append(args, NethermindStaticNodesFile, fmt.Sprintf("%s/static-nodes.json", shared.PathConfig(n.HomeDir()))) 57 } 58 59 if len(node.Spec.Bootnodes) != 0 { 60 bootnodes := []string{} 61 for _, bootnode := range node.Spec.Bootnodes { 62 bootnodes = append(bootnodes, string(bootnode)) 63 } 64 args = append(args, NethermindBootnodes, strings.Join(bootnodes, ",")) 65 } 66 67 if node.Spec.Genesis == nil { 68 args = append(args, NethermindNetwork, node.Spec.Network) 69 } else { 70 // use empty config, because nethermind uses mainnet.cfg by default which can shadow some settings here 71 args = append(args, NethermindNetwork, fmt.Sprintf("%s/empty.cfg", shared.PathConfig(n.HomeDir()))) 72 args = append(args, NethermindGenesisFile, fmt.Sprintf("%s/genesis.json", shared.PathConfig(n.HomeDir()))) 73 args = append(args, NethermindDiscoveryEnabled, "false") 74 } 75 76 switch node.Spec.SyncMode { 77 case ethereumv1alpha1.FullSynchronization: 78 args = append(args, NethermindFastSync, "false") 79 args = append(args, NethermindFastBlocks, "false") 80 args = append(args, NethermindDownloadBodiesInFastSync, "false") 81 args = append(args, NethermindDownloadReceiptsInFastSync, "false") 82 case ethereumv1alpha1.FastSynchronization: 83 args = append(args, NethermindFastSync, "true") 84 args = append(args, NethermindFastBlocks, "true") 85 args = append(args, NethermindDownloadBodiesInFastSync, "true") 86 args = append(args, NethermindDownloadReceiptsInFastSync, "true") 87 } 88 89 if node.Spec.Miner { 90 args = append(args, NethermindMiningEnabled, "true") 91 args = append(args, NethermindMinerCoinbase, string(node.Spec.Coinbase)) 92 args = append(args, NethermindUnlockAccounts, fmt.Sprintf("[%s]", node.Spec.Coinbase)) 93 args = append(args, NethermindPasswordFiles, fmt.Sprintf("[%s/account.password]", shared.PathSecrets(n.HomeDir()))) 94 } 95 96 if node.Spec.RPC { 97 args = append(args, NethermindRPCHTTPEnabled, "true") 98 args = append(args, NethermindRPCHTTPPort, fmt.Sprintf("%d", node.Spec.RPCPort)) 99 args = append(args, NethermindRPCHTTPHost, shared.Host(node.Spec.RPC)) 100 // JSON-RPC API 101 apis := []string{} 102 for _, api := range node.Spec.RPCAPI { 103 apis = append(apis, string(api)) 104 } 105 commaSeperatedAPIs := strings.Join(apis, ",") 106 args = append(args, NethermindRPCHTTPAPI, commaSeperatedAPIs) 107 } 108 109 if node.Spec.Engine { 110 args = append(args, NethermindRPCEnginePort, fmt.Sprintf("%d", node.Spec.EnginePort)) 111 jwtSecretPath := fmt.Sprintf("%s/jwt.secret", shared.PathSecrets(n.HomeDir())) 112 args = append(args, NethermindRPCJwtSecretFile, jwtSecretPath) 113 } 114 args = append(args, NethermindRPCEngineHost, shared.Host(node.Spec.Engine)) 115 116 if node.Spec.WS { 117 args = append(args, NethermindRPCWSEnabled, "true") 118 args = append(args, NethermindRPCWSPort, fmt.Sprintf("%d", node.Spec.WSPort)) 119 // no option for ws host, ws uses same http host as JSON-RPC 120 // nethermind ws reuses enabled JSON-RPC modules 121 } 122 123 return args 124 } 125 126 // Genesis returns genesis config parameter 127 func (p *NethermindClient) Genesis() (string, error) { 128 return p.ParityGenesis.Genesis(p.node) 129 } 130 131 // EncodeStaticNodes returns the static nodes, one per line 132 func (n *NethermindClient) EncodeStaticNodes() string { 133 134 if len(n.node.Spec.StaticNodes) == 0 { 135 return "[]" 136 } 137 138 encoded, _ := json.Marshal(n.node.Spec.StaticNodes) 139 return string(encoded) 140 }