func ImportChain(chain *core.BlockChain, fn string) error { // Watch for Ctrl-C while the import is running. // If a signal is received, the import will stop at the next batch. interrupt := make(chan os.Signal, 1) stop := make(chan struct{}) signal.Notify(interrupt, os.Interrupt) defer signal.Stop(interrupt) defer close(interrupt) go func() { if _, ok := <-interrupt; ok { glog.Info("caught interrupt during import, will stop at next batch") } close(stop) }() checkInterrupt := func() bool { select { case <-stop: return true default: return false } } glog.Infoln("Importing blockchain", fn) fh, err := os.Open(fn) if err != nil { return err } defer fh.Close() stream := rlp.NewStream(fh, 0) // Run actual the import. blocks := make(types.Blocks, importBatchSize) n := 0 for batch := 0; ; batch++ { // Load a batch of RLP blocks. if checkInterrupt() { return fmt.Errorf("interrupted") } i := 0 for ; i < importBatchSize; i++ { var b types.Block if err := stream.Decode(&b); err == io.EOF { break } else if err != nil { return fmt.Errorf("at block %d: %v", n, err) } // don't import first block if b.NumberU64() == 0 { i-- continue } blocks[i] = &b n++ } if i == 0 { break } // Import the batch. if checkInterrupt() { return fmt.Errorf("interrupted") } if hasAllBlocks(chain, blocks[:i]) { glog.Infof("skipping batch %d, all blocks present [%x / %x]", batch, blocks[0].Hash().Bytes()[:4], blocks[i-1].Hash().Bytes()[:4]) continue } if _, err := chain.InsertChain(blocks[:i]); err != nil { return fmt.Errorf("invalid block %d: %v", n, err) } } return nil }