202 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			202 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package test
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"math/rand"
 | |
| 	"sync/atomic"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	logging "github.com/ipfs/go-log/v2"
 | |
| 
 | |
| 	"github.com/filecoin-project/go-state-types/abi"
 | |
| 	"github.com/stretchr/testify/require"
 | |
| 
 | |
| 	"github.com/filecoin-project/lotus/build"
 | |
| 	"github.com/filecoin-project/lotus/miner"
 | |
| 	"github.com/filecoin-project/lotus/node/impl"
 | |
| )
 | |
| 
 | |
| //nolint:deadcode,varcheck
 | |
| var log = logging.Logger("apitest")
 | |
| 
 | |
| func (ts *testSuite) testMining(t *testing.T) {
 | |
| 	ctx := context.Background()
 | |
| 	apis, sn := ts.makeNodes(t, OneFull, OneMiner)
 | |
| 	api := apis[0]
 | |
| 
 | |
| 	newHeads, err := api.ChainNotify(ctx)
 | |
| 	require.NoError(t, err)
 | |
| 	initHead := (<-newHeads)[0]
 | |
| 	baseHeight := initHead.Val.Height()
 | |
| 
 | |
| 	h1, err := api.ChainHead(ctx)
 | |
| 	require.NoError(t, err)
 | |
| 	require.Equal(t, int64(h1.Height()), int64(baseHeight))
 | |
| 
 | |
| 	MineUntilBlock(ctx, t, apis[0], sn[0], nil)
 | |
| 	require.NoError(t, err)
 | |
| 
 | |
| 	<-newHeads
 | |
| 
 | |
| 	h2, err := api.ChainHead(ctx)
 | |
| 	require.NoError(t, err)
 | |
| 	require.Greater(t, int64(h2.Height()), int64(h1.Height()))
 | |
| }
 | |
| 
 | |
| func (ts *testSuite) testMiningReal(t *testing.T) {
 | |
| 	build.InsecurePoStValidation = false
 | |
| 	defer func() {
 | |
| 		build.InsecurePoStValidation = true
 | |
| 	}()
 | |
| 
 | |
| 	ctx := context.Background()
 | |
| 	apis, sn := ts.makeNodes(t, OneFull, OneMiner)
 | |
| 	api := apis[0]
 | |
| 
 | |
| 	newHeads, err := api.ChainNotify(ctx)
 | |
| 	require.NoError(t, err)
 | |
| 	at := (<-newHeads)[0].Val.Height()
 | |
| 
 | |
| 	h1, err := api.ChainHead(ctx)
 | |
| 	require.NoError(t, err)
 | |
| 	require.Equal(t, int64(at), int64(h1.Height()))
 | |
| 
 | |
| 	MineUntilBlock(ctx, t, apis[0], sn[0], nil)
 | |
| 	require.NoError(t, err)
 | |
| 
 | |
| 	<-newHeads
 | |
| 
 | |
| 	h2, err := api.ChainHead(ctx)
 | |
| 	require.NoError(t, err)
 | |
| 	require.Greater(t, int64(h2.Height()), int64(h1.Height()))
 | |
| 
 | |
| 	MineUntilBlock(ctx, t, apis[0], sn[0], nil)
 | |
| 	require.NoError(t, err)
 | |
| 
 | |
| 	<-newHeads
 | |
| 
 | |
| 	h3, err := api.ChainHead(ctx)
 | |
| 	require.NoError(t, err)
 | |
| 	require.Greater(t, int64(h3.Height()), int64(h2.Height()))
 | |
| }
 | |
| 
 | |
| func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExport bool) {
 | |
| 	// test making a deal with a fresh miner, and see if it starts to mine
 | |
| 
 | |
| 	ctx := context.Background()
 | |
| 	n, sn := b(t, OneFull, []StorageMiner{
 | |
| 		{Full: 0, Preseal: PresealGenesis},
 | |
| 		{Full: 0, Preseal: 0}, // TODO: Add support for miners on non-first full node
 | |
| 	})
 | |
| 	client := n[0].FullNode.(*impl.FullNodeAPI)
 | |
| 	provider := sn[1]
 | |
| 	genesisMiner := sn[0]
 | |
| 
 | |
| 	addrinfo, err := client.NetAddrsListen(ctx)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	if err := provider.NetConnect(ctx, addrinfo); err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	if err := genesisMiner.NetConnect(ctx, addrinfo); err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	time.Sleep(time.Second)
 | |
| 
 | |
| 	data := make([]byte, 600)
 | |
| 	rand.New(rand.NewSource(5)).Read(data)
 | |
| 
 | |
| 	r := bytes.NewReader(data)
 | |
| 	fcid, err := client.ClientImportLocal(ctx, r)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	fmt.Println("FILE CID: ", fcid)
 | |
| 
 | |
| 	var mine int32 = 1
 | |
| 	done := make(chan struct{})
 | |
| 	minedTwo := make(chan struct{})
 | |
| 
 | |
| 	m2addr, err := sn[1].ActorAddress(context.TODO())
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	go func() {
 | |
| 		defer close(done)
 | |
| 
 | |
| 		complChan := minedTwo
 | |
| 		for atomic.LoadInt32(&mine) != 0 {
 | |
| 			wait := make(chan int)
 | |
| 			mdone := func(mined bool, _ abi.ChainEpoch, err error) {
 | |
| 				n := 0
 | |
| 				if mined {
 | |
| 					n = 1
 | |
| 				}
 | |
| 				wait <- n
 | |
| 			}
 | |
| 
 | |
| 			if err := sn[0].MineOne(ctx, miner.MineReq{Done: mdone}); err != nil {
 | |
| 				t.Error(err)
 | |
| 			}
 | |
| 
 | |
| 			if err := sn[1].MineOne(ctx, miner.MineReq{Done: mdone}); err != nil {
 | |
| 				t.Error(err)
 | |
| 			}
 | |
| 
 | |
| 			expect := <-wait
 | |
| 			expect += <-wait
 | |
| 
 | |
| 			time.Sleep(blocktime)
 | |
| 			if expect == 0 {
 | |
| 				// null block
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			var nodeOneMined bool
 | |
| 			for _, node := range sn {
 | |
| 				mb, err := node.MiningBase(ctx)
 | |
| 				if err != nil {
 | |
| 					t.Error(err)
 | |
| 					return
 | |
| 				}
 | |
| 
 | |
| 				for _, b := range mb.Blocks() {
 | |
| 					if b.Miner == m2addr {
 | |
| 						nodeOneMined = true
 | |
| 						break
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 			}
 | |
| 
 | |
| 			if nodeOneMined && complChan != nil {
 | |
| 				close(complChan)
 | |
| 				complChan = nil
 | |
| 			}
 | |
| 
 | |
| 		}
 | |
| 	}()
 | |
| 
 | |
| 	deal := startDeal(t, ctx, provider, client, fcid, false)
 | |
| 
 | |
| 	// TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this
 | |
| 	time.Sleep(time.Second)
 | |
| 
 | |
| 	waitDealSealed(t, ctx, provider, client, deal, false)
 | |
| 
 | |
| 	<-minedTwo
 | |
| 
 | |
| 	atomic.StoreInt32(&mine, 0)
 | |
| 	fmt.Println("shutting down mining")
 | |
| 	<-done
 | |
| }
 |