github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/cmd/utils/cmd.go (about) 1 // Copyright 2014 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 17 // Package utils contains internal helper functions for go-ethereum commands. 18 package utils 19 20 import ( 21 "compress/gzip" 22 "fmt" 23 "io" 24 "os" 25 "os/signal" 26 "regexp" 27 "runtime" 28 "strings" 29 30 "github.com/atheioschain/go-atheios/common" 31 "github.com/atheioschain/go-atheios/core" 32 "github.com/atheioschain/go-atheios/core/types" 33 "github.com/atheioschain/go-atheios/internal/debug" 34 "github.com/atheioschain/go-atheios/logger" 35 "github.com/atheioschain/go-atheios/logger/glog" 36 "github.com/atheioschain/go-atheios/node" 37 "github.com/atheioschain/go-atheios/rlp" 38 ) 39 40 const ( 41 importBatchSize = 2500 42 ) 43 44 func openLogFile(Datadir string, filename string) *os.File { 45 path := common.AbsolutePath(Datadir, filename) 46 file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) 47 if err != nil { 48 panic(fmt.Sprintf("error opening log file '%s': %v", filename, err)) 49 } 50 return file 51 } 52 53 // Fatalf formats a message to standard error and exits the program. 54 // The message is also printed to standard output if standard error 55 // is redirected to a different file. 56 func Fatalf(format string, args ...interface{}) { 57 w := io.MultiWriter(os.Stdout, os.Stderr) 58 if runtime.GOOS == "windows" { 59 // The SameFile check below doesn't work on Windows. 60 // stdout is unlikely to get redirected though, so just print there. 61 w = os.Stdout 62 } else { 63 outf, _ := os.Stdout.Stat() 64 errf, _ := os.Stderr.Stat() 65 if outf != nil && errf != nil && os.SameFile(outf, errf) { 66 w = os.Stderr 67 } 68 } 69 fmt.Fprintf(w, "Fatal: "+format+"\n", args...) 70 os.Exit(1) 71 } 72 73 func StartNode(stack *node.Node) { 74 if err := stack.Start(); err != nil { 75 Fatalf("Error starting protocol stack: %v", err) 76 } 77 go func() { 78 sigc := make(chan os.Signal, 1) 79 signal.Notify(sigc, os.Interrupt) 80 defer signal.Stop(sigc) 81 <-sigc 82 glog.V(logger.Info).Infoln("Got interrupt, shutting down...") 83 go stack.Stop() 84 for i := 10; i > 0; i-- { 85 <-sigc 86 if i > 1 { 87 glog.V(logger.Info).Infof("Already shutting down, interrupt %d more times for panic.", i-1) 88 } 89 } 90 debug.Exit() // ensure trace and CPU profile data is flushed. 91 debug.LoudPanic("boom") 92 }() 93 } 94 95 func FormatTransactionData(data string) []byte { 96 d := common.StringToByteFunc(data, func(s string) (ret []byte) { 97 slice := regexp.MustCompile(`\n|\s`).Split(s, 1000000000) 98 for _, dataItem := range slice { 99 d := common.FormatData(dataItem) 100 ret = append(ret, d...) 101 } 102 return 103 }) 104 105 return d 106 } 107 108 func ImportChain(chain *core.BlockChain, fn string) error { 109 // Watch for Ctrl-C while the import is running. 110 // If a signal is received, the import will stop at the next batch. 111 interrupt := make(chan os.Signal, 1) 112 stop := make(chan struct{}) 113 signal.Notify(interrupt, os.Interrupt) 114 defer signal.Stop(interrupt) 115 defer close(interrupt) 116 go func() { 117 if _, ok := <-interrupt; ok { 118 glog.Info("caught interrupt during import, will stop at next batch") 119 } 120 close(stop) 121 }() 122 checkInterrupt := func() bool { 123 select { 124 case <-stop: 125 return true 126 default: 127 return false 128 } 129 } 130 131 glog.Infoln("Importing blockchain ", fn) 132 fh, err := os.Open(fn) 133 if err != nil { 134 return err 135 } 136 defer fh.Close() 137 138 var reader io.Reader = fh 139 if strings.HasSuffix(fn, ".gz") { 140 if reader, err = gzip.NewReader(reader); err != nil { 141 return err 142 } 143 } 144 145 stream := rlp.NewStream(reader, 0) 146 147 // Run actual the import. 148 blocks := make(types.Blocks, importBatchSize) 149 n := 0 150 for batch := 0; ; batch++ { 151 // Load a batch of RLP blocks. 152 if checkInterrupt() { 153 return fmt.Errorf("interrupted") 154 } 155 i := 0 156 for ; i < importBatchSize; i++ { 157 var b types.Block 158 if err := stream.Decode(&b); err == io.EOF { 159 break 160 } else if err != nil { 161 return fmt.Errorf("at block %d: %v", n, err) 162 } 163 // don't import first block 164 if b.NumberU64() == 0 { 165 i-- 166 continue 167 } 168 blocks[i] = &b 169 n++ 170 } 171 if i == 0 { 172 break 173 } 174 // Import the batch. 175 if checkInterrupt() { 176 return fmt.Errorf("interrupted") 177 } 178 if hasAllBlocks(chain, blocks[:i]) { 179 glog.Infof("skipping batch %d, all blocks present [%x / %x]", 180 batch, blocks[0].Hash().Bytes()[:4], blocks[i-1].Hash().Bytes()[:4]) 181 continue 182 } 183 184 if _, err := chain.InsertChain(blocks[:i]); err != nil { 185 return fmt.Errorf("invalid block %d: %v", n, err) 186 } 187 } 188 return nil 189 } 190 191 func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool { 192 for _, b := range bs { 193 if !chain.HasBlock(b.Hash()) { 194 return false 195 } 196 } 197 return true 198 } 199 200 func ExportChain(blockchain *core.BlockChain, fn string) error { 201 glog.Infoln("Exporting blockchain to ", fn) 202 fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) 203 if err != nil { 204 return err 205 } 206 defer fh.Close() 207 208 var writer io.Writer = fh 209 if strings.HasSuffix(fn, ".gz") { 210 writer = gzip.NewWriter(writer) 211 defer writer.(*gzip.Writer).Close() 212 } 213 214 if err := blockchain.Export(writer); err != nil { 215 return err 216 } 217 glog.Infoln("Exported blockchain to ", fn) 218 219 return nil 220 } 221 222 func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, last uint64) error { 223 glog.Infoln("Exporting blockchain to ", fn) 224 // TODO verify mode perms 225 fh, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm) 226 if err != nil { 227 return err 228 } 229 defer fh.Close() 230 231 var writer io.Writer = fh 232 if strings.HasSuffix(fn, ".gz") { 233 writer = gzip.NewWriter(writer) 234 defer writer.(*gzip.Writer).Close() 235 } 236 237 if err := blockchain.ExportN(writer, first, last); err != nil { 238 return err 239 } 240 glog.Infoln("Exported blockchain to ", fn) 241 return nil 242 }