common.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // Copyright 2018 The go-ethereum Authors
  2. // This file is part of go-ethereum.
  3. //
  4. // go-ethereum is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // go-ethereum is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
  16. package main
  17. import (
  18. "io/ioutil"
  19. "strconv"
  20. "strings"
  21. "github.com/ethereum/go-ethereum/accounts/keystore"
  22. "github.com/ethereum/go-ethereum/cmd/utils"
  23. "github.com/ethereum/go-ethereum/common"
  24. "github.com/ethereum/go-ethereum/console"
  25. "github.com/ethereum/go-ethereum/contracts/checkpointoracle"
  26. "github.com/ethereum/go-ethereum/ethclient"
  27. "github.com/ethereum/go-ethereum/params"
  28. "github.com/ethereum/go-ethereum/rpc"
  29. "gopkg.in/urfave/cli.v1"
  30. )
  31. // newClient creates a client with specified remote URL.
  32. func newClient(ctx *cli.Context) *ethclient.Client {
  33. client, err := ethclient.Dial(ctx.GlobalString(nodeURLFlag.Name))
  34. if err != nil {
  35. utils.Fatalf("Failed to connect to Ethereum node: %v", err)
  36. }
  37. return client
  38. }
  39. // newRPCClient creates a rpc client with specified node URL.
  40. func newRPCClient(url string) *rpc.Client {
  41. client, err := rpc.Dial(url)
  42. if err != nil {
  43. utils.Fatalf("Failed to connect to Ethereum node: %v", err)
  44. }
  45. return client
  46. }
  47. // getContractAddr retrieves the register contract address through
  48. // rpc request.
  49. func getContractAddr(client *rpc.Client) common.Address {
  50. var addr string
  51. if err := client.Call(&addr, "les_getCheckpointContractAddress"); err != nil {
  52. utils.Fatalf("Failed to fetch checkpoint oracle address: %v", err)
  53. }
  54. return common.HexToAddress(addr)
  55. }
  56. // getCheckpoint retrieves the specified checkpoint or the latest one
  57. // through rpc request.
  58. func getCheckpoint(ctx *cli.Context, client *rpc.Client) *params.TrustedCheckpoint {
  59. var checkpoint *params.TrustedCheckpoint
  60. if ctx.GlobalIsSet(indexFlag.Name) {
  61. var result [3]string
  62. index := uint64(ctx.GlobalInt64(indexFlag.Name))
  63. if err := client.Call(&result, "les_getCheckpoint", index); err != nil {
  64. utils.Fatalf("Failed to get local checkpoint %v, please ensure the les API is exposed", err)
  65. }
  66. checkpoint = &params.TrustedCheckpoint{
  67. SectionIndex: index,
  68. SectionHead: common.HexToHash(result[0]),
  69. CHTRoot: common.HexToHash(result[1]),
  70. BloomRoot: common.HexToHash(result[2]),
  71. }
  72. } else {
  73. var result [4]string
  74. err := client.Call(&result, "les_latestCheckpoint")
  75. if err != nil {
  76. utils.Fatalf("Failed to get local checkpoint %v, please ensure the les API is exposed", err)
  77. }
  78. index, err := strconv.ParseUint(result[0], 0, 64)
  79. if err != nil {
  80. utils.Fatalf("Failed to parse checkpoint index %v", err)
  81. }
  82. checkpoint = &params.TrustedCheckpoint{
  83. SectionIndex: index,
  84. SectionHead: common.HexToHash(result[1]),
  85. CHTRoot: common.HexToHash(result[2]),
  86. BloomRoot: common.HexToHash(result[3]),
  87. }
  88. }
  89. return checkpoint
  90. }
  91. // newContract creates a registrar contract instance with specified
  92. // contract address or the default contracts for mainnet or testnet.
  93. func newContract(client *rpc.Client) (common.Address, *checkpointoracle.CheckpointOracle) {
  94. addr := getContractAddr(client)
  95. if addr == (common.Address{}) {
  96. utils.Fatalf("No specified registrar contract address")
  97. }
  98. contract, err := checkpointoracle.NewCheckpointOracle(addr, ethclient.NewClient(client))
  99. if err != nil {
  100. utils.Fatalf("Failed to setup registrar contract %s: %v", addr, err)
  101. }
  102. return addr, contract
  103. }
  104. // promptPassphrase prompts the user for a passphrase.
  105. // Set confirmation to true to require the user to confirm the passphrase.
  106. func promptPassphrase(confirmation bool) string {
  107. passphrase, err := console.Stdin.PromptPassword("Passphrase: ")
  108. if err != nil {
  109. utils.Fatalf("Failed to read passphrase: %v", err)
  110. }
  111. if confirmation {
  112. confirm, err := console.Stdin.PromptPassword("Repeat passphrase: ")
  113. if err != nil {
  114. utils.Fatalf("Failed to read passphrase confirmation: %v", err)
  115. }
  116. if passphrase != confirm {
  117. utils.Fatalf("Passphrases do not match")
  118. }
  119. }
  120. return passphrase
  121. }
  122. // getPassphrase obtains a passphrase given by the user. It first checks the
  123. // --password command line flag and ultimately prompts the user for a
  124. // passphrase.
  125. func getPassphrase(ctx *cli.Context) string {
  126. passphraseFile := ctx.String(utils.PasswordFileFlag.Name)
  127. if passphraseFile != "" {
  128. content, err := ioutil.ReadFile(passphraseFile)
  129. if err != nil {
  130. utils.Fatalf("Failed to read passphrase file '%s': %v",
  131. passphraseFile, err)
  132. }
  133. return strings.TrimRight(string(content), "\r\n")
  134. }
  135. // Otherwise prompt the user for the passphrase.
  136. return promptPassphrase(false)
  137. }
  138. // getKey retrieves the user key through specified key file.
  139. func getKey(ctx *cli.Context) *keystore.Key {
  140. // Read key from file.
  141. keyFile := ctx.GlobalString(keyFileFlag.Name)
  142. keyJson, err := ioutil.ReadFile(keyFile)
  143. if err != nil {
  144. utils.Fatalf("Failed to read the keyfile at '%s': %v", keyFile, err)
  145. }
  146. // Decrypt key with passphrase.
  147. passphrase := getPassphrase(ctx)
  148. key, err := keystore.DecryptKey(keyJson, passphrase)
  149. if err != nil {
  150. utils.Fatalf("Failed to decrypt user key '%s': %v", keyFile, err)
  151. }
  152. return key
  153. }