test prove then dispute
This commit is contained in:
parent
d412ccdb3f
commit
0ba1306969
@ -48,6 +48,7 @@ type TestStorageNode struct {
|
|||||||
ListenAddr multiaddr.Multiaddr
|
ListenAddr multiaddr.Multiaddr
|
||||||
|
|
||||||
MineOne func(context.Context, miner.MineReq) error
|
MineOne func(context.Context, miner.MineReq) error
|
||||||
|
Stop func(context.Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
var PresealGenesis = -1
|
var PresealGenesis = -1
|
||||||
|
@ -16,13 +16,17 @@ import (
|
|||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-bitfield"
|
"github.com/filecoin-project/go-bitfield"
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
"github.com/filecoin-project/go-state-types/network"
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
"github.com/filecoin-project/lotus/extern/sector-storage/mock"
|
"github.com/filecoin-project/lotus/extern/sector-storage/mock"
|
||||||
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
|
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
|
||||||
|
proof3 "github.com/filecoin-project/specs-actors/v3/actors/runtime/proof"
|
||||||
"github.com/filecoin-project/specs-storage/storage"
|
"github.com/filecoin-project/specs-storage/storage"
|
||||||
|
|
||||||
"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/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"
|
||||||
@ -602,3 +606,206 @@ loop:
|
|||||||
require.Equal(t, p.MinerPower, p.TotalPower)
|
require.Equal(t, p.MinerPower, p.TotalPower)
|
||||||
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)*(nSectors-1)))
|
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)*(nSectors-1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWindowPostDispute(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// First, we configure two miners. After sealing, we're going to turn off the first miner so
|
||||||
|
// it doesn't submit proofs.
|
||||||
|
///
|
||||||
|
// Then we're going to manually submit bad proofs.
|
||||||
|
n, sn := b(t, []FullNodeOpts{
|
||||||
|
FullNodeWithActorsV3At(2),
|
||||||
|
}, []StorageMiner{
|
||||||
|
{Full: 0, Preseal: PresealGenesis},
|
||||||
|
{Full: 0},
|
||||||
|
})
|
||||||
|
|
||||||
|
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||||
|
chainMiner := sn[0]
|
||||||
|
evilMiner := sn[1]
|
||||||
|
|
||||||
|
{
|
||||||
|
addrinfo, err := client.NetAddrsListen(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := chainMiner.NetConnect(ctx, addrinfo); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := evilMiner.NetConnect(ctx, addrinfo); err != nil {
|
||||||
|
t.Fatal(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 := chainMiner.MineOne(ctx, MineNext); err != nil {
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
// context was canceled, ignore the error.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
defer func() {
|
||||||
|
cancel()
|
||||||
|
<-done
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Give the chain miner enough sectors to win every block.
|
||||||
|
pledgeSectors(t, ctx, chainMiner, 10, 0, nil)
|
||||||
|
// And the evil one 1 sector. No cookie for you.
|
||||||
|
pledgeSectors(t, ctx, evilMiner, 1, 0, nil)
|
||||||
|
|
||||||
|
// Let the evil miner's sectors gain power.
|
||||||
|
evilMinerAddr, err := evilMiner.ActorAddress(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
di, err := client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
minerInfo, err := client.StateMinerInfo(ctx, evilMinerAddr, 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
p, err := client.StateMinerPower(ctx, evilMinerAddr, types.EmptyTSK)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
ssz, err := evilMiner.ActorSectorSize(ctx, evilMinerAddr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// make sure it has gained power.
|
||||||
|
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)))
|
||||||
|
|
||||||
|
evilSectors, err := evilMiner.SectorsList(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
evilSectorNo := evilSectors[0] // only one.
|
||||||
|
evilSectorLoc, err := client.StateSectorPartition(ctx, evilMinerAddr, evilSectorNo, types.EmptyTSK)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
fmt.Println("evil miner stopping")
|
||||||
|
|
||||||
|
// Now stop the evil miner, and start manually submitting bad proofs.
|
||||||
|
require.NoError(t, evilMiner.Stop(ctx))
|
||||||
|
|
||||||
|
fmt.Println("evil miner stopped")
|
||||||
|
|
||||||
|
// Wait until we need to prove our sector.
|
||||||
|
for {
|
||||||
|
di, err = client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK)
|
||||||
|
require.NoError(t, err)
|
||||||
|
if di.Index == evilSectorLoc.Deadline {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
build.Clock.Sleep(blocktime)
|
||||||
|
}
|
||||||
|
|
||||||
|
// submit a bad proof
|
||||||
|
{
|
||||||
|
fmt.Println("submitting evil proof")
|
||||||
|
head, err := client.ChainHead(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
commEpoch := di.Open
|
||||||
|
commRand, err := client.ChainGetRandomnessFromTickets(
|
||||||
|
ctx, head.Key(), crypto.DomainSeparationTag_PoStChainCommit,
|
||||||
|
commEpoch, nil,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
params := &miner.SubmitWindowedPoStParams{
|
||||||
|
ChainCommitEpoch: commEpoch,
|
||||||
|
ChainCommitRand: commRand,
|
||||||
|
Deadline: evilSectorLoc.Deadline,
|
||||||
|
Partitions: []miner.PoStPartition{{Index: evilSectorLoc.Partition}},
|
||||||
|
Proofs: []proof3.PoStProof{{
|
||||||
|
PoStProof: minerInfo.WindowPoStProofType,
|
||||||
|
ProofBytes: []byte("I'm soooo very evil."),
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
|
||||||
|
enc, aerr := actors.SerializeParams(params)
|
||||||
|
require.NoError(t, aerr)
|
||||||
|
|
||||||
|
msg := &types.Message{
|
||||||
|
To: evilMinerAddr,
|
||||||
|
Method: miner.Methods.SubmitWindowedPoSt,
|
||||||
|
Params: enc,
|
||||||
|
Value: types.NewInt(0),
|
||||||
|
From: minerInfo.Owner,
|
||||||
|
}
|
||||||
|
sm, err := client.MpoolPushMessage(ctx, msg, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
fmt.Println("waiting for evil proof")
|
||||||
|
rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Zero(t, rec.Receipt.ExitCode, "evil proof not accepted: %s", rec.Receipt.ExitCode.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait until after the proving period.
|
||||||
|
for {
|
||||||
|
di, err := client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK)
|
||||||
|
require.NoError(t, err)
|
||||||
|
if di.Index != evilSectorLoc.Deadline {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
build.Clock.Sleep(blocktime)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("accepted evil proof")
|
||||||
|
|
||||||
|
// Make sure the evil node didn't lose any power.
|
||||||
|
p, err = client.StateMinerPower(ctx, evilMinerAddr, types.EmptyTSK)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)))
|
||||||
|
|
||||||
|
// OBJECTION! The good miner files a DISPUTE!!!!
|
||||||
|
{
|
||||||
|
params := &miner.DisputeWindowedPoStParams{
|
||||||
|
Deadline: evilSectorLoc.Deadline,
|
||||||
|
PoStIndex: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
enc, aerr := actors.SerializeParams(params)
|
||||||
|
require.NoError(t, aerr)
|
||||||
|
|
||||||
|
msg := &types.Message{
|
||||||
|
To: evilMinerAddr,
|
||||||
|
Method: miner.Methods.DisputeWindowedPoSt,
|
||||||
|
Params: enc,
|
||||||
|
Value: types.NewInt(0),
|
||||||
|
From: minerInfo.Owner, // TODO: new miner...
|
||||||
|
}
|
||||||
|
sm, err := client.MpoolPushMessage(ctx, msg, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
fmt.Println("waiting dispute")
|
||||||
|
rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Zero(t, rec.Receipt.ExitCode, "dispute not accepted: %s", rec.Receipt.ExitCode.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||||
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
|
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
|
||||||
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
|
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
|
||||||
|
miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -149,6 +150,7 @@ type DeclareFaultsParams = miner0.DeclareFaultsParams
|
|||||||
type DeclareFaultsRecoveredParams = miner0.DeclareFaultsRecoveredParams
|
type DeclareFaultsRecoveredParams = miner0.DeclareFaultsRecoveredParams
|
||||||
type SubmitWindowedPoStParams = miner0.SubmitWindowedPoStParams
|
type SubmitWindowedPoStParams = miner0.SubmitWindowedPoStParams
|
||||||
type ProveCommitSectorParams = miner0.ProveCommitSectorParams
|
type ProveCommitSectorParams = miner0.ProveCommitSectorParams
|
||||||
|
type DisputeWindowedPoStParams = miner3.DisputeWindowedPoStParams
|
||||||
|
|
||||||
func PreferredSealProofTypeFromWindowPoStType(nver network.Version, proof abi.RegisteredPoStProof) (abi.RegisteredSealProof, error) {
|
func PreferredSealProofTypeFromWindowPoStType(nver network.Version, proof abi.RegisteredPoStProof) (abi.RegisteredSealProof, error) {
|
||||||
// We added support for the new proofs in network version 7, and removed support for the old
|
// We added support for the new proofs in network version 7, and removed support for the old
|
||||||
|
@ -198,3 +198,13 @@ func TestPaymentChannels(t *testing.T) {
|
|||||||
|
|
||||||
test.TestPaymentChannels(t, builder.MockSbBuilder, 5*time.Millisecond)
|
test.TestPaymentChannels(t, builder.MockSbBuilder, 5*time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWindowPostDispute(t *testing.T) {
|
||||||
|
logging.SetLogLevel("miner", "ERROR")
|
||||||
|
logging.SetLogLevel("chainstore", "ERROR")
|
||||||
|
logging.SetLogLevel("chain", "ERROR")
|
||||||
|
logging.SetLogLevel("sub", "ERROR")
|
||||||
|
logging.SetLogLevel("storageminer", "ERROR")
|
||||||
|
|
||||||
|
test.TestWindowPostDispute(t, builder.MockSbBuilder, 2*time.Millisecond)
|
||||||
|
}
|
||||||
|
@ -148,7 +148,7 @@ func CreateTestStorageNode(ctx context.Context, t *testing.T, waddr address.Addr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return test.TestStorageNode{StorageMiner: minerapi, MineOne: mineOne}
|
return test.TestStorageNode{StorageMiner: minerapi, MineOne: mineOne, Stop: stop}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Builder(t *testing.T, fullOpts []test.FullNodeOpts, storage []test.StorageMiner) ([]test.TestNode, []test.TestStorageNode) {
|
func Builder(t *testing.T, fullOpts []test.FullNodeOpts, storage []test.StorageMiner) ([]test.TestNode, []test.TestStorageNode) {
|
||||||
|
Loading…
Reference in New Issue
Block a user