ensure we can't dispute a correct window post

This commit is contained in:
Steven Allen 2021-01-22 14:30:54 -08:00
parent 735d30af55
commit 0a294f146f
2 changed files with 151 additions and 10 deletions

View File

@ -27,7 +27,7 @@ import (
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner" minerActor "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
bminer "github.com/filecoin-project/lotus/miner" bminer "github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/lotus/node/impl" "github.com/filecoin-project/lotus/node/impl"
@ -747,7 +747,7 @@ func TestWindowPostDispute(t *testing.T, b APIBuilder, blocktime time.Duration)
// OBJECTION! The good miner files a DISPUTE!!!! // OBJECTION! The good miner files a DISPUTE!!!!
{ {
params := &miner.DisputeWindowedPoStParams{ params := &minerActor.DisputeWindowedPoStParams{
Deadline: evilSectorLoc.Deadline, Deadline: evilSectorLoc.Deadline,
PoStIndex: 0, PoStIndex: 0,
} }
@ -757,7 +757,7 @@ func TestWindowPostDispute(t *testing.T, b APIBuilder, blocktime time.Duration)
msg := &types.Message{ msg := &types.Message{
To: evilMinerAddr, To: evilMinerAddr,
Method: miner.Methods.DisputeWindowedPoSt, Method: minerActor.Methods.DisputeWindowedPoSt,
Params: enc, Params: enc,
Value: types.NewInt(0), Value: types.NewInt(0),
From: defaultFrom, From: defaultFrom,
@ -769,7 +769,6 @@ func TestWindowPostDispute(t *testing.T, b APIBuilder, blocktime time.Duration)
rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence) rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence)
require.NoError(t, err) require.NoError(t, err)
require.Zero(t, rec.Receipt.ExitCode, "dispute not accepted: %s", rec.Receipt.ExitCode.Error()) require.Zero(t, rec.Receipt.ExitCode, "dispute not accepted: %s", rec.Receipt.ExitCode.Error())
fmt.Println("GASS!!!: ", rec.Receipt.GasUsed)
} }
// Objection SUSTAINED! // Objection SUSTAINED!
@ -787,8 +786,8 @@ func TestWindowPostDispute(t *testing.T, b APIBuilder, blocktime time.Duration)
minerInfo, err := client.StateMinerInfo(ctx, evilMinerAddr, types.EmptyTSK) minerInfo, err := client.StateMinerInfo(ctx, evilMinerAddr, types.EmptyTSK)
require.NoError(t, err) require.NoError(t, err)
params := &miner.DeclareFaultsRecoveredParams{ params := &minerActor.DeclareFaultsRecoveredParams{
Recoveries: []miner.RecoveryDeclaration{{ Recoveries: []minerActor.RecoveryDeclaration{{
Deadline: evilSectorLoc.Deadline, Deadline: evilSectorLoc.Deadline,
Partition: evilSectorLoc.Partition, Partition: evilSectorLoc.Partition,
Sectors: bitfield.NewFromSet([]uint64{uint64(evilSectorNo)}), Sectors: bitfield.NewFromSet([]uint64{uint64(evilSectorNo)}),
@ -800,7 +799,7 @@ func TestWindowPostDispute(t *testing.T, b APIBuilder, blocktime time.Duration)
msg := &types.Message{ msg := &types.Message{
To: evilMinerAddr, To: evilMinerAddr,
Method: miner.Methods.DeclareFaultsRecovered, Method: minerActor.Methods.DeclareFaultsRecovered,
Params: enc, Params: enc,
Value: types.FromFil(30), // repay debt. Value: types.FromFil(30), // repay debt.
From: minerInfo.Owner, From: minerInfo.Owner,
@ -859,11 +858,11 @@ func submitBadProof(
if err != nil { if err != nil {
return err return err
} }
params := &miner.SubmitWindowedPoStParams{ params := &minerActor.SubmitWindowedPoStParams{
ChainCommitEpoch: commEpoch, ChainCommitEpoch: commEpoch,
ChainCommitRand: commRand, ChainCommitRand: commRand,
Deadline: dlIdx, Deadline: dlIdx,
Partitions: []miner.PoStPartition{{Index: partIdx}}, Partitions: []minerActor.PoStPartition{{Index: partIdx}},
Proofs: []proof3.PoStProof{{ Proofs: []proof3.PoStProof{{
PoStProof: minerInfo.WindowPoStProofType, PoStProof: minerInfo.WindowPoStProofType,
ProofBytes: []byte("I'm soooo very evil."), ProofBytes: []byte("I'm soooo very evil."),
@ -877,7 +876,7 @@ func submitBadProof(
msg := &types.Message{ msg := &types.Message{
To: maddr, To: maddr,
Method: miner.Methods.SubmitWindowedPoSt, Method: minerActor.Methods.SubmitWindowedPoSt,
Params: enc, Params: enc,
Value: types.NewInt(0), Value: types.NewInt(0),
From: from, From: from,
@ -896,3 +895,132 @@ func submitBadProof(
} }
return nil return nil
} }
func TestWindowPostDisputeFails(t *testing.T, b APIBuilder, blocktime time.Duration) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV3At(2)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
{
addrinfo, err := client.NetAddrsListen(ctx)
if err != nil {
t.Fatal(err)
}
if err := miner.NetConnect(ctx, addrinfo); err != nil {
t.Fatal(err)
}
}
defaultFrom, err := client.WalletDefaultAddress(ctx)
require.NoError(t, err)
maddr, err := miner.ActorAddress(ctx)
require.NoError(t, err)
build.Clock.Sleep(time.Second)
// Mine with the _second_ node (the good one).
done := make(chan struct{})
go func() {
defer close(done)
for ctx.Err() == nil {
build.Clock.Sleep(blocktime)
if err := miner.MineOne(ctx, MineNext); err != nil {
if ctx.Err() != nil {
// context was canceled, ignore the error.
return
}
t.Error(err)
}
}
}()
defer func() {
cancel()
<-done
}()
pledgeSectors(t, ctx, miner, 10, 0, nil)
di, err := client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
fmt.Printf("Running one proving period\n")
fmt.Printf("End for head.Height > %d\n", di.PeriodStart+di.WPoStProvingPeriod*2)
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
if head.Height() > di.PeriodStart+di.WPoStProvingPeriod*2 {
fmt.Printf("Now head.Height = %d\n", head.Height())
break
}
build.Clock.Sleep(blocktime)
}
ssz, err := miner.ActorSectorSize(ctx, maddr)
require.NoError(t, err)
expectedPower := types.NewInt(uint64(ssz) * (GenesisPreseals + 10))
p, err := client.StateMinerPower(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
// make sure it has gained power.
require.Equal(t, p.MinerPower.RawBytePower, expectedPower)
// Wait until a proof has been submitted.
var targetDeadline uint64
waitForProof:
for {
deadlines, err := client.StateMinerDeadlines(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
for dlIdx, dl := range deadlines {
nonEmpty, err := dl.PostSubmissions.IsEmpty()
require.NoError(t, err)
if nonEmpty {
targetDeadline = uint64(dlIdx)
break waitForProof
}
}
build.Clock.Sleep(blocktime)
}
for {
di, err := client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
// wait until the deadline finishes.
if di.Index == ((targetDeadline + 1) % di.WPoStPeriodDeadlines) {
break
}
build.Clock.Sleep(blocktime)
}
// Try to object to the proof. This should fail.
{
params := &minerActor.DisputeWindowedPoStParams{
Deadline: targetDeadline,
PoStIndex: 0,
}
enc, aerr := actors.SerializeParams(params)
require.NoError(t, aerr)
msg := &types.Message{
To: maddr,
Method: minerActor.Methods.DisputeWindowedPoSt,
Params: enc,
Value: types.NewInt(0),
From: defaultFrom,
}
_, err := client.MpoolPushMessage(ctx, msg, nil)
require.Error(t, err)
require.Contains(t, err.Error(), "failed to dispute valid post (RetCode=16)")
}
}

View File

@ -211,3 +211,16 @@ func TestWindowPostDispute(t *testing.T) {
test.TestWindowPostDispute(t, builder.MockSbBuilder, 2*time.Millisecond) test.TestWindowPostDispute(t, builder.MockSbBuilder, 2*time.Millisecond)
} }
func TestWindowPostDisputeFails(t *testing.T) {
if os.Getenv("LOTUS_TEST_WINDOW_POST") != "1" {
t.Skip("this takes a few minutes, set LOTUS_TEST_WINDOW_POST=1 to run")
}
logging.SetLogLevel("miner", "ERROR")
logging.SetLogLevel("chainstore", "ERROR")
logging.SetLogLevel("chain", "ERROR")
logging.SetLogLevel("sub", "ERROR")
logging.SetLogLevel("storageminer", "ERROR")
test.TestWindowPostDisputeFails(t, builder.MockSbBuilder, 2*time.Millisecond)
}