Merge pull request #1590 from filecoin-project/feat/newminer
Better mining tests, Fix no-sector miner panic
This commit is contained in:
commit
233c84ef3e
@ -24,6 +24,8 @@ type StorageMiner interface {
|
|||||||
|
|
||||||
ActorSectorSize(context.Context, address.Address) (abi.SectorSize, error)
|
ActorSectorSize(context.Context, address.Address) (abi.SectorSize, error)
|
||||||
|
|
||||||
|
MiningBase(context.Context) (*types.TipSet, error)
|
||||||
|
|
||||||
// Temp api for testing
|
// Temp api for testing
|
||||||
PledgeSector(context.Context) error
|
PledgeSector(context.Context) error
|
||||||
|
|
||||||
|
@ -176,6 +176,8 @@ type StorageMinerStruct struct {
|
|||||||
ActorAddress func(context.Context) (address.Address, error) `perm:"read"`
|
ActorAddress func(context.Context) (address.Address, error) `perm:"read"`
|
||||||
ActorSectorSize func(context.Context, address.Address) (abi.SectorSize, error) `perm:"read"`
|
ActorSectorSize func(context.Context, address.Address) (abi.SectorSize, error) `perm:"read"`
|
||||||
|
|
||||||
|
MiningBase func(context.Context) (*types.TipSet, error)
|
||||||
|
|
||||||
MarketImportDealData func(context.Context, cid.Cid, string) error `perm:"write"`
|
MarketImportDealData func(context.Context, cid.Cid, string) error `perm:"write"`
|
||||||
MarketListDeals func(ctx context.Context) ([]storagemarket.StorageDeal, error) `perm:"read"`
|
MarketListDeals func(ctx context.Context) ([]storagemarket.StorageDeal, error) `perm:"read"`
|
||||||
MarketListIncompleteDeals func(ctx context.Context) ([]storagemarket.MinerDeal, error) `perm:"read"`
|
MarketListIncompleteDeals func(ctx context.Context) ([]storagemarket.MinerDeal, error) `perm:"read"`
|
||||||
@ -662,6 +664,10 @@ func (c *StorageMinerStruct) ActorAddress(ctx context.Context) (address.Address,
|
|||||||
return c.Internal.ActorAddress(ctx)
|
return c.Internal.ActorAddress(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *StorageMinerStruct) MiningBase(ctx context.Context) (*types.TipSet, error) {
|
||||||
|
return c.Internal.MiningBase(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *StorageMinerStruct) ActorSectorSize(ctx context.Context, addr address.Address) (abi.SectorSize, error) {
|
func (c *StorageMinerStruct) ActorSectorSize(ctx context.Context, addr address.Address) (abi.SectorSize, error) {
|
||||||
return c.Internal.ActorSectorSize(ctx, addr)
|
return c.Internal.ActorSectorSize(ctx, addr)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/ipfs/go-cid"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
@ -36,7 +37,7 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport
|
|||||||
os.Setenv("BELLMAN_NO_GPU", "1")
|
os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
n, sn := b(t, 1, []int{0})
|
n, sn := b(t, 1, oneMiner)
|
||||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||||
miner := sn[0]
|
miner := sn[0]
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport
|
|||||||
defer close(done)
|
defer close(done)
|
||||||
for mine {
|
for mine {
|
||||||
time.Sleep(blocktime)
|
time.Sleep(blocktime)
|
||||||
if err := sn[0].MineOne(ctx); err != nil {
|
if err := sn[0].MineOne(ctx, func(bool) {}); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,7 +74,7 @@ func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
|||||||
os.Setenv("BELLMAN_NO_GPU", "1")
|
os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
n, sn := b(t, 1, []int{0})
|
n, sn := b(t, 1, oneMiner)
|
||||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||||
miner := sn[0]
|
miner := sn[0]
|
||||||
|
|
||||||
@ -94,7 +95,7 @@ func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
|||||||
defer close(done)
|
defer close(done)
|
||||||
for mine {
|
for mine {
|
||||||
time.Sleep(blocktime)
|
time.Sleep(blocktime)
|
||||||
if err := sn[0].MineOne(ctx); err != nil {
|
if err := sn[0].MineOne(ctx, func(bool) {}); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,7 +111,7 @@ func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
|||||||
|
|
||||||
func makeDeal(t *testing.T, ctx context.Context, rseed int, client *impl.FullNodeAPI, miner TestStorageNode, carExport bool) {
|
func makeDeal(t *testing.T, ctx context.Context, rseed int, client *impl.FullNodeAPI, miner TestStorageNode, carExport bool) {
|
||||||
data := make([]byte, 1600)
|
data := make([]byte, 1600)
|
||||||
rand.New(rand.NewSource(6)).Read(data)
|
rand.New(rand.NewSource(int64(rseed))).Read(data)
|
||||||
|
|
||||||
r := bytes.NewReader(data)
|
r := bytes.NewReader(data)
|
||||||
fcid, err := client.ClientImportLocal(ctx, r)
|
fcid, err := client.ClientImportLocal(ctx, r)
|
||||||
@ -118,13 +119,25 @@ func makeDeal(t *testing.T, ctx context.Context, rseed int, client *impl.FullNod
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println("FILE CID: ", fcid)
|
||||||
|
|
||||||
|
deal := startDeal(t, ctx, miner, client, fcid)
|
||||||
|
|
||||||
|
// 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, client, deal)
|
||||||
|
|
||||||
|
// Retrieval
|
||||||
|
|
||||||
|
testRetrieval(t, ctx, err, client, fcid, carExport, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client *impl.FullNodeAPI, fcid cid.Cid) *cid.Cid {
|
||||||
maddr, err := miner.ActorAddress(ctx)
|
maddr, err := miner.ActorAddress(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("FILE CID: ", fcid)
|
|
||||||
|
|
||||||
addr, err := client.WalletDefaultAddress(ctx)
|
addr, err := client.WalletDefaultAddress(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -139,9 +152,10 @@ func makeDeal(t *testing.T, ctx context.Context, rseed int, client *impl.FullNod
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%+v", err)
|
t.Fatalf("%+v", err)
|
||||||
}
|
}
|
||||||
|
return deal
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this
|
func waitDealSealed(t *testing.T, ctx context.Context, client *impl.FullNodeAPI, deal *cid.Cid) {
|
||||||
time.Sleep(time.Second)
|
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
di, err := client.ClientGetDealInfo(ctx, *deal)
|
di, err := client.ClientGetDealInfo(ctx, *deal)
|
||||||
@ -162,9 +176,9 @@ loop:
|
|||||||
fmt.Println("Deal state: ", storagemarket.DealStates[di.State])
|
fmt.Println("Deal state: ", storagemarket.DealStates[di.State])
|
||||||
time.Sleep(time.Second / 2)
|
time.Sleep(time.Second / 2)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieval
|
func testRetrieval(t *testing.T, ctx context.Context, err error, client *impl.FullNodeAPI, fcid cid.Cid, carExport bool, data []byte) {
|
||||||
|
|
||||||
offers, err := client.ClientFindData(ctx, fcid)
|
offers, err := client.ClientFindData(ctx, fcid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -200,35 +214,40 @@ loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if carExport {
|
if carExport {
|
||||||
bserv := dstest.Bserv()
|
rdata = extractCarData(t, ctx, rdata, rpath)
|
||||||
ch, err := car.LoadCar(bserv.Blockstore(), bytes.NewReader(rdata))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
b, err := bserv.GetBlock(ctx, ch.Roots[0])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
nd, err := ipld.Decode(b)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
dserv := dag.NewDAGService(bserv)
|
|
||||||
fil, err := unixfile.NewUnixfsFile(ctx, dserv, nd)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
outPath := filepath.Join(rpath, "retLoadedCAR")
|
|
||||||
if err := files.WriteTo(fil, outPath); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
rdata, err = ioutil.ReadFile(outPath)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(rdata, data) {
|
if !bytes.Equal(rdata, data) {
|
||||||
t.Fatal("wrong data retrieved")
|
t.Fatal("wrong data retrieved")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func extractCarData(t *testing.T, ctx context.Context, rdata []byte, rpath string) []byte {
|
||||||
|
bserv := dstest.Bserv()
|
||||||
|
ch, err := car.LoadCar(bserv.Blockstore(), bytes.NewReader(rdata))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
b, err := bserv.GetBlock(ctx, ch.Roots[0])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
nd, err := ipld.Decode(b)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
dserv := dag.NewDAGService(bserv)
|
||||||
|
fil, err := unixfile.NewUnixfsFile(ctx, dserv, nd)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
outPath := filepath.Join(rpath, "retLoadedCAR")
|
||||||
|
if err := files.WriteTo(fil, outPath); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
rdata, err = ioutil.ReadFile(outPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return rdata
|
||||||
|
}
|
||||||
|
@ -1,16 +1,28 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
logging "github.com/ipfs/go-log/v2"
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/node/impl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var log = logging.Logger("apitest")
|
||||||
|
|
||||||
func (ts *testSuite) testMining(t *testing.T) {
|
func (ts *testSuite) testMining(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
apis, sn := ts.makeNodes(t, 1, []int{0})
|
apis, sn := ts.makeNodes(t, 1, oneMiner)
|
||||||
api := apis[0]
|
api := apis[0]
|
||||||
|
|
||||||
h1, err := api.ChainHead(ctx)
|
h1, err := api.ChainHead(ctx)
|
||||||
@ -21,7 +33,7 @@ func (ts *testSuite) testMining(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
<-newHeads
|
<-newHeads
|
||||||
|
|
||||||
err = sn[0].MineOne(ctx)
|
err = sn[0].MineOne(ctx, func(bool) {})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
<-newHeads
|
<-newHeads
|
||||||
@ -30,3 +42,120 @@ func (ts *testSuite) testMining(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, abi.ChainEpoch(1), h2.Height())
|
require.Equal(t, abi.ChainEpoch(1), h2.Height())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExport bool) {
|
||||||
|
os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
|
|
||||||
|
// test making a deal with a fresh miner, and see if it starts to mine
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
n, sn := b(t, 1, []StorageMiner{
|
||||||
|
{Full: 0, Preseal: PresealGenesis},
|
||||||
|
{Full: 0, Preseal: 0}, // TODO: Add support for storage 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{})
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(done)
|
||||||
|
|
||||||
|
prevExpect := 0
|
||||||
|
for atomic.LoadInt32(&mine) != 0 {
|
||||||
|
wait := make(chan int, 2)
|
||||||
|
mdone := func(mined bool) {
|
||||||
|
go func() {
|
||||||
|
n := 0
|
||||||
|
if mined {
|
||||||
|
n = 1
|
||||||
|
}
|
||||||
|
wait <- n
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := sn[0].MineOne(ctx, mdone); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := sn[1].MineOne(ctx, mdone); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect := <-wait
|
||||||
|
expect += <-wait
|
||||||
|
|
||||||
|
time.Sleep(blocktime)
|
||||||
|
|
||||||
|
for {
|
||||||
|
n := 0
|
||||||
|
for i, node := range sn {
|
||||||
|
mb, err := node.MiningBase(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mb.Cids()) != expect {
|
||||||
|
log.Warnf("node %d mining base not complete (%d, want %d)", i, len(mb.Cids()), expect)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
if n == len(sn) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(blocktime)
|
||||||
|
}
|
||||||
|
|
||||||
|
if prevExpect == 2 && expect == 2 && minedTwo != nil {
|
||||||
|
close(minedTwo)
|
||||||
|
minedTwo = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
prevExpect = expect
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
deal := startDeal(t, ctx, provider, client, fcid)
|
||||||
|
|
||||||
|
// 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, client, deal)
|
||||||
|
|
||||||
|
<-minedTwo
|
||||||
|
|
||||||
|
atomic.StoreInt32(&mine, 0)
|
||||||
|
fmt.Println("shutting down mining")
|
||||||
|
<-done
|
||||||
|
}
|
||||||
|
@ -16,7 +16,14 @@ type TestNode struct {
|
|||||||
type TestStorageNode struct {
|
type TestStorageNode struct {
|
||||||
api.StorageMiner
|
api.StorageMiner
|
||||||
|
|
||||||
MineOne func(context.Context) error
|
MineOne func(context.Context, func(bool)) error
|
||||||
|
}
|
||||||
|
|
||||||
|
var PresealGenesis = -1
|
||||||
|
|
||||||
|
type StorageMiner struct {
|
||||||
|
Full int
|
||||||
|
Preseal int
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIBuilder is a function which is invoked in test suite to provide
|
// APIBuilder is a function which is invoked in test suite to provide
|
||||||
@ -24,7 +31,7 @@ type TestStorageNode struct {
|
|||||||
//
|
//
|
||||||
// storage array defines storage nodes, numbers in the array specify full node
|
// storage array defines storage nodes, numbers in the array specify full node
|
||||||
// index the storage node 'belongs' to
|
// index the storage node 'belongs' to
|
||||||
type APIBuilder func(t *testing.T, nFull int, storage []int) ([]TestNode, []TestStorageNode)
|
type APIBuilder func(t *testing.T, nFull int, storage []StorageMiner) ([]TestNode, []TestStorageNode)
|
||||||
type testSuite struct {
|
type testSuite struct {
|
||||||
makeNodes APIBuilder
|
makeNodes APIBuilder
|
||||||
}
|
}
|
||||||
@ -41,9 +48,11 @@ func TestApis(t *testing.T, b APIBuilder) {
|
|||||||
t.Run("testMining", ts.testMining)
|
t.Run("testMining", ts.testMining)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var oneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}}
|
||||||
|
|
||||||
func (ts *testSuite) testVersion(t *testing.T) {
|
func (ts *testSuite) testVersion(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
apis, _ := ts.makeNodes(t, 1, []int{0})
|
apis, _ := ts.makeNodes(t, 1, oneMiner)
|
||||||
api := apis[0]
|
api := apis[0]
|
||||||
|
|
||||||
v, err := api.Version(ctx)
|
v, err := api.Version(ctx)
|
||||||
@ -57,7 +66,7 @@ func (ts *testSuite) testVersion(t *testing.T) {
|
|||||||
|
|
||||||
func (ts *testSuite) testID(t *testing.T) {
|
func (ts *testSuite) testID(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
apis, _ := ts.makeNodes(t, 1, []int{0})
|
apis, _ := ts.makeNodes(t, 1, oneMiner)
|
||||||
api := apis[0]
|
api := apis[0]
|
||||||
|
|
||||||
id, err := api.ID(ctx)
|
id, err := api.ID(ctx)
|
||||||
@ -69,7 +78,7 @@ func (ts *testSuite) testID(t *testing.T) {
|
|||||||
|
|
||||||
func (ts *testSuite) testConnectTwo(t *testing.T) {
|
func (ts *testSuite) testConnectTwo(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
apis, _ := ts.makeNodes(t, 2, []int{0})
|
apis, _ := ts.makeNodes(t, 2, oneMiner)
|
||||||
|
|
||||||
p, err := apis[0].NetPeers(ctx)
|
p, err := apis[0].NetPeers(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -148,6 +148,10 @@ func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *S
|
|||||||
return nil, xerrors.Errorf("getting proving set: %w", err)
|
return nil, xerrors.Errorf("getting proving set: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(sectorSet) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
spt, err := ffiwrapper.SealProofTypeFromSectorSize(mas.Info.SectorSize)
|
spt, err := ffiwrapper.SealProofTypeFromSectorSize(mas.Info.SectorSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("getting seal proof type: %w", err)
|
return nil, xerrors.Errorf("getting seal proof type: %w", err)
|
||||||
@ -449,6 +453,10 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, tsk types.TipSetKey
|
|||||||
return nil, xerrors.Errorf("getting wpost proving set: %w", err)
|
return nil, xerrors.Errorf("getting wpost proving set: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(sectors) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
mpow, tpow, err := GetPowerRaw(ctx, sm, lbst, maddr)
|
mpow, tpow, err := GetPowerRaw(ctx, sm, lbst, maddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to get power: %w", err)
|
return nil, xerrors.Errorf("failed to get power: %w", err)
|
||||||
|
4
go.sum
4
go.sum
@ -28,7 +28,9 @@ github.com/Stebalien/go-bitfield v0.0.1/go.mod h1:GNjFpasyUVkHMsfEOk8EFLJ9syQ6SI
|
|||||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||||
github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw=
|
github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw=
|
||||||
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
|
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
|
||||||
github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs=
|
github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs=
|
||||||
@ -806,6 +808,7 @@ github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAri
|
|||||||
github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
|
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
||||||
@ -1095,6 +1098,7 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
|
|||||||
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
|
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
|
||||||
google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
|
google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
@ -25,7 +25,8 @@ import (
|
|||||||
|
|
||||||
var log = logging.Logger("miner")
|
var log = logging.Logger("miner")
|
||||||
|
|
||||||
type waitFunc func(ctx context.Context, baseTime uint64) error
|
// returns a callback reporting whether we mined a blocks in this round
|
||||||
|
type waitFunc func(ctx context.Context, baseTime uint64) (func(bool), error)
|
||||||
|
|
||||||
func NewMiner(api api.FullNode, epp gen.WinningPoStProver, beacon beacon.RandomBeacon) *Miner {
|
func NewMiner(api api.FullNode, epp gen.WinningPoStProver, beacon beacon.RandomBeacon) *Miner {
|
||||||
arc, err := lru.NewARC(10000)
|
arc, err := lru.NewARC(10000)
|
||||||
@ -37,12 +38,12 @@ func NewMiner(api api.FullNode, epp gen.WinningPoStProver, beacon beacon.RandomB
|
|||||||
api: api,
|
api: api,
|
||||||
epp: epp,
|
epp: epp,
|
||||||
beacon: beacon,
|
beacon: beacon,
|
||||||
waitFunc: func(ctx context.Context, baseTime uint64) error {
|
waitFunc: func(ctx context.Context, baseTime uint64) (func(bool), error) {
|
||||||
// Wait around for half the block time in case other parents come in
|
// Wait around for half the block time in case other parents come in
|
||||||
deadline := baseTime + build.PropagationDelay
|
deadline := baseTime + build.PropagationDelay
|
||||||
time.Sleep(time.Until(time.Unix(int64(deadline), 0)))
|
time.Sleep(time.Until(time.Unix(int64(deadline), 0)))
|
||||||
|
|
||||||
return nil
|
return func(bool) {}, nil
|
||||||
},
|
},
|
||||||
minedBlockHeights: arc,
|
minedBlockHeights: arc,
|
||||||
}
|
}
|
||||||
@ -167,7 +168,8 @@ eventLoop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait until propagation delay period after block we plan to mine on
|
// Wait until propagation delay period after block we plan to mine on
|
||||||
if err := m.waitFunc(ctx, prebase.ts.MinTimestamp()); err != nil {
|
onDone, err := m.waitFunc(ctx, prebase.TipSet.MinTimestamp())
|
||||||
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -177,8 +179,8 @@ eventLoop:
|
|||||||
log.Errorf("failed to get best mining candidate: %s", err)
|
log.Errorf("failed to get best mining candidate: %s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if base.ts.Equals(lastBase.ts) && lastBase.nullRounds == base.nullRounds {
|
if base.TipSet.Equals(lastBase.TipSet) && lastBase.NullRounds == base.NullRounds {
|
||||||
log.Warnf("BestMiningCandidate from the previous round: %s (nulls:%d)", lastBase.ts.Cids(), lastBase.nullRounds)
|
log.Warnf("BestMiningCandidate from the previous round: %s (nulls:%d)", lastBase.TipSet.Cids(), lastBase.NullRounds)
|
||||||
time.Sleep(build.BlockDelay * time.Second)
|
time.Sleep(build.BlockDelay * time.Second)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -197,6 +199,8 @@ eventLoop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDone(len(blks) != 0)
|
||||||
|
|
||||||
if len(blks) != 0 {
|
if len(blks) != 0 {
|
||||||
btime := time.Unix(int64(blks[0].Header.Timestamp), 0)
|
btime := time.Unix(int64(blks[0].Header.Timestamp), 0)
|
||||||
if time.Now().Before(btime) {
|
if time.Now().Before(btime) {
|
||||||
@ -232,7 +236,7 @@ eventLoop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nextRound := time.Unix(int64(base.ts.MinTimestamp()+uint64(build.BlockDelay*base.nullRounds)), 0)
|
nextRound := time.Unix(int64(base.TipSet.MinTimestamp()+uint64(build.BlockDelay*base.NullRounds)), 0)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-time.After(time.Until(nextRound)):
|
case <-time.After(time.Until(nextRound)):
|
||||||
@ -248,8 +252,8 @@ eventLoop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MiningBase struct {
|
type MiningBase struct {
|
||||||
ts *types.TipSet
|
TipSet *types.TipSet
|
||||||
nullRounds abi.ChainEpoch
|
NullRounds abi.ChainEpoch
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) {
|
func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) {
|
||||||
@ -259,7 +263,7 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if m.lastWork != nil {
|
if m.lastWork != nil {
|
||||||
if m.lastWork.ts.Equals(bts) {
|
if m.lastWork.TipSet.Equals(bts) {
|
||||||
return m.lastWork, nil
|
return m.lastWork, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +271,7 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ltsw, err := m.api.ChainTipSetWeight(ctx, m.lastWork.ts.Key())
|
ltsw, err := m.api.ChainTipSetWeight(ctx, m.lastWork.TipSet.Key())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -277,7 +281,7 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m.lastWork = &MiningBase{ts: bts}
|
m.lastWork = &MiningBase{TipSet: bts}
|
||||||
return m.lastWork, nil
|
return m.lastWork, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,15 +295,19 @@ func (m *Miner) hasPower(ctx context.Context, addr address.Address, ts *types.Ti
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningBase) (*types.BlockMsg, error) {
|
func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningBase) (*types.BlockMsg, error) {
|
||||||
log.Debugw("attempting to mine a block", "tipset", types.LogCids(base.ts.Cids()))
|
log.Debugw("attempting to mine a block", "tipset", types.LogCids(base.TipSet.Cids()))
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
round := base.ts.Height() + base.nullRounds + 1
|
round := base.TipSet.Height() + base.NullRounds + 1
|
||||||
|
|
||||||
mbi, err := m.api.MinerGetBaseInfo(ctx, addr, round, base.ts.Key())
|
mbi, err := m.api.MinerGetBaseInfo(ctx, addr, round, base.TipSet.Key())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to get mining base info: %w", err)
|
return nil, xerrors.Errorf("failed to get mining base info: %w", err)
|
||||||
}
|
}
|
||||||
|
if mbi == nil {
|
||||||
|
base.NullRounds++
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
beaconPrev := mbi.PrevBeaconEntry
|
beaconPrev := mbi.PrevBeaconEntry
|
||||||
|
|
||||||
@ -308,17 +316,17 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
|
|||||||
return nil, xerrors.Errorf("get beacon entries failed: %w", err)
|
return nil, xerrors.Errorf("get beacon entries failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hasPower, err := m.hasPower(ctx, addr, base.ts)
|
hasPower, err := m.hasPower(ctx, addr, base.TipSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("checking if miner is slashed: %w", err)
|
return nil, xerrors.Errorf("checking if miner is slashed: %w", err)
|
||||||
}
|
}
|
||||||
if !hasPower {
|
if !hasPower {
|
||||||
// slashed or just have no power yet
|
// slashed or just have no power yet
|
||||||
base.nullRounds++
|
base.NullRounds++
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Time delta between now and our mining base: %ds (nulls: %d)", uint64(time.Now().Unix())-base.ts.MinTimestamp(), base.nullRounds)
|
log.Infof("Time delta between now and our mining base: %ds (nulls: %d)", uint64(time.Now().Unix())-base.TipSet.MinTimestamp(), base.NullRounds)
|
||||||
|
|
||||||
rbase := beaconPrev
|
rbase := beaconPrev
|
||||||
if len(bvals) > 0 {
|
if len(bvals) > 0 {
|
||||||
@ -330,17 +338,17 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
|
|||||||
return nil, xerrors.Errorf("scratching ticket failed: %w", err)
|
return nil, xerrors.Errorf("scratching ticket failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
winner, err := gen.IsRoundWinner(ctx, base.ts, round, addr, rbase, mbi, m.api)
|
winner, err := gen.IsRoundWinner(ctx, base.TipSet, round, addr, rbase, mbi, m.api)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to check if we win next round: %w", err)
|
return nil, xerrors.Errorf("failed to check if we win next round: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if winner == nil {
|
if winner == nil {
|
||||||
base.nullRounds++
|
base.NullRounds++
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rand, err := m.api.ChainGetRandomness(ctx, base.ts.Key(), crypto.DomainSeparationTag_WinningPoStChallengeSeed, base.ts.Height()+base.nullRounds, nil)
|
rand, err := m.api.ChainGetRandomness(ctx, base.TipSet.Key(), crypto.DomainSeparationTag_WinningPoStChallengeSeed, base.TipSet.Height()+base.NullRounds, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to get randomness for winning post: %w", err)
|
return nil, xerrors.Errorf("failed to get randomness for winning post: %w", err)
|
||||||
}
|
}
|
||||||
@ -353,7 +361,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get pending messages early,
|
// get pending messages early,
|
||||||
pending, err := m.api.MpoolPending(context.TODO(), base.ts.Key())
|
pending, err := m.api.MpoolPending(context.TODO(), base.TipSet.Key())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to get pending messages: %w", err)
|
return nil, xerrors.Errorf("failed to get pending messages: %w", err)
|
||||||
}
|
}
|
||||||
@ -387,8 +395,8 @@ func (m *Miner) computeTicket(ctx context.Context, addr address.Address, brand *
|
|||||||
if err := addr.MarshalCBOR(buf); err != nil {
|
if err := addr.MarshalCBOR(buf); err != nil {
|
||||||
return nil, xerrors.Errorf("failed to marshal address to cbor: %w", err)
|
return nil, xerrors.Errorf("failed to marshal address to cbor: %w", err)
|
||||||
}
|
}
|
||||||
input, err := m.api.ChainGetRandomness(ctx, base.ts.Key(), crypto.DomainSeparationTag_TicketProduction,
|
input, err := m.api.ChainGetRandomness(ctx, base.TipSet.Key(), crypto.DomainSeparationTag_TicketProduction,
|
||||||
base.ts.Height()+base.nullRounds+1-build.TicketRandomnessLookback, buf.Bytes())
|
base.TipSet.Height()+base.NullRounds+1-build.TicketRandomnessLookback, buf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -405,7 +413,7 @@ func (m *Miner) computeTicket(ctx context.Context, addr address.Address, brand *
|
|||||||
|
|
||||||
func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket,
|
func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket,
|
||||||
eproof *types.ElectionProof, bvals []types.BeaconEntry, wpostProof []abi.PoStProof, pending []*types.SignedMessage) (*types.BlockMsg, error) {
|
eproof *types.ElectionProof, bvals []types.BeaconEntry, wpostProof []abi.PoStProof, pending []*types.SignedMessage) (*types.BlockMsg, error) {
|
||||||
msgs, err := SelectMessages(context.TODO(), m.api.StateGetActor, base.ts, pending)
|
msgs, err := SelectMessages(context.TODO(), m.api.StateGetActor, base.TipSet, pending)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("message filtering failed: %w", err)
|
return nil, xerrors.Errorf("message filtering failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -415,14 +423,14 @@ func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *type
|
|||||||
msgs = msgs[:build.BlockMessageLimit]
|
msgs = msgs[:build.BlockMessageLimit]
|
||||||
}
|
}
|
||||||
|
|
||||||
uts := base.ts.MinTimestamp() + uint64(build.BlockDelay*(base.nullRounds+1))
|
uts := base.TipSet.MinTimestamp() + uint64(build.BlockDelay*(base.NullRounds+1))
|
||||||
|
|
||||||
nheight := base.ts.Height() + base.nullRounds + 1
|
nheight := base.TipSet.Height() + base.NullRounds + 1
|
||||||
|
|
||||||
// why even return this? that api call could just submit it for us
|
// why even return this? that api call could just submit it for us
|
||||||
return m.api.MinerCreateBlock(context.TODO(), &api.BlockTemplate{
|
return m.api.MinerCreateBlock(context.TODO(), &api.BlockTemplate{
|
||||||
Miner: addr,
|
Miner: addr,
|
||||||
Parents: base.ts.Key(),
|
Parents: base.TipSet.Key(),
|
||||||
Ticket: ticket,
|
Ticket: ticket,
|
||||||
Eproof: eproof,
|
Eproof: eproof,
|
||||||
BeaconValues: bvals,
|
BeaconValues: bvals,
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
lru "github.com/hashicorp/golang-lru"
|
lru "github.com/hashicorp/golang-lru"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewTestMiner(nextCh <-chan struct{}, addr address.Address) func(api.FullNode, gen.WinningPoStProver, beacon.RandomBeacon) *Miner {
|
func NewTestMiner(nextCh <-chan func(bool), addr address.Address) func(api.FullNode, gen.WinningPoStProver, beacon.RandomBeacon) *Miner {
|
||||||
return func(api api.FullNode, epp gen.WinningPoStProver, b beacon.RandomBeacon) *Miner {
|
return func(api api.FullNode, epp gen.WinningPoStProver, b beacon.RandomBeacon) *Miner {
|
||||||
arc, err := lru.NewARC(10000)
|
arc, err := lru.NewARC(10000)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -32,14 +32,13 @@ func NewTestMiner(nextCh <-chan struct{}, addr address.Address) func(api.FullNod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func chanWaiter(next <-chan struct{}) func(ctx context.Context, _ uint64) error {
|
func chanWaiter(next <-chan func(bool)) func(ctx context.Context, _ uint64) (func(bool), error) {
|
||||||
return func(ctx context.Context, _ uint64) error {
|
return func(ctx context.Context, _ uint64) (func(bool), error) {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return nil, ctx.Err()
|
||||||
case <-next:
|
case cb := <-next:
|
||||||
|
return cb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,14 @@ func (sm *StorageMinerAPI) ActorAddress(context.Context) (address.Address, error
|
|||||||
return sm.Miner.Address(), nil
|
return sm.Miner.Address(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sm *StorageMinerAPI) MiningBase(ctx context.Context) (*types.TipSet, error) {
|
||||||
|
mb, err := sm.BlockMiner.GetBestMiningCandidate(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return mb.TipSet, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (sm *StorageMinerAPI) ActorSectorSize(ctx context.Context, addr address.Address) (abi.SectorSize, error) {
|
func (sm *StorageMinerAPI) ActorSectorSize(ctx context.Context, addr address.Address) (abi.SectorSize, error) {
|
||||||
mi, err := sm.Full.StateMinerInfo(ctx, addr, types.EmptyTSK)
|
mi, err := sm.Full.StateMinerInfo(ctx, addr, types.EmptyTSK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -79,7 +79,7 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
nic := storedcounter.New(ds, datastore.NewKey("/storage/nextid"))
|
nic := storedcounter.New(ds, datastore.NewKey("/storage/nextid"))
|
||||||
for i := 0; i < nPreseal; i++ {
|
for i := 0; i < nGenesisPreseals; i++ {
|
||||||
nic.Next()
|
nic.Next()
|
||||||
}
|
}
|
||||||
nic.Next()
|
nic.Next()
|
||||||
@ -109,7 +109,7 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a
|
|||||||
// start node
|
// start node
|
||||||
var minerapi api.StorageMiner
|
var minerapi api.StorageMiner
|
||||||
|
|
||||||
mineBlock := make(chan struct{})
|
mineBlock := make(chan func(bool))
|
||||||
// TODO: use stop
|
// TODO: use stop
|
||||||
_, err = node.New(ctx,
|
_, err = node.New(ctx,
|
||||||
node.StorageMiner(&minerapi),
|
node.StorageMiner(&minerapi),
|
||||||
@ -134,9 +134,9 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a
|
|||||||
|
|
||||||
err = minerapi.NetConnect(ctx, remoteAddrs)
|
err = minerapi.NetConnect(ctx, remoteAddrs)
|
||||||
require.NoError(t, err)*/
|
require.NoError(t, err)*/
|
||||||
mineOne := func(ctx context.Context) error {
|
mineOne := func(ctx context.Context, cb func(bool)) error {
|
||||||
select {
|
select {
|
||||||
case mineBlock <- struct{}{}:
|
case mineBlock <- cb:
|
||||||
return nil
|
return nil
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
@ -146,7 +146,7 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a
|
|||||||
return test.TestStorageNode{StorageMiner: minerapi, MineOne: mineOne}
|
return test.TestStorageNode{StorageMiner: minerapi, MineOne: mineOne}
|
||||||
}
|
}
|
||||||
|
|
||||||
func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.TestStorageNode) {
|
func builder(t *testing.T, nFull int, storage []test.StorageMiner) ([]test.TestNode, []test.TestStorageNode) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
mn := mocknet.New(ctx)
|
mn := mocknet.New(ctx)
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
genm, k, err := seed.PreSeal(maddr, abi.RegisteredProof_StackedDRG2KiBPoSt, 0, nPreseal, tdir, []byte("make genesis mem random"), nil)
|
genm, k, err := seed.PreSeal(maddr, abi.RegisteredProof_StackedDRG2KiBPoSt, 0, nGenesisPreseals, tdir, []byte("make genesis mem random"), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -238,16 +238,16 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, full := range storage {
|
for i, def := range storage {
|
||||||
// TODO: support non-bootstrap miners
|
// TODO: support non-bootstrap miners
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
t.Fatal("only one storage node supported")
|
t.Fatal("only one storage node supported")
|
||||||
}
|
}
|
||||||
if full != 0 {
|
if def.Full != 0 {
|
||||||
t.Fatal("storage nodes only supported on the first full node")
|
t.Fatal("storage nodes only supported on the first full node")
|
||||||
}
|
}
|
||||||
|
|
||||||
f := fulls[full]
|
f := fulls[def.Full]
|
||||||
if _, err := f.FullNode.WalletImport(ctx, &keys[i].KeyInfo); err != nil {
|
if _, err := f.FullNode.WalletImport(ctx, &keys[i].KeyInfo); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -276,26 +276,17 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te
|
|||||||
return fulls, storers
|
return fulls, storers
|
||||||
}
|
}
|
||||||
|
|
||||||
const nPreseal = 2
|
const nGenesisPreseals = 2
|
||||||
|
|
||||||
func mockSbBuilder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.TestStorageNode) {
|
func mockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner) ([]test.TestNode, []test.TestStorageNode) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
mn := mocknet.New(ctx)
|
mn := mocknet.New(ctx)
|
||||||
|
|
||||||
fulls := make([]test.TestNode, nFull)
|
fulls := make([]test.TestNode, nFull)
|
||||||
storers := make([]test.TestStorageNode, len(storage))
|
storers := make([]test.TestStorageNode, len(storage))
|
||||||
|
|
||||||
pk, _, err := crypto.GenerateEd25519Key(rand.Reader)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
minerPid, err := peer.IDFromPrivateKey(pk)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
var genbuf bytes.Buffer
|
var genbuf bytes.Buffer
|
||||||
|
|
||||||
if len(storage) > 1 {
|
|
||||||
panic("need more peer IDs")
|
|
||||||
}
|
|
||||||
// PRESEAL SECTION, TRY TO REPLACE WITH BETTER IN THE FUTURE
|
// PRESEAL SECTION, TRY TO REPLACE WITH BETTER IN THE FUTURE
|
||||||
// TODO: would be great if there was a better way to fake the preseals
|
// TODO: would be great if there was a better way to fake the preseals
|
||||||
|
|
||||||
@ -304,6 +295,7 @@ func mockSbBuilder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []t
|
|||||||
var maddrs []address.Address
|
var maddrs []address.Address
|
||||||
var presealDirs []string
|
var presealDirs []string
|
||||||
var keys []*wallet.Key
|
var keys []*wallet.Key
|
||||||
|
var pidKeys []crypto.PrivKey
|
||||||
for i := 0; i < len(storage); i++ {
|
for i := 0; i < len(storage); i++ {
|
||||||
maddr, err := address.NewIDAddress(genesis2.MinerStart + uint64(i))
|
maddr, err := address.NewIDAddress(genesis2.MinerStart + uint64(i))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -313,10 +305,23 @@ func mockSbBuilder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []t
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
genm, k, err := mockstorage.PreSeal(2048, maddr, nPreseal)
|
|
||||||
|
preseals := storage[i].Preseal
|
||||||
|
if preseals == test.PresealGenesis {
|
||||||
|
preseals = nGenesisPreseals
|
||||||
|
}
|
||||||
|
|
||||||
|
genm, k, err := mockstorage.PreSeal(2048, maddr, preseals)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pk, _, err := crypto.GenerateEd25519Key(rand.Reader)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
minerPid, err := peer.IDFromPrivateKey(pk)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
genm.PeerId = minerPid
|
genm.PeerId = minerPid
|
||||||
|
|
||||||
wk, err := wallet.NewKey(*k)
|
wk, err := wallet.NewKey(*k)
|
||||||
@ -331,6 +336,7 @@ func mockSbBuilder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []t
|
|||||||
})
|
})
|
||||||
|
|
||||||
keys = append(keys, wk)
|
keys = append(keys, wk)
|
||||||
|
pidKeys = append(pidKeys, pk)
|
||||||
presealDirs = append(presealDirs, tdir)
|
presealDirs = append(presealDirs, tdir)
|
||||||
maddrs = append(maddrs, maddr)
|
maddrs = append(maddrs, maddr)
|
||||||
genms = append(genms, *genm)
|
genms = append(genms, *genm)
|
||||||
@ -369,16 +375,13 @@ func mockSbBuilder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, full := range storage {
|
for i, def := range storage {
|
||||||
// TODO: support non-bootstrap miners
|
// TODO: support non-bootstrap miners
|
||||||
if i != 0 {
|
if def.Full != 0 {
|
||||||
t.Fatal("only one storage node supported")
|
|
||||||
}
|
|
||||||
if full != 0 {
|
|
||||||
t.Fatal("storage nodes only supported on the first full node")
|
t.Fatal("storage nodes only supported on the first full node")
|
||||||
}
|
}
|
||||||
|
|
||||||
f := fulls[full]
|
f := fulls[def.Full]
|
||||||
if _, err := f.FullNode.WalletImport(ctx, &keys[i].KeyInfo); err != nil {
|
if _, err := f.FullNode.WalletImport(ctx, &keys[i].KeyInfo); err != nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -386,10 +389,7 @@ func mockSbBuilder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []t
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
genMiner := maddrs[i]
|
storers[i] = testStorageNode(ctx, t, genms[i].Worker, maddrs[i], pidKeys[i], f, mn, node.Options(
|
||||||
wa := genms[i].Worker
|
|
||||||
|
|
||||||
storers[i] = testStorageNode(ctx, t, wa, genMiner, pk, f, mn, node.Options(
|
|
||||||
node.Override(new(sectorstorage.SectorManager), func() (sectorstorage.SectorManager, error) {
|
node.Override(new(sectorstorage.SectorManager), func() (sectorstorage.SectorManager, error) {
|
||||||
return mock.NewMockSectorMgr(5, build.SectorSizes[0]), nil
|
return mock.NewMockSectorMgr(5, build.SectorSizes[0]), nil
|
||||||
}),
|
}),
|
||||||
@ -409,7 +409,7 @@ func TestAPI(t *testing.T) {
|
|||||||
test.TestApis(t, builder)
|
test.TestApis(t, builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
func rpcBuilder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.TestStorageNode) {
|
func rpcBuilder(t *testing.T, nFull int, storage []test.StorageMiner) ([]test.TestNode, []test.TestStorageNode) {
|
||||||
fullApis, storaApis := builder(t, nFull, storage)
|
fullApis, storaApis := builder(t, nFull, storage)
|
||||||
fulls := make([]test.TestNode, nFull)
|
fulls := make([]test.TestNode, nFull)
|
||||||
storers := make([]test.TestStorageNode, len(storage))
|
storers := make([]test.TestStorageNode, len(storage))
|
||||||
@ -477,3 +477,13 @@ func TestAPIDealFlowReal(t *testing.T) {
|
|||||||
|
|
||||||
test.TestDealFlow(t, builder, time.Second, false)
|
test.TestDealFlow(t, builder, time.Second, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDealMining(t *testing.T) {
|
||||||
|
logging.SetLogLevel("miner", "ERROR")
|
||||||
|
logging.SetLogLevel("chainstore", "ERROR")
|
||||||
|
logging.SetLogLevel("chain", "ERROR")
|
||||||
|
logging.SetLogLevel("sub", "ERROR")
|
||||||
|
logging.SetLogLevel("storageminer", "ERROR")
|
||||||
|
|
||||||
|
test.TestDealMining(t, mockSbBuilder, 50*time.Millisecond, false)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user