lotus/lotus-soup/baseline.go

197 lines
5.6 KiB
Go
Raw Normal View History

package main
import (
2020-06-24 13:10:01 +00:00
"bytes"
"context"
"fmt"
2020-06-24 13:10:01 +00:00
"math/rand"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/impl"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer"
)
// This is the basline test; Filecoin 101.
//
// A network with a bootstrapper, a number of miners, and a number of clients/full nodes
// is constructed and connected through the bootstrapper.
// Some funds are allocated to each node and a number of sectors are presealed in the genesis block.
//
// The test plan:
// One or more clients store content to one or more miners, testing storage deals.
// The plan ensures that the storage deals hit the blockchain and measure the time it took.
// Verification: one or more clients retrieve and verify the hashes of stored content.
// The plan ensures that all (previously) published content can be correctly retrieved
// and measures the time it took.
//
// Preparation of the genesis block: this is the responsibility of the bootstrapper.
// In order to compute the genesis block, we need to collect identities and presealed
// sectors from each node.
// The we create a genesis block that allocates some funds to each node and collects
// the presealed sectors.
var baselineRoles = map[string]func(*TestEnvironment) error{
"bootstrapper": runBaselineBootstrapper,
"miner": runBaselineMiner,
"client": runBaselineClient,
}
func runBaselineBootstrapper(t *TestEnvironment) error {
t.RecordMessage("running bootstrapper")
_, err := prepareBootstrapper(t)
if err != nil {
return err
}
2020-06-24 12:29:04 +00:00
ctx := context.Background()
t.SyncClient.MustSignalAndWait(ctx, stateDone, t.TestInstanceCount)
return nil
}
func runBaselineMiner(t *TestEnvironment) error {
t.RecordMessage("running miner")
2020-06-24 12:40:29 +00:00
_, err := prepareMiner(t)
if err != nil {
return err
}
ctx := context.Background()
addrs, err := collectClientsAddrs(t, ctx, t.IntParam("clients"))
if err != nil {
return err
}
t.RecordMessage("got %v client addrs", len(addrs))
2020-06-24 13:10:01 +00:00
// mine / stop mining
//mine := true
//done := make(chan struct{})
//go func() {
//defer close(done)
//for mine {
//time.Sleep(blocktime)
//if err := sn[0].MineOne(ctx, func(bool) {}); err != nil {
//t.Error(err)
//}
//}
//}()
//makeDeal(t, ctx, 6, client, miner, carExport)
//mine = false
//fmt.Println("shutting down mining")
//<-done
// TODO wait a bit for network to bootstrap
// TODO just wait until completion of test, serving requests -- the client does all the job
2020-06-24 12:29:04 +00:00
t.SyncClient.MustSignalAndWait(ctx, stateDone, t.TestInstanceCount)
return nil
}
func runBaselineClient(t *TestEnvironment) error {
t.RecordMessage("running client")
2020-06-24 13:10:01 +00:00
cl, err := prepareClient(t)
if err != nil {
return err
}
ctx := context.Background()
addrs, err := collectMinersAddrs(t, ctx, t.IntParam("miners"))
if err != nil {
return err
}
2020-06-24 13:10:01 +00:00
client := cl.fullApi.(*impl.FullNodeAPI)
t.RecordMessage("got %v miner addrs", len(addrs))
2020-06-24 13:10:01 +00:00
if err := client.NetConnect(ctx, addrs[0].PeerAddr); err != nil {
2020-06-24 12:40:29 +00:00
return err
}
t.RecordMessage("client connected to miner")
2020-06-24 13:10:01 +00:00
// generate a number of random "files" and publish them to one or more miners
data := make([]byte, 1600)
rand.New(rand.NewSource(time.Now().UnixNano())).Read(data)
r := bytes.NewReader(data)
fcid, err := client.ClientImportLocal(ctx, r)
if err != nil {
return err
}
t.RecordMessage("file cid: %s", fcid)
// start deal
deal := startDeal(ctx, addrs[0].ActorAddr, client, fcid)
spew.Dump(deal)
// 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)
//testRetrieval(t, ctx, err, client, fcid, carExport, data)
// TODO broadcast published content CIDs to other clients
2020-06-24 13:10:01 +00:00
// TODO select a random piece of content published by some other client and retrieve it
2020-06-24 12:29:04 +00:00
t.SyncClient.MustSignalAndWait(ctx, stateDone, t.TestInstanceCount)
return nil
}
2020-06-24 13:10:01 +00:00
func collectMinersAddrs(t *TestEnvironment, ctx context.Context, miners int) ([]MinerAddresses, error) {
ch := make(chan MinerAddresses)
sub := t.SyncClient.MustSubscribe(ctx, minersAddrsTopic, ch)
2020-06-24 13:10:01 +00:00
addrs := make([]MinerAddresses, 0, miners)
for i := 0; i < miners; i++ {
select {
case a := <-ch:
addrs = append(addrs, a)
case err := <-sub.Done():
return nil, fmt.Errorf("got error while waiting for miners addrs: %w", err)
}
}
return addrs, nil
}
2020-06-24 13:10:01 +00:00
func collectClientsAddrs(t *TestEnvironment, ctx context.Context, clients int) ([]peer.AddrInfo, error) {
ch := make(chan peer.AddrInfo)
2020-06-24 13:10:01 +00:00
sub := t.SyncClient.MustSubscribe(ctx, clientsAddrsTopic, ch)
2020-06-24 13:10:01 +00:00
addrs := make([]peer.AddrInfo, 0, clients)
for i := 0; i < clients; i++ {
select {
case a := <-ch:
addrs = append(addrs, a)
case err := <-sub.Done():
2020-06-24 13:10:01 +00:00
return nil, fmt.Errorf("got error while waiting for clients addrs: %w", err)
}
}
return addrs, nil
}
2020-06-24 13:10:01 +00:00
func startDeal(ctx context.Context, minerActorAddr address.Address, client *impl.FullNodeAPI, fcid cid.Cid) *cid.Cid {
//func startDeal(ctx context.Context, minerActorAddr address.Address, client api.FullNodeAPI, fcid cid.Cid) *cid.Cid {
addr, _ := client.WalletDefaultAddress(ctx)
deal, err := client.ClientStartDeal(ctx, &api.StartDealParams{
Data: &storagemarket.DataRef{Root: fcid},
Wallet: addr,
Miner: minerActorAddr,
EpochPrice: types.NewInt(1000000),
MinBlocksDuration: 100,
})
if err != nil {
panic(err)
}
return deal
}