Merge pull request #8719 from filecoin-project/gstuart/cli-bad-post
feat: cli: New commands for testing.
This commit is contained in:
commit
966f6816eb
@ -59,6 +59,7 @@ var sectorsCmd = &cli.Command{
|
||||
sectorsCapacityCollateralCmd,
|
||||
sectorsBatching,
|
||||
sectorsRefreshPieceMatchingCmd,
|
||||
sectorsCompactPartitionsCmd,
|
||||
},
|
||||
}
|
||||
|
||||
@ -2089,3 +2090,106 @@ func yesno(b bool) string {
|
||||
}
|
||||
return color.RedString("NO")
|
||||
}
|
||||
|
||||
// TODO simulate this call if --really-do-it is not used
|
||||
var sectorsCompactPartitionsCmd = &cli.Command{
|
||||
Name: "compact-partitions",
|
||||
Usage: "removes dead sectors from partitions and reduces the number of partitions used if possible",
|
||||
Flags: []cli.Flag{
|
||||
&cli.Uint64Flag{
|
||||
Name: "deadline",
|
||||
Usage: "the deadline to compact the partitions in",
|
||||
Required: true,
|
||||
},
|
||||
&cli.Int64SliceFlag{
|
||||
Name: "partitions",
|
||||
Usage: "list of partitions to compact sectors in",
|
||||
Required: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "really-do-it",
|
||||
Usage: "Actually send transaction performing the action",
|
||||
Value: false,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "actor",
|
||||
Usage: "Specify the address of the miner to run this command",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if !cctx.Bool("really-do-it") {
|
||||
fmt.Println("Pass --really-do-it to actually execute this action")
|
||||
return nil
|
||||
}
|
||||
|
||||
api, acloser, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer acloser()
|
||||
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
maddr, err := getActorAddress(ctx, cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
minfo, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deadline := cctx.Uint64("deadline")
|
||||
if deadline > miner.WPoStPeriodDeadlines {
|
||||
return fmt.Errorf("deadline %d out of range", deadline)
|
||||
}
|
||||
|
||||
parts := cctx.Int64Slice("partitions")
|
||||
if len(parts) <= 0 {
|
||||
return fmt.Errorf("must include at least one partition to compact")
|
||||
}
|
||||
fmt.Printf("compacting %d paritions\n", len(parts))
|
||||
|
||||
partitions := bitfield.New()
|
||||
for _, partition := range parts {
|
||||
partitions.Set(uint64(partition))
|
||||
}
|
||||
|
||||
params := miner.CompactPartitionsParams{
|
||||
Deadline: deadline,
|
||||
Partitions: partitions,
|
||||
}
|
||||
|
||||
sp, err := actors.SerializeParams(¶ms)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("serializing params: %w", err)
|
||||
}
|
||||
|
||||
smsg, err := api.MpoolPushMessage(ctx, &types.Message{
|
||||
From: minfo.Worker,
|
||||
To: maddr,
|
||||
Method: builtin.MethodsMiner.CompactPartitions,
|
||||
Value: big.Zero(),
|
||||
Params: sp,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("mpool push: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Requested compact partitions in message %s\n", smsg.Cid())
|
||||
|
||||
wait, err := api.StateWaitMsg(ctx, smsg.Cid(), 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check it executed successfully
|
||||
if wait.Receipt.ExitCode != 0 {
|
||||
fmt.Println(cctx.App.Writer, "compact partitions failed!")
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -9,15 +9,20 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
miner2 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
|
||||
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/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-bitfield"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/builtin"
|
||||
miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
power7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/power"
|
||||
"github.com/filecoin-project/specs-actors/v7/actors/runtime/proof"
|
||||
|
||||
"github.com/docker/go-units"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
@ -37,6 +42,8 @@ var minerCmd = &cli.Command{
|
||||
minerUnpackInfoCmd,
|
||||
minerCreateCmd,
|
||||
minerFaultsCmd,
|
||||
sendInvalidWindowPoStCmd,
|
||||
generateAndSendConsensusFaultCmd,
|
||||
},
|
||||
}
|
||||
|
||||
@ -75,7 +82,7 @@ var minerFaultsCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
faults, err := faultBf.All(miner2.SectorsMax)
|
||||
faults, err := faultBf.All(abi.MaxSectorNumber)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -216,7 +223,7 @@ var minerCreateCmd = &cli.Command{
|
||||
return xerrors.Errorf("getting post proof type: %w", err)
|
||||
}
|
||||
|
||||
params, err := actors.SerializeParams(&power6.CreateMinerParams{
|
||||
params, err := actors.SerializeParams(&power7.CreateMinerParams{
|
||||
Owner: owner,
|
||||
Worker: worker,
|
||||
WindowPoStProofType: spt,
|
||||
@ -252,7 +259,7 @@ var minerCreateCmd = &cli.Command{
|
||||
return xerrors.Errorf("create miner failed: exit code %d", mw.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
var retval power6.CreateMinerReturn
|
||||
var retval power7.CreateMinerReturn
|
||||
if err := retval.UnmarshalCBOR(bytes.NewReader(mw.Receipt.Return)); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -354,3 +361,226 @@ var minerUnpackInfoCmd = &cli.Command{
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var sendInvalidWindowPoStCmd = &cli.Command{
|
||||
Name: "send-invalid-windowed-post",
|
||||
Usage: "Sends an invalid windowed post for a specific deadline",
|
||||
Description: `Note: This is meant for testing purposes and should NOT be used on mainnet or you will be slashed`,
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "really-do-it",
|
||||
Usage: "Actually send transaction performing the action",
|
||||
Value: false,
|
||||
},
|
||||
&cli.Int64SliceFlag{
|
||||
Name: "partitions",
|
||||
Usage: "list of partitions to submit invalid post for",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "actor",
|
||||
Usage: "Specify the address of the miner to run this command",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if !cctx.Bool("really-do-it") {
|
||||
return xerrors.Errorf("Pass --really-do-it to actually execute this action")
|
||||
}
|
||||
|
||||
api, acloser, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting api: %w", err)
|
||||
}
|
||||
defer acloser()
|
||||
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
maddr, err := address.NewFromString(cctx.String("actor"))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting actor address: %w", err)
|
||||
}
|
||||
|
||||
minfo, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting mienr info: %w", err)
|
||||
}
|
||||
|
||||
deadline, err := api.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting deadline: %w", err)
|
||||
}
|
||||
|
||||
partitionIndices := cctx.Int64Slice("partitions")
|
||||
if len(partitionIndices) <= 0 {
|
||||
return fmt.Errorf("must include at least one partition to compact")
|
||||
}
|
||||
|
||||
chainHead, err := api.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting chain head: %w", err)
|
||||
}
|
||||
|
||||
checkRand, err := api.StateGetRandomnessFromTickets(ctx, crypto.DomainSeparationTag_PoStChainCommit, deadline.Challenge, nil, chainHead.Key())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting randomness: %w", err)
|
||||
}
|
||||
|
||||
proofSize, err := minfo.WindowPoStProofType.ProofSize()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting proof size: %w", err)
|
||||
}
|
||||
|
||||
var partitions []miner8.PoStPartition
|
||||
|
||||
emptyProof := []proof.PoStProof{{
|
||||
PoStProof: minfo.WindowPoStProofType,
|
||||
ProofBytes: make([]byte, proofSize)}}
|
||||
|
||||
for _, partition := range partitionIndices {
|
||||
newPartition := miner8.PoStPartition{
|
||||
Index: uint64(partition),
|
||||
Skipped: bitfield.New(),
|
||||
}
|
||||
partitions = append(partitions, newPartition)
|
||||
}
|
||||
|
||||
params := miner8.SubmitWindowedPoStParams{
|
||||
Deadline: deadline.Index,
|
||||
Partitions: partitions,
|
||||
Proofs: emptyProof,
|
||||
ChainCommitEpoch: deadline.Challenge,
|
||||
ChainCommitRand: checkRand,
|
||||
}
|
||||
|
||||
sp, err := actors.SerializeParams(¶ms)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("serializing params: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("submitting bad PoST for %d paritions\n", len(partitionIndices))
|
||||
smsg, err := api.MpoolPushMessage(ctx, &types.Message{
|
||||
From: minfo.Worker,
|
||||
To: maddr,
|
||||
Method: builtin.MethodsMiner.SubmitWindowedPoSt,
|
||||
Value: big.Zero(),
|
||||
Params: sp,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("mpool push: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Invalid PoST in message %s\n", smsg.Cid())
|
||||
|
||||
wait, err := api.StateWaitMsg(ctx, smsg.Cid(), 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check it executed successfully
|
||||
if wait.Receipt.ExitCode != 0 {
|
||||
fmt.Println(cctx.App.Writer, "Invalid PoST message failed!")
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var generateAndSendConsensusFaultCmd = &cli.Command{
|
||||
Name: "generate-and-send-consensus-fault",
|
||||
Usage: "Provided a block CID mined by the miner, will create another block at the same height, and send both block headers to generate a consensus fault.",
|
||||
Description: `Note: This is meant for testing purposes and should NOT be used on mainnet or you will be slashed`,
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if cctx.NArg() != 1 {
|
||||
return xerrors.Errorf("expected 1 arg (blockCID)")
|
||||
}
|
||||
|
||||
blockCid, err := cid.Parse(cctx.Args().First())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting first arg: %w", err)
|
||||
}
|
||||
|
||||
api, acloser, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting chain head: %w", err)
|
||||
}
|
||||
defer acloser()
|
||||
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
blockHeader, err := api.ChainGetBlock(ctx, blockCid)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting block header: %w", err)
|
||||
}
|
||||
|
||||
maddr := blockHeader.Miner
|
||||
|
||||
minfo, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting miner info: %w", err)
|
||||
}
|
||||
|
||||
// We are changing one field in the block header, then resigning the new block.
|
||||
// This gives two different blocks signed by the same miner at the same height which will result in a consensus fault.
|
||||
blockHeaderCopy := *blockHeader
|
||||
blockHeaderCopy.ForkSignaling = blockHeader.ForkSignaling + 1
|
||||
|
||||
signingBytes, err := blockHeaderCopy.SigningBytes()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting bytes to sign second block: %w", err)
|
||||
}
|
||||
|
||||
sig, err := api.WalletSign(ctx, minfo.Worker, signingBytes)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("signing second block: %w", err)
|
||||
}
|
||||
blockHeaderCopy.BlockSig = sig
|
||||
|
||||
buf1 := new(bytes.Buffer)
|
||||
err = blockHeader.MarshalCBOR(buf1)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("marshalling block header 1: %w", err)
|
||||
}
|
||||
buf2 := new(bytes.Buffer)
|
||||
err = blockHeaderCopy.MarshalCBOR(buf2)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("marshalling block header 2: %w", err)
|
||||
}
|
||||
|
||||
params := miner8.ReportConsensusFaultParams{
|
||||
BlockHeader1: buf1.Bytes(),
|
||||
BlockHeader2: buf2.Bytes(),
|
||||
}
|
||||
|
||||
sp, err := actors.SerializeParams(¶ms)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("serializing params: %w", err)
|
||||
}
|
||||
|
||||
smsg, err := api.MpoolPushMessage(ctx, &types.Message{
|
||||
From: minfo.Worker,
|
||||
To: maddr,
|
||||
Method: builtin.MethodsMiner.ReportConsensusFault,
|
||||
Value: big.Zero(),
|
||||
Params: sp,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("mpool push: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Consensus fault reported in message %s\n", smsg.Cid())
|
||||
|
||||
wait, err := api.StateWaitMsg(ctx, smsg.Cid(), 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check it executed successfully
|
||||
if wait.Receipt.ExitCode != 0 {
|
||||
fmt.Println(cctx.App.Writer, "Report consensus fault failed!")
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ var verifRegVerifyClientCmd = &cli.Command{
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
fmt.Println("DEPRECATED: This behavior is being moved to `lotus verifreg`")
|
||||
fmt.Println("DEPRECATED: This behavior is being moved to `lotus filplus`")
|
||||
froms := cctx.String("from")
|
||||
if froms == "" {
|
||||
return fmt.Errorf("must specify from address with --from")
|
||||
@ -264,7 +264,7 @@ var verifRegListVerifiersCmd = &cli.Command{
|
||||
Usage: "list all verifiers",
|
||||
Hidden: true,
|
||||
Action: func(cctx *cli.Context) error {
|
||||
fmt.Println("DEPRECATED: This behavior is being moved to `lotus verifreg`")
|
||||
fmt.Println("DEPRECATED: This behavior is being moved to `lotus filplus`")
|
||||
api, closer, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -296,7 +296,7 @@ var verifRegListClientsCmd = &cli.Command{
|
||||
Usage: "list all verified clients",
|
||||
Hidden: true,
|
||||
Action: func(cctx *cli.Context) error {
|
||||
fmt.Println("DEPRECATED: This behavior is being moved to `lotus verifreg`")
|
||||
fmt.Println("DEPRECATED: This behavior is being moved to `lotus filplus`")
|
||||
api, closer, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -328,7 +328,7 @@ var verifRegCheckClientCmd = &cli.Command{
|
||||
Usage: "check verified client remaining bytes",
|
||||
Hidden: true,
|
||||
Action: func(cctx *cli.Context) error {
|
||||
fmt.Println("DEPRECATED: This behavior is being moved to `lotus verifreg`")
|
||||
fmt.Println("DEPRECATED: This behavior is being moved to `lotus filplus`")
|
||||
if !cctx.Args().Present() {
|
||||
return fmt.Errorf("must specify client address to check")
|
||||
}
|
||||
@ -364,7 +364,7 @@ var verifRegCheckVerifierCmd = &cli.Command{
|
||||
Usage: "check verifiers remaining bytes",
|
||||
Hidden: true,
|
||||
Action: func(cctx *cli.Context) error {
|
||||
fmt.Println("DEPRECATED: This behavior is being moved to `lotus verifreg`")
|
||||
fmt.Println("DEPRECATED: This behavior is being moved to `lotus filplus`")
|
||||
if !cctx.Args().Present() {
|
||||
return fmt.Errorf("must specify verifier address to check")
|
||||
}
|
||||
|
@ -1685,6 +1685,7 @@ COMMANDS:
|
||||
get-cc-collateral Get the collateral required to pledge a committed capacity sector
|
||||
batching manage batch sector operations
|
||||
match-pending-pieces force a refreshed match of pending pieces to open sectors without manually waiting for more deals
|
||||
compact-partitions removes dead sectors from partitions and reduces the number of partitions used if possible
|
||||
help, h Shows a list of commands or help for one command
|
||||
|
||||
OPTIONS:
|
||||
@ -2026,6 +2027,23 @@ OPTIONS:
|
||||
|
||||
```
|
||||
|
||||
### lotus-miner sectors compact-partitions
|
||||
```
|
||||
NAME:
|
||||
lotus-miner sectors compact-partitions - removes dead sectors from partitions and reduces the number of partitions used if possible
|
||||
|
||||
USAGE:
|
||||
lotus-miner sectors compact-partitions [command options] [arguments...]
|
||||
|
||||
OPTIONS:
|
||||
--deadline value the deadline to compact the partitions in (default: 0)
|
||||
--partitions value list of partitions to compact sectors in
|
||||
--really-do-it Actually send transaction performing the action (default: false)
|
||||
--actor value Specify the address of the miner to run this command
|
||||
--help, -h show help (default: false)
|
||||
|
||||
```
|
||||
|
||||
## lotus-miner proving
|
||||
```
|
||||
NAME:
|
||||
|
Loading…
Reference in New Issue
Block a user