Skip to content

Commit

Permalink
Add flag to allow restarting devnet (filecoin-project#1521)
Browse files Browse the repository at this point in the history
* Make devnet restarteable with data

* rename flag

* Update readme

* wording tweak
  • Loading branch information
lalexgap authored Jun 14, 2023
1 parent c9c08be commit a9435e5
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 82 deletions.
52 changes: 32 additions & 20 deletions cmd/devnet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import (
"context"
"log"
"os"
"os/signal"
"syscall"

"github.com/filecoin-project/boost/pkg/devnet"

"github.com/urfave/cli/v2"

logging "github.com/ipfs/go-log/v2"
)

Expand All @@ -17,26 +17,38 @@ func init() {
}

func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

home, err := os.UserHomeDir()
if err != nil {
panic(err)
const initFlag = "initialize"
app := &cli.App{
Name: "devnet",
Usage: "Run a local devnet",
Flags: []cli.Flag{
&cli.BoolFlag{
Aliases: []string{"i"},
Name: initFlag,
Value: true,
Usage: "Whether to initialize the devnet or attempt to use the existing state directories and config.",
},
},
Action: func(cctx *cli.Context) error {

home, err := os.UserHomeDir()
if err != nil {
return err
}

done := make(chan struct{})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

go devnet.Run(ctx, home, done, cctx.Bool(initFlag))

<-done
return nil
},
}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)

done := make(chan struct{})
go devnet.Run(ctx, home, done)

// setup a signal handler to cancel the context
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, syscall.SIGTERM, syscall.SIGINT)
select {
case <-interrupt:
log.Println("closing as we got interrupt")
cancel()
case <-ctx.Done():
}

<-done
}
20 changes: 12 additions & 8 deletions pkg/devnet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,20 @@ simply run one of the integration tests - it should start devnet automatically.

### Building and installing Lotus-related binaries

git clone https://github.com/filecoin-project/lotus
cd lotus
git checkout master # or whichever version
make debug
sudo make install
install -C ./lotus-seed /usr/local/bin/lotus-seed
git clone https://github.com/filecoin-project/lotus
cd lotus
git checkout master # or whichever version
make debug
sudo make install
install -C ./lotus-seed /usr/local/bin/lotus-seed

### Clean up state directories

Make sure your $LOTUS_PATH and $LOTUS_MINER_PATH are clean before running devnet:

rm -rf ~/.lotus
rm -rf ~/.lotusminer
rm -rf ~/.lotus
rm -rf ~/.lotusminer

### Running using existing state directories

To use existing state directories and config the devnet can be run using `./devnet -i=false`. This skips trying to initialize the devnet and will use the existing directories.
115 changes: 61 additions & 54 deletions pkg/devnet/devnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,42 +16,44 @@ import (

var log = logging.Logger("devnet")

func Run(ctx context.Context, tempHome string, done chan struct{}) {
func Run(ctx context.Context, tempHome string, done chan struct{}, initialize bool) {
var wg sync.WaitGroup

log.Debugw("using temp home dir", "dir", tempHome)

// The parameter files can be as large as 1GiB.
// If this is the first time lotus runs,
// and the machine doesn't have particularly fast internet,
// we don't want devnet to seemingly stall for many minutes.
// Instead, show the download progress explicitly.
// fetch-params will exit in about a second if all files are up to date.
// The command is also pretty verbose, so reduce its verbosity.
{
// One hour should be enough for practically any machine.
ctx, cancel := context.WithTimeout(ctx, time.Hour)

log.Debugw("lotus fetch-params 8388608")
cmd := exec.CommandContext(ctx, "lotus", "fetch-params", "8388608")
cmd.Env = []string{fmt.Sprintf("HOME=%s", tempHome), "GOLOG_LOG_LEVEL=error"}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatal(err)
if initialize {
// The parameter files can be as large as 1GiB.
// If this is the first time lotus runs,
// and the machine doesn't have particularly fast internet,
// we don't want devnet to seemingly stall for many minutes.
// Instead, show the download progress explicitly.
// fetch-params will exit in about a second if all files are up to date.
// The command is also pretty verbose, so reduce its verbosity.
{
// One hour should be enough for practically any machine.
ctx, cancel := context.WithTimeout(ctx, time.Hour)

log.Debugw("lotus fetch-params 8388608")
cmd := exec.CommandContext(ctx, "lotus", "fetch-params", "8388608")
cmd.Env = []string{fmt.Sprintf("HOME=%s", tempHome), "GOLOG_LOG_LEVEL=error"}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
cancel()
}
cancel()
}

wg.Add(2)
go func() {
runLotusDaemon(ctx, tempHome)
runLotusDaemon(ctx, tempHome, initialize)
log.Debugw("shut down lotus daemon")
wg.Done()
}()

go func() {
runLotusMiner(ctx, tempHome)
runLotusMiner(ctx, tempHome, initialize)
log.Debugw("shut down lotus miner")
wg.Done()
}()
Expand Down Expand Up @@ -88,46 +90,51 @@ func runCmdsWithLog(ctx context.Context, name string, commands [][]string, homeD
}
}

func runLotusDaemon(ctx context.Context, home string) {
cmds := [][]string{
{"lotus-seed", "genesis", "new", "localnet.json"},
{"lotus-seed", "pre-seal", "--sector-size=8388608", "--num-sectors=1"},
{"lotus-seed", "genesis", "add-miner", "localnet.json",
filepath.Join(home, ".genesis-sectors", "pre-seal-t01000.json")},
{"lotus", "daemon", "--lotus-make-genesis=dev.gen",
"--genesis-template=localnet.json", "--bootstrap=false"},
func runLotusDaemon(ctx context.Context, home string, initialize bool) {
cmds := [][]string{}
if initialize {
cmds = append(cmds, []string{"lotus-seed", "genesis", "new", "localnet.json"},
[]string{"lotus-seed", "pre-seal", "--sector-size=8388608", "--num-sectors=1"},
[]string{"lotus-seed", "genesis", "add-miner", "localnet.json",
filepath.Join(home, ".genesis-sectors", "pre-seal-t01000.json")},
[]string{"lotus", "daemon", "--lotus-make-genesis=dev.gen",
"--genesis-template=localnet.json", "--bootstrap=false"})
} else {
cmds = append(cmds, []string{"lotus", "daemon", "--genesis=dev.gen", "--bootstrap=false"})
}

runCmdsWithLog(ctx, "lotus-daemon", cmds, home)
}

func runLotusMiner(ctx context.Context, home string) {
func runLotusMiner(ctx context.Context, home string, initialize bool) {
cmds := [][]string{
{"lotus", "wait-api"}, // wait for lotus node to run

{"lotus", "wallet", "import",
filepath.Join(home, ".genesis-sectors", "pre-seal-t01000.key")},
{"lotus-miner", "init", "--genesis-miner", "--actor=t01000", "--sector-size=8388608",
"--pre-sealed-sectors=" + filepath.Join(home, ".genesis-sectors"),
"--pre-sealed-metadata=" + filepath.Join(home, ".genesis-sectors", "pre-seal-t01000.json"),
"--nosync"},

// Starting in network version 13,
// pre-commits are batched by default,
// and commits are aggregated by default.
// This means deals could sit at StorageDealAwaitingPreCommit or
// StorageDealSealing for a while, going past our 10m test timeout.
{"sed", "-Ei", "-e", "s/#BatchPreCommits\\ =\\ true/BatchPreCommits=false/",
filepath.Join(home, ".lotusminer", "config.toml")},

{"sed", "-Ei", "-e", "s/#AggregateCommits\\ =\\ true/AggregateCommits=false/",
filepath.Join(home, ".lotusminer", "config.toml")},

{"sed", "-Ei", "-e", "s/#EnableMarkets\\ =\\ true/EnableMarkets=false/",
filepath.Join(home, ".lotusminer", "config.toml")},

{"lotus-miner", "run", "--nosync"},
}
if initialize {
cmds = append(cmds,
[]string{"lotus", "wallet", "import",
filepath.Join(home, ".genesis-sectors", "pre-seal-t01000.key")},
[]string{"lotus-miner", "init", "--genesis-miner", "--actor=t01000", "--sector-size=8388608",
"--pre-sealed-sectors=" + filepath.Join(home, ".genesis-sectors"),
"--pre-sealed-metadata=" + filepath.Join(home, ".genesis-sectors", "pre-seal-t01000.json"),
"--nosync"},

// Starting in network version 13,
// pre-commits are batched by default,
// and commits are aggregated by default.
// This means deals could sit at StorageDealAwaitingPreCommit or
// StorageDealSealing for a while, going past our 10m test timeout.
[]string{"sed", "-Ei", "-e", "s/#BatchPreCommits\\ =\\ true/BatchPreCommits=false/",
filepath.Join(home, ".lotusminer", "config.toml")},

[]string{"sed", "-Ei", "-e", "s/#AggregateCommits\\ =\\ true/AggregateCommits=false/",
filepath.Join(home, ".lotusminer", "config.toml")},

[]string{"sed", "-Ei", "-e", "s/#EnableMarkets\\ =\\ true/EnableMarkets=false/",
filepath.Join(home, ".lotusminer", "config.toml")},
)
}
cmds = append(cmds, []string{"lotus-miner", "run", "--nosync"})

runCmdsWithLog(ctx, "lotus-miner", cmds, home)
}
Expand Down

0 comments on commit a9435e5

Please sign in to comment.