Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shed: Add a util to create miners more easily #7595

Merged
merged 1 commit into from
Nov 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions chain/actors/builtin/miner/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,22 @@ func SealProofTypeFromSectorSize(ssize abi.SectorSize, nv network.Version) (abi.

return 0, xerrors.Errorf("unsupported network version")
}

// WindowPoStProofTypeFromSectorSize returns preferred post proof type for creating
// new miner actors and new sectors
func WindowPoStProofTypeFromSectorSize(ssize abi.SectorSize) (abi.RegisteredPoStProof, error) {
switch ssize {
case 2 << 10:
return abi.RegisteredPoStProof_StackedDrgWindow2KiBV1, nil
case 8 << 20:
return abi.RegisteredPoStProof_StackedDrgWindow8MiBV1, nil
case 512 << 20:
return abi.RegisteredPoStProof_StackedDrgWindow512MiBV1, nil
case 32 << 30:
return abi.RegisteredPoStProof_StackedDrgWindow32GiBV1, nil
case 64 << 30:
return abi.RegisteredPoStProof_StackedDrgWindow64GiBV1, nil
default:
return 0, xerrors.Errorf("unsupported sector size for miner: %v", ssize)
}
}
66 changes: 47 additions & 19 deletions cmd/lotus-miner/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"path/filepath"
"strconv"

power6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/power"

"github.com/docker/go-units"
"github.com/google/uuid"
"github.com/ipfs/go-datastore"
Expand Down Expand Up @@ -644,11 +646,26 @@ func createStorageMiner(ctx context.Context, api v1api.FullNode, peerid peer.ID,
return address.Address{}, err
}

sender := owner
if fromstr := cctx.String("from"); fromstr != "" {
faddr, err := address.NewFromString(fromstr)
if err != nil {
return address.Undef, fmt.Errorf("could not parse from address: %w", err)
}
sender = faddr
}

// make sure the sender account exists on chain
_, err = api.StateLookupID(ctx, owner, types.EmptyTSK)
if err != nil {
return address.Undef, xerrors.Errorf("sender must exist on chain: %w", err)
}

// make sure the worker account exists on chain
_, err = api.StateLookupID(ctx, worker, types.EmptyTSK)
if err != nil {
signed, err := api.MpoolPushMessage(ctx, &types.Message{
From: owner,
From: sender,
To: worker,
Value: types.NewInt(0),
}, nil)
Expand All @@ -668,35 +685,46 @@ func createStorageMiner(ctx context.Context, api v1api.FullNode, peerid peer.ID,
}
}

nv, err := api.StateNetworkVersion(ctx, types.EmptyTSK)
// make sure the owner account exists on chain
_, err = api.StateLookupID(ctx, owner, types.EmptyTSK)
if err != nil {
return address.Undef, xerrors.Errorf("getting network version: %w", err)
signed, err := api.MpoolPushMessage(ctx, &types.Message{
From: sender,
To: owner,
Value: types.NewInt(0),
}, nil)
if err != nil {
return address.Undef, xerrors.Errorf("push owner init: %w", err)
}

log.Infof("Initializing owner account %s, message: %s", worker, signed.Cid())
log.Infof("Waiting for confirmation")

mw, err := api.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence, lapi.LookbackNoLimit, true)
if err != nil {
return address.Undef, xerrors.Errorf("waiting for owner init: %w", err)
}
if mw.Receipt.ExitCode != 0 {
return address.Undef, xerrors.Errorf("initializing owner account failed: exit code %d", mw.Receipt.ExitCode)
}
}

spt, err := miner.SealProofTypeFromSectorSize(abi.SectorSize(ssize), nv)
// Note: the correct thing to do would be to call SealProofTypeFromSectorSize if actors version is v3 or later, but this still works
spt, err := miner.WindowPoStProofTypeFromSectorSize(abi.SectorSize(ssize))
if err != nil {
return address.Undef, xerrors.Errorf("getting seal proof type: %w", err)
return address.Undef, xerrors.Errorf("getting post proof type: %w", err)
}

params, err := actors.SerializeParams(&power2.CreateMinerParams{
Owner: owner,
Worker: worker,
SealProofType: spt,
Peer: abi.PeerID(peerid),
params, err := actors.SerializeParams(&power6.CreateMinerParams{
Owner: owner,
Worker: worker,
WindowPoStProofType: spt,
Peer: abi.PeerID(peerid),
})
if err != nil {
return address.Undef, err
}

sender := owner
if fromstr := cctx.String("from"); fromstr != "" {
faddr, err := address.NewFromString(fromstr)
if err != nil {
return address.Undef, fmt.Errorf("could not parse from address: %w", err)
}
sender = faddr
}

createStorageMinerMsg := &types.Message{
To: power.Address,
From: sender,
Expand Down
163 changes: 163 additions & 0 deletions cmd/lotus-shed/miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,27 @@ package main

import (
"bufio"
"bytes"
"fmt"
"io"
"os"
"path/filepath"
"strings"

power6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/power"

"github.com/docker/go-units"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"

"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"

"github.com/mitchellh/go-homedir"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
Expand All @@ -17,6 +33,153 @@ var minerCmd = &cli.Command{
Usage: "miner-related utilities",
Subcommands: []*cli.Command{
minerUnpackInfoCmd,
minerCreateCmd,
},
}

var minerCreateCmd = &cli.Command{
Name: "create",
Usage: "sends a create miner msg",
ArgsUsage: "[sender] [owner] [worker] [sector size]",
Action: func(cctx *cli.Context) error {
wapi, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}

defer closer()
ctx := lcli.ReqContext(cctx)

if cctx.Args().Len() != 4 {
return xerrors.Errorf("expected 4 args (sender owner worker sectorSize)")
}

sender, err := address.NewFromString(cctx.Args().First())
if err != nil {
return err
}

owner, err := address.NewFromString(cctx.Args().Get(1))
if err != nil {
return err
}

worker, err := address.NewFromString(cctx.Args().Get(2))
if err != nil {
return err
}

ssize, err := units.RAMInBytes(cctx.Args().Get(3))
if err != nil {
return fmt.Errorf("failed to parse sector size: %w", err)
}

// make sure the sender account exists on chain
_, err = wapi.StateLookupID(ctx, owner, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("sender must exist on chain: %w", err)
}

// make sure the worker account exists on chain
_, err = wapi.StateLookupID(ctx, worker, types.EmptyTSK)
if err != nil {
signed, err := wapi.MpoolPushMessage(ctx, &types.Message{
From: sender,
To: worker,
Value: types.NewInt(0),
}, nil)
if err != nil {
return xerrors.Errorf("push worker init: %w", err)
}

log.Infof("Initializing worker account %s, message: %s", worker, signed.Cid())
log.Infof("Waiting for confirmation")

mw, err := wapi.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence)
if err != nil {
return xerrors.Errorf("waiting for worker init: %w", err)
}

if mw.Receipt.ExitCode != 0 {
return xerrors.Errorf("initializing worker account failed: exit code %d", mw.Receipt.ExitCode)
}
}

// make sure the owner account exists on chain
_, err = wapi.StateLookupID(ctx, owner, types.EmptyTSK)
if err != nil {
signed, err := wapi.MpoolPushMessage(ctx, &types.Message{
From: sender,
To: owner,
Value: types.NewInt(0),
}, nil)
if err != nil {
return xerrors.Errorf("push owner init: %w", err)
}

log.Infof("Initializing owner account %s, message: %s", worker, signed.Cid())
log.Infof("Wating for confirmation")

mw, err := wapi.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence)
if err != nil {
return xerrors.Errorf("waiting for owner init: %w", err)
}

if mw.Receipt.ExitCode != 0 {
return xerrors.Errorf("initializing owner account failed: exit code %d", mw.Receipt.ExitCode)
}
}

// Note: the correct thing to do would be to call SealProofTypeFromSectorSize if actors version is v3 or later, but this still works
spt, err := miner.WindowPoStProofTypeFromSectorSize(abi.SectorSize(ssize))
if err != nil {
return xerrors.Errorf("getting post proof type: %w", err)
}

params, err := actors.SerializeParams(&power6.CreateMinerParams{
Owner: owner,
Worker: worker,
WindowPoStProofType: spt,
})

if err != nil {
return err
}

createStorageMinerMsg := &types.Message{
To: power.Address,
From: sender,
Value: big.Zero(),

Method: power.Methods.CreateMiner,
Params: params,
}

signed, err := wapi.MpoolPushMessage(ctx, createStorageMinerMsg, nil)
if err != nil {
return xerrors.Errorf("pushing createMiner message: %w", err)
}

log.Infof("Pushed CreateMiner message: %s", signed.Cid())
log.Infof("Waiting for confirmation")

mw, err := wapi.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence)
if err != nil {
return xerrors.Errorf("waiting for createMiner message: %w", err)
}

if mw.Receipt.ExitCode != 0 {
return xerrors.Errorf("create miner failed: exit code %d", mw.Receipt.ExitCode)
}

var retval power6.CreateMinerReturn
if err := retval.UnmarshalCBOR(bytes.NewReader(mw.Receipt.Return)); err != nil {
return err
}

log.Infof("New miners address is: %s (%s)", retval.IDAddress, retval.RobustAddress)

return nil
},
}

Expand Down