func makedag(ctx *cli.Context) { utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) args := ctx.Args() wrongArgs := func() { utils.Fatalf(`Usage: geth makedag <block number> <outputdir>`) } switch { case len(args) == 2: blockNum, err := strconv.ParseUint(args[0], 0, 64) dir := args[1] if err != nil { wrongArgs() } else { dir = filepath.Clean(dir) // seems to require a trailing slash if !strings.HasSuffix(dir, "/") { dir = dir + "/" } _, err = ioutil.ReadDir(dir) if err != nil { utils.Fatalf("Can't find dir") } fmt.Println("making DAG, this could take awhile...") ethash.MakeDAG(blockNum, dir) } default: wrongArgs() } }
func (self *minerApi) MakeDAG(req *shared.Request) (interface{}, error) { args := new(MakeDAGArgs) if err := self.codec.Decode(req.Params, &args); err != nil { return nil, err } if args.BlockNumber < 0 { return false, shared.NewValidationError("BlockNumber", "BlockNumber must be positive") } err := ethash.MakeDAG(uint64(args.BlockNumber), "") if err == nil { return true, nil } return false, err }
// StartAutoDAG() spawns a go routine that checks the DAG every autoDAGcheckInterval // by default that is 10 times per epoch // in epoch n, if we past autoDAGepochHeight within-epoch blocks, // it calls ethash.MakeDAG to pregenerate the DAG for the next epoch n+1 // if it does not exist yet as well as remove the DAG for epoch n-1 // the loop quits if autodagquit channel is closed, it can safely restart and // stop any number of times. // For any more sophisticated pattern of DAG generation, use CLI subcommand // makedag func (self *Ethereum) StartAutoDAG() { if self.autodagquit != nil { return // already started } go func() { glog.V(logger.Info).Infof("Automatic pregeneration of ethash DAG ON (ethash dir: %s)", ethash.DefaultDir) var nextEpoch uint64 timer := time.After(0) self.autodagquit = make(chan bool) for { select { case <-timer: glog.V(logger.Info).Infof("checking DAG (ethash dir: %s)", ethash.DefaultDir) currentBlock := self.ChainManager().CurrentBlock().NumberU64() thisEpoch := currentBlock / epochLength if nextEpoch <= thisEpoch { if currentBlock%epochLength > autoDAGepochHeight { if thisEpoch > 0 { previousDag, previousDagFull := dagFiles(thisEpoch - 1) os.Remove(filepath.Join(ethash.DefaultDir, previousDag)) os.Remove(filepath.Join(ethash.DefaultDir, previousDagFull)) glog.V(logger.Info).Infof("removed DAG for epoch %d (%s)", thisEpoch-1, previousDag) } nextEpoch = thisEpoch + 1 dag, _ := dagFiles(nextEpoch) if _, err := os.Stat(dag); os.IsNotExist(err) { glog.V(logger.Info).Infof("Pregenerating DAG for epoch %d (%s)", nextEpoch, dag) err := ethash.MakeDAG(nextEpoch*epochLength, "") // "" -> ethash.DefaultDir if err != nil { glog.V(logger.Error).Infof("Error generating DAG for epoch %d (%s)", nextEpoch, dag) return } } else { glog.V(logger.Error).Infof("DAG for epoch %d (%s)", nextEpoch, dag) } } } timer = time.After(autoDAGcheckInterval) case <-self.autodagquit: return } } }() }