213 lines
4.7 KiB
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...),
|
|
}
|
|
}
|