cmd.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. This file is part of go-ethereum
  3. go-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. go-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /**
  15. * @authors
  16. * Jeffrey Wilcke <i@jev.io>
  17. * Viktor Tron <viktor@ethdev.com>
  18. */
  19. package utils
  20. import (
  21. "bufio"
  22. "fmt"
  23. "io"
  24. "os"
  25. "os/signal"
  26. "regexp"
  27. "strings"
  28. "github.com/ethereum/go-ethereum/common"
  29. "github.com/ethereum/go-ethereum/core"
  30. "github.com/ethereum/go-ethereum/core/types"
  31. "github.com/ethereum/go-ethereum/eth"
  32. "github.com/ethereum/go-ethereum/logger"
  33. "github.com/ethereum/go-ethereum/logger/glog"
  34. "github.com/ethereum/go-ethereum/rlp"
  35. "github.com/peterh/liner"
  36. )
  37. var interruptCallbacks = []func(os.Signal){}
  38. // Register interrupt handlers callbacks
  39. func RegisterInterrupt(cb func(os.Signal)) {
  40. interruptCallbacks = append(interruptCallbacks, cb)
  41. }
  42. // go routine that call interrupt handlers in order of registering
  43. func HandleInterrupt() {
  44. c := make(chan os.Signal, 1)
  45. go func() {
  46. signal.Notify(c, os.Interrupt)
  47. for sig := range c {
  48. glog.V(logger.Error).Infof("Shutting down (%v) ... \n", sig)
  49. RunInterruptCallbacks(sig)
  50. }
  51. }()
  52. }
  53. func RunInterruptCallbacks(sig os.Signal) {
  54. for _, cb := range interruptCallbacks {
  55. cb(sig)
  56. }
  57. }
  58. func openLogFile(Datadir string, filename string) *os.File {
  59. path := common.AbsolutePath(Datadir, filename)
  60. file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
  61. if err != nil {
  62. panic(fmt.Sprintf("error opening log file '%s': %v", filename, err))
  63. }
  64. return file
  65. }
  66. func confirm(message string) bool {
  67. fmt.Println(message, "Are you sure? (y/n)")
  68. var r string
  69. fmt.Scanln(&r)
  70. for ; ; fmt.Scanln(&r) {
  71. if r == "n" || r == "y" {
  72. break
  73. } else {
  74. fmt.Printf("Yes or no? (%s)", r)
  75. }
  76. }
  77. return r == "y"
  78. }
  79. func PromptConfirm(prompt string) (bool, error) {
  80. var (
  81. input string
  82. err error
  83. )
  84. prompt = prompt + " [y/N] "
  85. if liner.TerminalSupported() {
  86. lr := liner.NewLiner()
  87. defer lr.Close()
  88. input, err = lr.Prompt(prompt)
  89. } else {
  90. fmt.Print(prompt)
  91. input, err = bufio.NewReader(os.Stdin).ReadString('\n')
  92. fmt.Println()
  93. }
  94. if len(input) > 0 && strings.ToUpper(input[:1]) == "Y" {
  95. return true, nil
  96. } else {
  97. return false, nil
  98. }
  99. return false, err
  100. }
  101. func PromptPassword(prompt string, warnTerm bool) (string, error) {
  102. if liner.TerminalSupported() {
  103. lr := liner.NewLiner()
  104. defer lr.Close()
  105. return lr.PasswordPrompt(prompt)
  106. }
  107. if warnTerm {
  108. fmt.Println("!! Unsupported terminal, password will be echoed.")
  109. }
  110. fmt.Print(prompt)
  111. input, err := bufio.NewReader(os.Stdin).ReadString('\n')
  112. fmt.Println()
  113. return input, err
  114. }
  115. func initDataDir(Datadir string) {
  116. _, err := os.Stat(Datadir)
  117. if err != nil {
  118. if os.IsNotExist(err) {
  119. fmt.Printf("Data directory '%s' doesn't exist, creating it\n", Datadir)
  120. os.Mkdir(Datadir, 0777)
  121. }
  122. }
  123. }
  124. // Fatalf formats a message to standard output and exits the program.
  125. func Fatalf(format string, args ...interface{}) {
  126. fmt.Fprintf(os.Stderr, "Fatal: "+format+"\n", args...)
  127. fmt.Fprintf(os.Stdout, "Fatal: "+format+"\n", args...)
  128. logger.Flush()
  129. os.Exit(1)
  130. }
  131. func StartEthereum(ethereum *eth.Ethereum) {
  132. glog.V(logger.Info).Infoln("Starting", ethereum.Name())
  133. if err := ethereum.Start(); err != nil {
  134. Fatalf("Error starting Ethereum: %v", err)
  135. }
  136. RegisterInterrupt(func(sig os.Signal) {
  137. ethereum.Stop()
  138. logger.Flush()
  139. })
  140. }
  141. func StartEthereumForTest(ethereum *eth.Ethereum) {
  142. glog.V(logger.Info).Infoln("Starting ", ethereum.Name())
  143. ethereum.StartForTest()
  144. RegisterInterrupt(func(sig os.Signal) {
  145. ethereum.Stop()
  146. logger.Flush()
  147. })
  148. }
  149. func FormatTransactionData(data string) []byte {
  150. d := common.StringToByteFunc(data, func(s string) (ret []byte) {
  151. slice := regexp.MustCompile("\\n|\\s").Split(s, 1000000000)
  152. for _, dataItem := range slice {
  153. d := common.FormatData(dataItem)
  154. ret = append(ret, d...)
  155. }
  156. return
  157. })
  158. return d
  159. }
  160. func ImportChain(chainmgr *core.ChainManager, fn string) error {
  161. fmt.Printf("importing blockchain '%s'\n", fn)
  162. fh, err := os.OpenFile(fn, os.O_RDONLY, os.ModePerm)
  163. if err != nil {
  164. return err
  165. }
  166. defer fh.Close()
  167. chainmgr.Reset()
  168. stream := rlp.NewStream(fh, 0)
  169. var i, n int
  170. batchSize := 2500
  171. blocks := make(types.Blocks, batchSize)
  172. for ; ; i++ {
  173. var b types.Block
  174. if err := stream.Decode(&b); err == io.EOF {
  175. break
  176. } else if err != nil {
  177. return fmt.Errorf("at block %d: %v", i, err)
  178. }
  179. blocks[n] = &b
  180. n++
  181. if n == batchSize {
  182. if _, err := chainmgr.InsertChain(blocks); err != nil {
  183. return fmt.Errorf("invalid block %v", err)
  184. }
  185. n = 0
  186. blocks = make(types.Blocks, batchSize)
  187. }
  188. }
  189. if n > 0 {
  190. if _, err := chainmgr.InsertChain(blocks[:n]); err != nil {
  191. return fmt.Errorf("invalid block %v", err)
  192. }
  193. }
  194. fmt.Printf("imported %d blocks\n", i)
  195. return nil
  196. }
  197. func ExportChain(chainmgr *core.ChainManager, fn string) error {
  198. fmt.Printf("exporting blockchain '%s'\n", fn)
  199. fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
  200. if err != nil {
  201. return err
  202. }
  203. defer fh.Close()
  204. if err := chainmgr.Export(fh); err != nil {
  205. return err
  206. }
  207. fmt.Printf("exported blockchain\n")
  208. return nil
  209. }