github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/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  	"runtime"
    27  	"strings"
    28  
    29  	"github.com/ethereum/go-ethereum/core"
    30  	"github.com/ethereum/go-ethereum/core/types"
    31  	"github.com/ethereum/go-ethereum/internal/debug"
    32  	"github.com/ethereum/go-ethereum/log"
    33  	"github.com/ethereum/go-ethereum/node"
    34  	"github.com/ethereum/go-ethereum/rlp"
    35  )
    36  
    37  const (
    38  	importBatchSize = 2500
    39  )
    40  
    41  // Fatalf formats a message to standard error and exits the program.
    42  // The message is also printed to standard output if standard error
    43  // is redirected to a different file.
    44  func Fatalf(format string, args ...interface{}) {
    45  	w := io.MultiWriter(os.Stdout, os.Stderr)
    46  	if runtime.GOOS == "windows" {
    47  		// The SameFile check below doesn't work on Windows.
    48  		// stdout is unlikely to get redirected though, so just print there.
    49  		w = os.Stdout
    50  	} else {
    51  		outf, _ := os.Stdout.Stat()
    52  		errf, _ := os.Stderr.Stat()
    53  		if outf != nil && errf != nil && os.SameFile(outf, errf) {
    54  			w = os.Stderr
    55  		}
    56  	}
    57  	fmt.Fprintf(w, "Fatal: "+format+"\n", args...)
    58  	os.Exit(1)
    59  }
    60  
    61  func StartNode(stack *node.Node) {
    62  
    63  	if err := stack.Start(); err != nil {  // Qmanager Enode 값을 읽어와서 노드 객체에 연결시킴.
    64  		// Temp disable :
    65  		fmt.Printf("Error starting protocol stack: %v", err)  //not port no when run private : geth --localIP 1
    66  	}
    67  	go func() {
    68  		sigc := make(chan os.Signal, 1)
    69  		signal.Notify(sigc, os.Interrupt)
    70  		defer signal.Stop(sigc)
    71  		<-sigc
    72  		log.Info("Got interrupt, shutting down...")
    73  		go stack.Stop()
    74  		for i := 10; i > 0; i-- {
    75  			<-sigc
    76  			if i > 1 {
    77  				log.Warn("Already shutting down, interrupt more to panic.", "times", i-1)
    78  			}
    79  		}
    80  		debug.Exit() // ensure trace and CPU profile data is flushed.
    81  		debug.LoudPanic("boom")
    82  	}()
    83  }
    84  
    85  func ImportChain(chain *core.BlockChain, fn string) error {
    86  	// Watch for Ctrl-C while the import is running.
    87  	// If a signal is received, the import will stop at the next batch.
    88  	interrupt := make(chan os.Signal, 1)
    89  	stop := make(chan struct{})
    90  	signal.Notify(interrupt, os.Interrupt)
    91  	defer signal.Stop(interrupt)
    92  	defer close(interrupt)
    93  	go func() {
    94  		if _, ok := <-interrupt; ok {
    95  			log.Info("Interrupted during import, stopping at next batch")
    96  		}
    97  		close(stop)
    98  	}()
    99  	checkInterrupt := func() bool {
   100  		select {
   101  		case <-stop:
   102  			return true
   103  		default:
   104  			return false
   105  		}
   106  	}
   107  
   108  	log.Info("Importing blockchain", "file", fn)
   109  	fh, err := os.Open(fn)
   110  	if err != nil {
   111  		return err
   112  	}
   113  	defer fh.Close()
   114  
   115  	var reader io.Reader = fh
   116  	if strings.HasSuffix(fn, ".gz") {
   117  		if reader, err = gzip.NewReader(reader); err != nil {
   118  			return err
   119  		}
   120  	}
   121  
   122  	stream := rlp.NewStream(reader, 0)
   123  
   124  	// Run actual the import.
   125  	blocks := make(types.Blocks, importBatchSize)
   126  	n := 0
   127  	for batch := 0; ; batch++ {
   128  		// Load a batch of RLP blocks.
   129  		if checkInterrupt() {
   130  			return fmt.Errorf("interrupted")
   131  		}
   132  		i := 0
   133  		for ; i < importBatchSize; i++ {
   134  			var b types.Block
   135  			if err := stream.Decode(&b); err == io.EOF {
   136  				break
   137  			} else if err != nil {
   138  				return fmt.Errorf("at block %d: %v", n, err)
   139  			}
   140  			// don't import first block
   141  			if b.NumberU64() == 0 {
   142  				i--
   143  				continue
   144  			}
   145  			blocks[i] = &b
   146  			n++
   147  		}
   148  		if i == 0 {
   149  			break
   150  		}
   151  		// Import the batch.
   152  		if checkInterrupt() {
   153  			return fmt.Errorf("interrupted")
   154  		}
   155  		if hasAllBlocks(chain, blocks[:i]) {
   156  			log.Info("Skipping batch as all blocks present", "batch", batch, "first", blocks[0].Hash(), "last", blocks[i-1].Hash())
   157  			continue
   158  		}
   159  
   160  		if _, err := chain.InsertChain(blocks[:i]); err != nil {
   161  			return fmt.Errorf("invalid block %d: %v", n, err)
   162  		}
   163  	}
   164  	return nil
   165  }
   166  
   167  func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool {
   168  	for _, b := range bs {
   169  		if !chain.HasBlock(b.Hash()) {
   170  			return false
   171  		}
   172  	}
   173  	return true
   174  }
   175  
   176  func ExportChain(blockchain *core.BlockChain, fn string) error {
   177  	log.Info("Exporting blockchain", "file", fn)
   178  	fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
   179  	if err != nil {
   180  		return err
   181  	}
   182  	defer fh.Close()
   183  
   184  	var writer io.Writer = fh
   185  	if strings.HasSuffix(fn, ".gz") {
   186  		writer = gzip.NewWriter(writer)
   187  		defer writer.(*gzip.Writer).Close()
   188  	}
   189  
   190  	if err := blockchain.Export(writer); err != nil {
   191  		return err
   192  	}
   193  	log.Info("Exported blockchain", "file", fn)
   194  
   195  	return nil
   196  }
   197  
   198  func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, last uint64) error {
   199  	log.Info("Exporting blockchain", "file", fn)
   200  	// TODO verify mode perms
   201  	fh, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm)
   202  	if err != nil {
   203  		return err
   204  	}
   205  	defer fh.Close()
   206  
   207  	var writer io.Writer = fh
   208  	if strings.HasSuffix(fn, ".gz") {
   209  		writer = gzip.NewWriter(writer)
   210  		defer writer.(*gzip.Writer).Close()
   211  	}
   212  
   213  	if err := blockchain.ExportN(writer, first, last); err != nil {
   214  		return err
   215  	}
   216  	log.Info("Exported blockchain to", "file", fn)
   217  	return nil
   218  }