lotus/cmd/lotus-seed/main.go

213 lines
4.7 KiB
Go

package main
import (
"encoding/hex"
"encoding/json"
"fmt"
"os"
"github.com/docker/go-units"
logging "github.com/ipfs/go-log/v2"
"github.com/mitchellh/go-homedir"
"github.com/urfave/cli/v2"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
"github.com/filecoin-project/lotus/genesis"
)
var log = logging.Logger("lotus-seed")
func main() {
_ = logging.SetLogLevel("*", "INFO")
local := []*cli.Command{
genesisCmd,
preSealCmd,
aggregateManifestsCmd,
}
app := &cli.App{
Name: "lotus-seed",
Usage: "Seal sectors for genesis miner",
Version: string(build.NodeUserVersion()),
Flags: []cli.Flag{
&cli.StringFlag{
Name: "sector-dir",
Value: "~/.genesis-sectors",
},
},
Commands: local,
}
if err := app.Run(os.Args); err != nil {
log.Warn(err)
os.Exit(1)
}
}
var preSealCmd = &cli.Command{
Name: "pre-seal",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "miner-addr",
Value: "t01000",
Usage: "specify the future address of your miner",
},
&cli.StringFlag{
Name: "sector-size",
Value: "2KiB",
Usage: "specify size of sectors to pre-seal",
},
&cli.StringFlag{
Name: "ticket-preimage",
Value: "lotus is fire",
Usage: "set the ticket preimage for sealing randomness",
},
&cli.IntFlag{
Name: "num-sectors",
Value: 1,
Usage: "select number of sectors to pre-seal",
},
&cli.Uint64Flag{
Name: "sector-offset",
Value: 0,
Usage: "how many sector ids to skip when starting to seal",
},
&cli.StringFlag{
Name: "key",
Value: "",
Usage: "(optional) Key to use for signing / owner/worker addresses",
},
&cli.BoolFlag{
Name: "fake-sectors",
Value: false,
},
&cli.UintFlag{
Name: "network-version",
Usage: "specify network version",
Value: uint(build.GenesisNetworkVersion),
},
},
Action: func(c *cli.Context) error {
sdir := c.String("sector-dir")
sbroot, err := homedir.Expand(sdir)
if err != nil {
return err
}
maddr, err := address.NewFromString(c.String("miner-addr"))
if err != nil {
return err
}
var k *types.KeyInfo
if c.String("key") != "" {
k = new(types.KeyInfo)
kh, err := os.ReadFile(c.String("key"))
if err != nil {
return err
}
kb, err := hex.DecodeString(string(kh))
if err != nil {
return err
}
if err := json.Unmarshal(kb, k); err != nil {
return err
}
}
sectorSizeInt, err := units.RAMInBytes(c.String("sector-size"))
if err != nil {
return err
}
sectorSize := abi.SectorSize(sectorSizeInt)
nv := build.GenesisNetworkVersion
if c.IsSet("network-version") {
nv = network.Version(c.Uint64("network-version"))
}
var synthetic = false // there's little reason to have this for a seed.
spt, err := miner.SealProofTypeFromSectorSize(sectorSize, nv, synthetic)
if err != nil {
return err
}
gm, key, err := seed.PreSeal(maddr, spt, abi.SectorNumber(c.Uint64("sector-offset")), c.Int("num-sectors"), sbroot, []byte(c.String("ticket-preimage")), k, c.Bool("fake-sectors"))
if err != nil {
return err
}
return seed.WriteGenesisMiner(maddr, sbroot, gm, key)
},
}
var aggregateManifestsCmd = &cli.Command{
Name: "aggregate-manifests",
Usage: "aggregate a set of preseal manifests into a single file",
Action: func(cctx *cli.Context) error {
var inputs []map[string]genesis.Miner
for _, infi := range cctx.Args().Slice() {
fi, err := os.Open(infi)
if err != nil {
return err
}
var val map[string]genesis.Miner
if err := json.NewDecoder(fi).Decode(&val); err != nil {
return err
}
inputs = append(inputs, val)
if err := fi.Close(); err != nil {
return err
}
}
output := make(map[string]genesis.Miner)
for _, in := range inputs {
for maddr, val := range in {
if gm, ok := output[maddr]; ok {
output[maddr] = mergeGenMiners(gm, val)
} else {
output[maddr] = val
}
}
}
blob, err := json.MarshalIndent(output, "", " ")
if err != nil {
return err
}
fmt.Println(string(blob))
return nil
},
}
func mergeGenMiners(a, b genesis.Miner) genesis.Miner {
if a.SectorSize != b.SectorSize {
panic("sector sizes mismatch")
}
return genesis.Miner{
Owner: a.Owner,
Worker: a.Worker,
PeerId: a.PeerId,
MarketBalance: big.Zero(),
PowerBalance: big.Zero(),
SectorSize: a.SectorSize,
Sectors: append(a.Sectors, b.Sectors...),
}
}