github.com/prysmaticlabs/prysm@v1.4.4/tools/deployContract/deployContract.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "context" 6 "fmt" 7 "io/ioutil" 8 "math/big" 9 "os" 10 "time" 11 12 "github.com/ethereum/go-ethereum/accounts/abi/bind" 13 "github.com/ethereum/go-ethereum/accounts/keystore" 14 "github.com/ethereum/go-ethereum/common" 15 "github.com/ethereum/go-ethereum/crypto" 16 "github.com/ethereum/go-ethereum/ethclient" 17 "github.com/ethereum/go-ethereum/rpc" 18 contracts "github.com/prysmaticlabs/prysm/contracts/deposit-contract" 19 "github.com/prysmaticlabs/prysm/shared/version" 20 "github.com/sirupsen/logrus" 21 "github.com/urfave/cli/v2" 22 prefixed "github.com/x-cray/logrus-prefixed-formatter" 23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 k8s "k8s.io/client-go/kubernetes" 25 "k8s.io/client-go/rest" 26 ) 27 28 func main() { 29 var keystoreUTCPath string 30 var ipcPath string 31 var passwordFile string 32 var httpPath string 33 var privKeyString string 34 var k8sConfigMapName string 35 var drainAddress string 36 37 customFormatter := new(prefixed.TextFormatter) 38 customFormatter.TimestampFormat = "2006-01-02 15:04:05" 39 customFormatter.FullTimestamp = true 40 logrus.SetFormatter(customFormatter) 41 log := logrus.WithField("prefix", "main") 42 43 app := cli.App{} 44 app.Name = "deployDepositContract" 45 app.Usage = "this is a util to deploy deposit contract" 46 app.Version = version.Version() 47 app.Flags = []cli.Flag{ 48 &cli.StringFlag{ 49 Name: "keystoreUTCPath", 50 Usage: "Location of keystore", 51 Destination: &keystoreUTCPath, 52 }, 53 &cli.StringFlag{ 54 Name: "ipcPath", 55 Usage: "Filename for IPC socket/pipe within the datadir", 56 Destination: &ipcPath, 57 }, 58 &cli.StringFlag{ 59 Name: "httpPath", 60 Value: "http://localhost:8545/", 61 Usage: "HTTP-RPC server listening interface", 62 Destination: &httpPath, 63 }, 64 &cli.StringFlag{ 65 Name: "passwordFile", 66 Value: "./password.txt", 67 Usage: "Password file for unlock account", 68 Destination: &passwordFile, 69 }, 70 &cli.StringFlag{ 71 Name: "privKey", 72 Usage: "Private key to unlock account", 73 Destination: &privKeyString, 74 }, 75 &cli.StringFlag{ 76 Name: "k8sConfig", 77 Usage: "Name of kubernetes config map to update with the contract address", 78 Destination: &k8sConfigMapName, 79 }, 80 &cli.StringFlag{ 81 Name: "drainAddress", 82 Value: "", 83 Usage: "The drain address to specify in the contract. The default will be msg.sender", 84 Destination: &drainAddress, 85 }, 86 } 87 88 app.Action = func(c *cli.Context) error { 89 // Set up RPC client 90 var rpcClient *rpc.Client 91 var err error 92 var txOps *bind.TransactOpts 93 94 // Uses HTTP-RPC if IPC is not set 95 if ipcPath == "" { 96 rpcClient, err = rpc.Dial(httpPath) 97 } else { 98 rpcClient, err = rpc.Dial(ipcPath) 99 } 100 if err != nil { 101 return err 102 } 103 104 client := ethclient.NewClient(rpcClient) 105 106 // User inputs private key, sign tx with private key 107 if privKeyString != "" { 108 privKey, err := crypto.HexToECDSA(privKeyString) 109 if err != nil { 110 log.Fatal(err) 111 } 112 txOps, err = bind.NewKeyedTransactorWithChainID(privKey, big.NewInt(1337)) 113 if err != nil { 114 log.Fatal(err) 115 } 116 txOps.Value = big.NewInt(0) 117 txOps.GasLimit = 4000000 118 txOps.Context = context.Background() 119 // User inputs keystore json file, sign tx with keystore json 120 } else { 121 // #nosec - Inclusion of file via variable is OK for this tool. 122 file, err := os.Open(passwordFile) 123 if err != nil { 124 return err 125 } 126 127 scanner := bufio.NewScanner(file) 128 scanner.Split(bufio.ScanWords) 129 scanner.Scan() 130 password := scanner.Text() 131 132 // #nosec - Inclusion of file via variable is OK for this tool. 133 keyJSON, err := ioutil.ReadFile(keystoreUTCPath) 134 if err != nil { 135 return err 136 } 137 privKey, err := keystore.DecryptKey(keyJSON, password) 138 if err != nil { 139 return err 140 } 141 142 txOps, err = bind.NewKeyedTransactorWithChainID(privKey.PrivateKey, big.NewInt(1337)) 143 if err != nil { 144 log.Fatal(err) 145 } 146 txOps.Value = big.NewInt(0) 147 txOps.GasLimit = 4000000 148 txOps.Context = context.Background() 149 } 150 151 drain := txOps.From 152 if drainAddress != "" { 153 drain = common.HexToAddress(drainAddress) 154 } 155 156 txOps.GasPrice = big.NewInt(10 * 1e9 /* 10 gwei */) 157 158 // Deploy validator registration contract 159 addr, tx, _, err := contracts.DeployDepositContract( 160 txOps, 161 client, 162 drain, 163 ) 164 165 if err != nil { 166 return err 167 } 168 169 // Wait for contract to mine 170 for pending := true; pending; _, pending, err = client.TransactionByHash(context.Background(), tx.Hash()) { 171 if err != nil { 172 return err 173 } 174 time.Sleep(1 * time.Second) 175 } 176 177 log.WithFields(logrus.Fields{ 178 "address": addr.Hex(), 179 }).Info("New contract deployed") 180 181 if k8sConfigMapName != "" { 182 if err := updateKubernetesConfigMap(context.Background(), addr.Hex()); err != nil { 183 log.Fatalf("Failed to update kubernetes config map: %v", err) 184 } else { 185 log.Printf("Updated config map %s", k8sConfigMapName) 186 } 187 } 188 return nil 189 } 190 191 err := app.Run(os.Args) 192 if err != nil { 193 log.Fatal(err) 194 } 195 } 196 197 // updateKubernetesConfigMap in the beacon-chain namespace. This specifically 198 // updates the data value for DEPOSIT_CONTRACT_ADDRESS. 199 func updateKubernetesConfigMap(ctx context.Context, contractAddr string) error { 200 config, err := rest.InClusterConfig() 201 if err != nil { 202 return err 203 } 204 205 client, err := k8s.NewForConfig(config) 206 if err != nil { 207 return err 208 } 209 210 cm, err := client.CoreV1().ConfigMaps("beacon-chain").Get(ctx, "beacon-config", metav1.GetOptions{}) 211 if err != nil { 212 return err 213 } 214 215 if cm.Data["DEPOSIT_CONTRACT_ADDRESS"] != "0x0" { 216 return fmt.Errorf("existing vcr address in config map = %v", cm.Data["DEPOSIT_CONTRACT_ADDRESS"]) 217 } 218 cm.Data["DEPOSIT_CONTRACT_ADDRESS"] = contractAddr 219 220 _, err = client.CoreV1().ConfigMaps("beacon-chain").Update(ctx, cm, metav1.UpdateOptions{}) 221 222 return err 223 }