2022-01-14 13:11:04 +00:00
package itests
import (
"context"
2022-03-18 11:32:16 +00:00
"sync/atomic"
2022-01-14 13:11:04 +00:00
"testing"
"time"
2022-03-18 18:07:39 +00:00
"golang.org/x/xerrors"
2022-01-18 10:37:15 +00:00
logging "github.com/ipfs/go-log/v2"
2022-01-14 13:11:04 +00:00
"github.com/stretchr/testify/require"
2022-01-21 12:33:47 +00:00
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
2022-01-18 10:37:15 +00:00
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
2022-01-14 13:11:04 +00:00
"github.com/filecoin-project/lotus/extern/sector-storage/sealtasks"
2022-03-18 18:07:39 +00:00
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
2022-01-14 13:11:04 +00:00
"github.com/filecoin-project/lotus/itests/kit"
2022-03-18 18:07:39 +00:00
"github.com/filecoin-project/lotus/node"
2022-01-21 12:33:47 +00:00
"github.com/filecoin-project/lotus/node/impl"
2022-03-18 18:07:39 +00:00
"github.com/filecoin-project/lotus/node/repo"
2022-01-18 10:37:15 +00:00
"github.com/filecoin-project/lotus/storage"
2022-01-21 12:33:47 +00:00
storage2 "github.com/filecoin-project/specs-storage/storage"
2022-01-14 13:11:04 +00:00
)
func TestWorkerPledge ( t * testing . T ) {
ctx := context . Background ( )
_ , miner , worker , ens := kit . EnsembleWorker ( t , kit . WithAllSubsystems ( ) , kit . ThroughRPC ( ) , kit . WithNoLocalSealing ( true ) ,
kit . WithTaskTypes ( [ ] sealtasks . TaskType { sealtasks . TTFetch , sealtasks . TTCommit1 , sealtasks . TTFinalize , sealtasks . TTAddPiece , sealtasks . TTPreCommit1 , sealtasks . TTPreCommit2 , sealtasks . TTCommit2 , sealtasks . TTUnseal } ) ) // no mock proofs
ens . InterconnectAll ( ) . BeginMining ( 50 * time . Millisecond )
e , err := worker . Enabled ( ctx )
require . NoError ( t , err )
require . True ( t , e )
miner . PledgeSectors ( ctx , 1 , 0 , nil )
}
func TestWinningPostWorker ( t * testing . T ) {
prevIns := build . InsecurePoStValidation
build . InsecurePoStValidation = false
defer func ( ) {
build . InsecurePoStValidation = prevIns
} ( )
ctx := context . Background ( )
client , _ , worker , ens := kit . EnsembleWorker ( t , kit . WithAllSubsystems ( ) , kit . ThroughRPC ( ) ,
kit . WithTaskTypes ( [ ] sealtasks . TaskType { sealtasks . TTGenerateWinningPoSt } ) ) // no mock proofs
ens . InterconnectAll ( ) . BeginMining ( 50 * time . Millisecond )
e , err := worker . Enabled ( ctx )
require . NoError ( t , err )
require . True ( t , e )
client . WaitTillChain ( ctx , kit . HeightAtLeast ( 6 ) )
}
func TestWindowPostWorker ( t * testing . T ) {
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
_ = logging . SetLogLevel ( "storageminer" , "INFO" )
sectors := 2 * 48 * 2
client , miner , _ , ens := kit . EnsembleWorker ( t ,
kit . PresealSectors ( sectors ) , // 2 sectors per partition, 2 partitions in all 48 deadlines
kit . LatestActorsAt ( - 1 ) ,
kit . ThroughRPC ( ) ,
kit . WithTaskTypes ( [ ] sealtasks . TaskType { sealtasks . TTGenerateWindowPoSt } ) )
maddr , err := miner . ActorAddress ( ctx )
require . NoError ( t , err )
di , err := client . StateMinerProvingDeadline ( ctx , maddr , types . EmptyTSK )
require . NoError ( t , err )
bm := ens . InterconnectAll ( ) . BeginMining ( 2 * time . Millisecond ) [ 0 ]
di = di . NextNotElapsed ( )
t . Log ( "Running one proving period" )
waitUntil := di . Open + di . WPoStChallengeWindow * 2 + storage . SubmitConfidence
2022-01-18 11:11:59 +00:00
client . WaitTillChain ( ctx , kit . HeightAtLeast ( waitUntil ) )
2022-01-14 13:11:04 +00:00
t . Log ( "Waiting for post message" )
bm . Stop ( )
2022-01-18 14:53:13 +00:00
var lastPending [ ] * types . SignedMessage
2022-01-14 13:11:04 +00:00
for i := 0 ; i < 500 ; i ++ {
2022-01-18 14:53:13 +00:00
lastPending , err = client . MpoolPending ( ctx , types . EmptyTSK )
2022-01-14 13:11:04 +00:00
require . NoError ( t , err )
2022-01-18 14:53:13 +00:00
if len ( lastPending ) > 0 {
2022-01-14 13:11:04 +00:00
break
}
time . Sleep ( 40 * time . Millisecond )
}
2022-01-18 14:53:13 +00:00
require . Greater ( t , len ( lastPending ) , 0 )
2022-01-14 13:11:04 +00:00
t . Log ( "post message landed" )
bm . MineBlocks ( ctx , 2 * time . Millisecond )
waitUntil = di . Open + di . WPoStChallengeWindow * 3
t . Logf ( "End for head.Height > %d" , waitUntil )
2022-01-18 11:11:59 +00:00
ts := client . WaitTillChain ( ctx , kit . HeightAtLeast ( waitUntil ) )
2022-01-14 13:11:04 +00:00
t . Logf ( "Now head.Height = %d" , ts . Height ( ) )
p , err := client . StateMinerPower ( ctx , maddr , types . EmptyTSK )
require . NoError ( t , err )
ssz , err := miner . ActorSectorSize ( ctx , maddr )
require . NoError ( t , err )
require . Equal ( t , p . MinerPower , p . TotalPower )
require . Equal ( t , p . MinerPower . RawBytePower , types . NewInt ( uint64 ( ssz ) * uint64 ( sectors ) ) )
2022-01-21 12:33:47 +00:00
mid , err := address . IDFromAddress ( maddr )
require . NoError ( t , err )
di , err = client . StateMinerProvingDeadline ( ctx , maddr , types . EmptyTSK )
require . NoError ( t , err )
// Remove one sector in the next deadline (so it's skipped)
{
parts , err := client . StateMinerPartitions ( ctx , maddr , di . Index + 1 , types . EmptyTSK )
require . NoError ( t , err )
require . Greater ( t , len ( parts ) , 0 )
secs := parts [ 0 ] . AllSectors
n , err := secs . Count ( )
require . NoError ( t , err )
require . Equal ( t , uint64 ( 2 ) , n )
// Drop the sector
sid , err := secs . First ( )
2022-03-18 09:59:27 +00:00
require . NoError ( t , err )
2022-01-21 12:33:47 +00:00
t . Logf ( "Drop sector %d; dl %d part %d" , sid , di . Index + 1 , 0 )
err = miner . BaseAPI . ( * impl . StorageMinerAPI ) . IStorageMgr . Remove ( ctx , storage2 . SectorRef {
ID : abi . SectorID {
Miner : abi . ActorID ( mid ) ,
Number : abi . SectorNumber ( sid ) ,
} ,
} )
require . NoError ( t , err )
}
waitUntil = di . Close + di . WPoStChallengeWindow
ts = client . WaitTillChain ( ctx , kit . HeightAtLeast ( waitUntil ) )
t . Logf ( "Now head.Height = %d" , ts . Height ( ) )
p , err = client . StateMinerPower ( ctx , maddr , types . EmptyTSK )
require . NoError ( t , err )
require . Equal ( t , p . MinerPower , p . TotalPower )
require . Equal ( t , p . MinerPower . RawBytePower , types . NewInt ( uint64 ( ssz ) * uint64 ( sectors - 1 ) ) )
2022-01-14 13:11:04 +00:00
}
2022-03-18 11:32:16 +00:00
type badWorkerStorage struct {
stores . Store
2022-03-18 18:07:39 +00:00
badsector * uint64
notBadCount int
2022-03-18 11:32:16 +00:00
}
func ( bs * badWorkerStorage ) GenerateSingleVanillaProof ( ctx context . Context , minerID abi . ActorID , si storiface . PostSectorChallenge , ppt abi . RegisteredPoStProof ) ( [ ] byte , error ) {
2022-03-18 18:07:39 +00:00
if atomic . LoadUint64 ( bs . badsector ) == uint64 ( si . SectorNumber ) {
bs . notBadCount --
if bs . notBadCount < 0 {
return nil , xerrors . New ( "no proof for you" )
}
2022-03-18 11:32:16 +00:00
}
return bs . Store . GenerateSingleVanillaProof ( ctx , minerID , si , ppt )
}
func TestWindowPostWorkerSkipBadSector ( t * testing . T ) {
ctx , cancel := context . WithCancel ( context . Background ( ) )
defer cancel ( )
_ = logging . SetLogLevel ( "storageminer" , "INFO" )
sectors := 2 * 48 * 2
2022-03-18 18:53:59 +00:00
var badsector uint64 = 100000
2022-03-18 11:32:16 +00:00
client , miner , _ , ens := kit . EnsembleWorker ( t ,
kit . PresealSectors ( sectors ) , // 2 sectors per partition, 2 partitions in all 48 deadlines
kit . LatestActorsAt ( - 1 ) ,
kit . ThroughRPC ( ) ,
kit . WithTaskTypes ( [ ] sealtasks . TaskType { sealtasks . TTGenerateWindowPoSt } ) ,
kit . WithWorkerStorage ( func ( store stores . Store ) stores . Store {
2022-03-18 18:07:39 +00:00
return & badWorkerStorage {
2022-03-18 11:32:16 +00:00
Store : store ,
2022-03-18 18:53:59 +00:00
badsector : & badsector ,
2022-03-18 11:32:16 +00:00
}
2022-03-18 18:07:39 +00:00
} ) ,
kit . ConstructorOpts ( node . ApplyIf ( node . IsType ( repo . StorageMiner ) ,
node . Override ( new ( stores . Store ) , func ( store * stores . Remote ) stores . Store {
return & badWorkerStorage {
Store : store ,
2022-03-18 18:53:59 +00:00
badsector : & badsector ,
2022-03-18 18:07:39 +00:00
notBadCount : 1 ,
}
} ) ) ) )
2022-03-18 11:32:16 +00:00
maddr , err := miner . ActorAddress ( ctx )
require . NoError ( t , err )
di , err := client . StateMinerProvingDeadline ( ctx , maddr , types . EmptyTSK )
require . NoError ( t , err )
2022-03-18 18:53:59 +00:00
bm := ens . InterconnectAll ( ) . BeginMiningMustPost ( 2 * time . Millisecond ) [ 0 ]
2022-03-18 11:32:16 +00:00
di = di . NextNotElapsed ( )
t . Log ( "Running one proving period" )
waitUntil := di . Open + di . WPoStChallengeWindow * 2 + storage . SubmitConfidence
client . WaitTillChain ( ctx , kit . HeightAtLeast ( waitUntil ) )
t . Log ( "Waiting for post message" )
bm . Stop ( )
var lastPending [ ] * types . SignedMessage
for i := 0 ; i < 500 ; i ++ {
lastPending , err = client . MpoolPending ( ctx , types . EmptyTSK )
require . NoError ( t , err )
if len ( lastPending ) > 0 {
break
}
time . Sleep ( 40 * time . Millisecond )
}
require . Greater ( t , len ( lastPending ) , 0 )
t . Log ( "post message landed" )
2022-03-18 18:53:59 +00:00
bm . MineBlocksMustPost ( ctx , 2 * time . Millisecond )
2022-03-18 11:32:16 +00:00
waitUntil = di . Open + di . WPoStChallengeWindow * 3
t . Logf ( "End for head.Height > %d" , waitUntil )
ts := client . WaitTillChain ( ctx , kit . HeightAtLeast ( waitUntil ) )
t . Logf ( "Now head.Height = %d" , ts . Height ( ) )
p , err := client . StateMinerPower ( ctx , maddr , types . EmptyTSK )
require . NoError ( t , err )
ssz , err := miner . ActorSectorSize ( ctx , maddr )
require . NoError ( t , err )
require . Equal ( t , p . MinerPower , p . TotalPower )
require . Equal ( t , p . MinerPower . RawBytePower , types . NewInt ( uint64 ( ssz ) * uint64 ( sectors ) ) )
di , err = client . StateMinerProvingDeadline ( ctx , maddr , types . EmptyTSK )
require . NoError ( t , err )
// Remove one sector in the next deadline (so it's skipped)
{
parts , err := client . StateMinerPartitions ( ctx , maddr , di . Index + 1 , types . EmptyTSK )
require . NoError ( t , err )
require . Greater ( t , len ( parts ) , 0 )
secs := parts [ 0 ] . AllSectors
n , err := secs . Count ( )
require . NoError ( t , err )
require . Equal ( t , uint64 ( 2 ) , n )
// Drop the sector
sid , err := secs . First ( )
require . NoError ( t , err )
t . Logf ( "Drop sector %d; dl %d part %d" , sid , di . Index + 1 , 0 )
2022-03-18 18:53:59 +00:00
atomic . StoreUint64 ( & badsector , sid )
2022-03-18 11:32:16 +00:00
require . NoError ( t , err )
}
waitUntil = di . Close + di . WPoStChallengeWindow
ts = client . WaitTillChain ( ctx , kit . HeightAtLeast ( waitUntil ) )
t . Logf ( "Now head.Height = %d" , ts . Height ( ) )
p , err = client . StateMinerPower ( ctx , maddr , types . EmptyTSK )
require . NoError ( t , err )
require . Equal ( t , p . MinerPower , p . TotalPower )
require . Equal ( t , p . MinerPower . RawBytePower , types . NewInt ( uint64 ( ssz ) * uint64 ( sectors - 1 ) ) )
}