2021-05-18 21:01:10 +00:00
|
|
|
package kit
|
2020-08-13 20:37:09 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"crypto/rand"
|
|
|
|
"io/ioutil"
|
|
|
|
"net"
|
|
|
|
"net/http/httptest"
|
2020-10-07 09:26:15 +00:00
|
|
|
"strings"
|
2020-08-13 20:37:09 +00:00
|
|
|
"sync"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2021-05-21 18:46:58 +00:00
|
|
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
2021-04-05 19:34:03 +00:00
|
|
|
"github.com/gorilla/mux"
|
2020-10-07 09:26:15 +00:00
|
|
|
"golang.org/x/xerrors"
|
|
|
|
|
2020-08-13 20:37:09 +00:00
|
|
|
"github.com/filecoin-project/go-address"
|
|
|
|
"github.com/filecoin-project/go-jsonrpc"
|
2020-09-07 03:49:10 +00:00
|
|
|
"github.com/filecoin-project/go-state-types/abi"
|
|
|
|
"github.com/filecoin-project/go-state-types/big"
|
2021-04-23 12:29:46 +00:00
|
|
|
"github.com/filecoin-project/go-state-types/exitcode"
|
2020-08-13 20:37:09 +00:00
|
|
|
"github.com/filecoin-project/go-storedcounter"
|
|
|
|
"github.com/filecoin-project/lotus/api"
|
|
|
|
"github.com/filecoin-project/lotus/api/client"
|
2021-04-05 19:34:03 +00:00
|
|
|
"github.com/filecoin-project/lotus/api/v0api"
|
2021-04-05 17:56:53 +00:00
|
|
|
"github.com/filecoin-project/lotus/api/v1api"
|
2020-08-13 20:37:09 +00:00
|
|
|
"github.com/filecoin-project/lotus/build"
|
2020-10-29 17:32:09 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain"
|
2020-08-13 20:37:09 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/actors"
|
2020-10-08 20:32:54 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
2021-04-23 12:29:46 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
|
2020-08-13 20:37:09 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/gen"
|
|
|
|
genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis"
|
2020-11-04 15:53:16 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/messagepool"
|
2020-08-13 20:37:09 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
|
|
"github.com/filecoin-project/lotus/chain/wallet"
|
|
|
|
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
|
|
|
|
sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage"
|
|
|
|
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
|
|
|
|
"github.com/filecoin-project/lotus/extern/sector-storage/mock"
|
|
|
|
"github.com/filecoin-project/lotus/genesis"
|
2020-10-08 01:09:33 +00:00
|
|
|
lotusminer "github.com/filecoin-project/lotus/miner"
|
2020-08-13 20:37:09 +00:00
|
|
|
"github.com/filecoin-project/lotus/node"
|
|
|
|
"github.com/filecoin-project/lotus/node/modules"
|
|
|
|
testing2 "github.com/filecoin-project/lotus/node/modules/testing"
|
|
|
|
"github.com/filecoin-project/lotus/node/repo"
|
|
|
|
"github.com/filecoin-project/lotus/storage/mockstorage"
|
2020-10-08 01:09:33 +00:00
|
|
|
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
|
2021-04-23 12:29:46 +00:00
|
|
|
power2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/power"
|
2020-08-13 20:37:09 +00:00
|
|
|
"github.com/ipfs/go-datastore"
|
|
|
|
"github.com/libp2p/go-libp2p-core/crypto"
|
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
|
|
|
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
|
|
|
|
"github.com/multiformats/go-multiaddr"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
2020-10-29 17:32:09 +00:00
|
|
|
func init() {
|
|
|
|
chain.BootstrapPeerThreshold = 1
|
2020-11-09 11:35:42 +00:00
|
|
|
messagepool.HeadChangeCoalesceMinDelay = time.Microsecond
|
|
|
|
messagepool.HeadChangeCoalesceMaxDelay = 2 * time.Microsecond
|
|
|
|
messagepool.HeadChangeCoalesceMergeInterval = 100 * time.Nanosecond
|
2020-10-29 17:32:09 +00:00
|
|
|
}
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
func CreateTestStorageNode(ctx context.Context, t *testing.T, waddr address.Address, act address.Address, pk crypto.PrivKey, tnd TestFullNode, mn mocknet.Mocknet, opts node.Option) TestMiner {
|
2020-08-13 20:37:09 +00:00
|
|
|
r := repo.NewMemory(nil)
|
|
|
|
|
|
|
|
lr, err := r.Lock(repo.StorageMiner)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
ks, err := lr.KeyStore()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
kbytes, err := pk.Bytes()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = ks.Put("libp2p-host", types.KeyInfo{
|
|
|
|
Type: "libp2p-host",
|
|
|
|
PrivateKey: kbytes,
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2021-01-26 10:25:34 +00:00
|
|
|
ds, err := lr.Datastore(context.TODO(), "/metadata")
|
2020-08-13 20:37:09 +00:00
|
|
|
require.NoError(t, err)
|
2021-05-19 16:13:30 +00:00
|
|
|
err = ds.Put(datastore.NewKey("miner-address"), act.Bytes())
|
2020-08-13 20:37:09 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
nic := storedcounter.New(ds, datastore.NewKey(modules.StorageCounterDSPrefix))
|
2021-05-17 12:28:09 +00:00
|
|
|
for i := 0; i < GenesisPreseals; i++ {
|
2020-08-13 20:37:09 +00:00
|
|
|
_, err := nic.Next()
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
_, err = nic.Next()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = lr.Close()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
peerid, err := peer.IDFromPrivateKey(pk)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-10-08 01:09:33 +00:00
|
|
|
enc, err := actors.SerializeParams(&miner2.ChangePeerIDParams{NewID: abi.PeerID(peerid)})
|
2020-08-13 20:37:09 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
msg := &types.Message{
|
|
|
|
To: act,
|
|
|
|
From: waddr,
|
2020-10-08 20:32:54 +00:00
|
|
|
Method: miner.Methods.ChangePeerID,
|
2020-08-13 20:37:09 +00:00
|
|
|
Params: enc,
|
|
|
|
Value: types.NewInt(0),
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = tnd.MpoolPushMessage(ctx, msg, nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// start node
|
|
|
|
var minerapi api.StorageMiner
|
|
|
|
|
2020-10-08 01:09:33 +00:00
|
|
|
mineBlock := make(chan lotusminer.MineReq)
|
2020-10-08 22:59:06 +00:00
|
|
|
stop, err := node.New(ctx,
|
2020-08-13 20:37:09 +00:00
|
|
|
node.StorageMiner(&minerapi),
|
|
|
|
node.Online(),
|
|
|
|
node.Repo(r),
|
|
|
|
node.Test(),
|
|
|
|
|
|
|
|
node.MockHost(mn),
|
|
|
|
|
2021-04-05 17:56:53 +00:00
|
|
|
node.Override(new(v1api.FullNode), tnd),
|
2020-10-08 01:09:33 +00:00
|
|
|
node.Override(new(*lotusminer.Miner), lotusminer.NewTestMiner(mineBlock, act)),
|
2020-08-13 20:37:09 +00:00
|
|
|
|
|
|
|
opts,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("failed to construct node: %v", err)
|
|
|
|
}
|
2020-10-07 09:26:15 +00:00
|
|
|
|
2020-10-08 22:59:06 +00:00
|
|
|
t.Cleanup(func() { _ = stop(context.Background()) })
|
2020-08-13 20:37:09 +00:00
|
|
|
|
|
|
|
/*// Bootstrap with full node
|
2021-05-18 21:01:10 +00:00
|
|
|
remoteAddrs, err := tnd.NetAddrsListen(Ctx)
|
2020-08-13 20:37:09 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2021-05-18 21:01:10 +00:00
|
|
|
err = minerapi.NetConnect(Ctx, remoteAddrs)
|
2020-08-13 20:37:09 +00:00
|
|
|
require.NoError(t, err)*/
|
2020-10-08 01:09:33 +00:00
|
|
|
mineOne := func(ctx context.Context, req lotusminer.MineReq) error {
|
2020-08-13 20:37:09 +00:00
|
|
|
select {
|
|
|
|
case mineBlock <- req:
|
|
|
|
return nil
|
|
|
|
case <-ctx.Done():
|
|
|
|
return ctx.Err()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
return TestMiner{StorageMiner: minerapi, MineOne: mineOne, Stop: stop}
|
2020-08-13 20:37:09 +00:00
|
|
|
}
|
|
|
|
|
2021-05-21 19:39:41 +00:00
|
|
|
func storageBuilder(parentNode TestFullNode, mn mocknet.Mocknet, opts node.Option) MinerBuilder {
|
2021-05-19 10:47:37 +00:00
|
|
|
return func(ctx context.Context, t *testing.T, spt abi.RegisteredSealProof, owner address.Address) TestMiner {
|
2021-04-23 12:29:46 +00:00
|
|
|
pk, _, err := crypto.GenerateEd25519Key(rand.Reader)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
minerPid, err := peer.IDFromPrivateKey(pk)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
params, serr := actors.SerializeParams(&power2.CreateMinerParams{
|
|
|
|
Owner: owner,
|
|
|
|
Worker: owner,
|
|
|
|
SealProofType: spt,
|
|
|
|
Peer: abi.PeerID(minerPid),
|
|
|
|
})
|
|
|
|
require.NoError(t, serr)
|
|
|
|
|
|
|
|
createStorageMinerMsg := &types.Message{
|
|
|
|
To: power.Address,
|
|
|
|
From: owner,
|
|
|
|
Value: big.Zero(),
|
|
|
|
|
|
|
|
Method: power.Methods.CreateMiner,
|
|
|
|
Params: params,
|
|
|
|
|
|
|
|
GasLimit: 0,
|
|
|
|
GasPremium: big.NewInt(5252),
|
|
|
|
}
|
|
|
|
|
|
|
|
signed, err := parentNode.MpoolPushMessage(ctx, createStorageMinerMsg, nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2021-04-27 06:13:49 +00:00
|
|
|
mw, err := parentNode.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence, api.LookbackNoLimit, true)
|
2021-04-23 12:29:46 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, exitcode.Ok, mw.Receipt.ExitCode)
|
|
|
|
|
|
|
|
var retval power2.CreateMinerReturn
|
|
|
|
err = retval.UnmarshalCBOR(bytes.NewReader(mw.Receipt.Return))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
return CreateTestStorageNode(ctx, t, owner, retval.IDAddress, pk, parentNode, mn, opts)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
func Builder(t *testing.T, fullOpts []FullNodeOpts, storage []StorageMiner) ([]TestFullNode, []TestMiner) {
|
2020-10-08 10:21:15 +00:00
|
|
|
return mockBuilderOpts(t, fullOpts, storage, false)
|
2020-10-07 09:26:15 +00:00
|
|
|
}
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
func RPCBuilder(t *testing.T, fullOpts []FullNodeOpts, storage []StorageMiner) ([]TestFullNode, []TestMiner) {
|
2020-10-08 10:21:15 +00:00
|
|
|
return mockBuilderOpts(t, fullOpts, storage, true)
|
2020-10-07 09:26:15 +00:00
|
|
|
}
|
|
|
|
|
2021-05-20 11:17:41 +00:00
|
|
|
func MockMinerBuilder(t *testing.T, fullOpts []FullNodeOpts, storage []StorageMiner) ([]TestFullNode, []TestMiner) {
|
|
|
|
return mockMinerBuilderOpts(t, fullOpts, storage, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
func RPCMockMinerBuilder(t *testing.T, fullOpts []FullNodeOpts, storage []StorageMiner) ([]TestFullNode, []TestMiner) {
|
|
|
|
return mockMinerBuilderOpts(t, fullOpts, storage, true)
|
2020-10-07 09:26:15 +00:00
|
|
|
}
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
func mockBuilderOpts(t *testing.T, fullOpts []FullNodeOpts, storage []StorageMiner, rpc bool) ([]TestFullNode, []TestMiner) {
|
2020-10-08 22:59:06 +00:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
2020-08-13 20:37:09 +00:00
|
|
|
mn := mocknet.New(ctx)
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
fulls := make([]TestFullNode, len(fullOpts))
|
|
|
|
miners := make([]TestMiner, len(storage))
|
2020-08-13 20:37:09 +00:00
|
|
|
|
2021-05-20 15:12:42 +00:00
|
|
|
// *****
|
2020-08-13 20:37:09 +00:00
|
|
|
pk, _, err := crypto.GenerateEd25519Key(rand.Reader)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
minerPid, err := peer.IDFromPrivateKey(pk)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
var genbuf bytes.Buffer
|
|
|
|
|
|
|
|
if len(storage) > 1 {
|
|
|
|
panic("need more peer IDs")
|
|
|
|
}
|
2021-05-20 15:12:42 +00:00
|
|
|
// *****
|
|
|
|
|
2020-08-13 20:37:09 +00:00
|
|
|
// PRESEAL SECTION, TRY TO REPLACE WITH BETTER IN THE FUTURE
|
|
|
|
// TODO: would be great if there was a better way to fake the preseals
|
|
|
|
|
2021-05-20 15:12:42 +00:00
|
|
|
var (
|
|
|
|
genms []genesis.Miner
|
|
|
|
maddrs []address.Address
|
|
|
|
genaccs []genesis.Actor
|
|
|
|
keys []*wallet.Key
|
|
|
|
)
|
2020-08-13 20:37:09 +00:00
|
|
|
|
|
|
|
var presealDirs []string
|
|
|
|
for i := 0; i < len(storage); i++ {
|
|
|
|
maddr, err := address.NewIDAddress(genesis2.MinerStart + uint64(i))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
tdir, err := ioutil.TempDir("", "preseal-memgen")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2021-05-17 12:28:09 +00:00
|
|
|
genm, k, err := seed.PreSeal(maddr, abi.RegisteredSealProof_StackedDrg2KiBV1, 0, GenesisPreseals, tdir, []byte("make genesis mem random"), nil, true)
|
2020-08-13 20:37:09 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
genm.PeerId = minerPid
|
|
|
|
|
|
|
|
wk, err := wallet.NewKey(*k)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genaccs = append(genaccs, genesis.Actor{
|
|
|
|
Type: genesis.TAccount,
|
|
|
|
Balance: big.Mul(big.NewInt(400000000), types.NewInt(build.FilecoinPrecision)),
|
|
|
|
Meta: (&genesis.AccountMeta{Owner: wk.Address}).ActorMeta(),
|
|
|
|
})
|
|
|
|
|
|
|
|
keys = append(keys, wk)
|
|
|
|
presealDirs = append(presealDirs, tdir)
|
|
|
|
maddrs = append(maddrs, maddr)
|
|
|
|
genms = append(genms, *genm)
|
|
|
|
}
|
|
|
|
templ := &genesis.Template{
|
2020-08-19 21:54:40 +00:00
|
|
|
Accounts: genaccs,
|
|
|
|
Miners: genms,
|
2020-09-30 21:55:50 +00:00
|
|
|
NetworkName: "test",
|
2020-08-19 21:54:40 +00:00
|
|
|
Timestamp: uint64(time.Now().Unix() - 10000), // some time sufficiently far in the past
|
|
|
|
VerifregRootKey: gen.DefaultVerifregRootkeyActor,
|
|
|
|
RemainderAccount: gen.DefaultRemainderAccountActor,
|
2020-08-13 20:37:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// END PRESEAL SECTION
|
|
|
|
|
2020-10-07 09:26:15 +00:00
|
|
|
for i := 0; i < len(fullOpts); i++ {
|
2020-08-13 20:37:09 +00:00
|
|
|
var genesis node.Option
|
|
|
|
if i == 0 {
|
|
|
|
genesis = node.Override(new(modules.Genesis), testing2.MakeGenesisMem(&genbuf, *templ))
|
|
|
|
} else {
|
|
|
|
genesis = node.Override(new(modules.Genesis), modules.LoadGenesis(genbuf.Bytes()))
|
|
|
|
}
|
|
|
|
|
2020-10-08 22:59:06 +00:00
|
|
|
stop, err := node.New(ctx,
|
2020-10-09 16:43:22 +00:00
|
|
|
node.FullAPI(&fulls[i].FullNode, node.Lite(fullOpts[i].Lite)),
|
2020-08-13 20:37:09 +00:00
|
|
|
node.Online(),
|
|
|
|
node.Repo(repo.NewMemory(nil)),
|
|
|
|
node.MockHost(mn),
|
|
|
|
node.Test(),
|
|
|
|
|
|
|
|
genesis,
|
2020-10-08 09:24:31 +00:00
|
|
|
|
|
|
|
fullOpts[i].Opts(fulls),
|
2020-08-13 20:37:09 +00:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2020-10-07 09:26:15 +00:00
|
|
|
|
2020-10-08 22:59:06 +00:00
|
|
|
t.Cleanup(func() { _ = stop(context.Background()) })
|
2020-10-07 09:26:15 +00:00
|
|
|
|
|
|
|
if rpc {
|
|
|
|
fulls[i] = fullRpc(t, fulls[i])
|
|
|
|
}
|
2021-04-23 12:29:46 +00:00
|
|
|
|
|
|
|
fulls[i].Stb = storageBuilder(fulls[i], mn, node.Options())
|
2020-08-13 20:37:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for i, def := range storage {
|
|
|
|
// TODO: support non-bootstrap miners
|
|
|
|
if i != 0 {
|
|
|
|
t.Fatal("only one storage node supported")
|
|
|
|
}
|
|
|
|
if def.Full != 0 {
|
|
|
|
t.Fatal("storage nodes only supported on the first full node")
|
|
|
|
}
|
|
|
|
|
|
|
|
f := fulls[def.Full]
|
|
|
|
if _, err := f.FullNode.WalletImport(ctx, &keys[i].KeyInfo); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := f.FullNode.WalletSetDefault(ctx, keys[i].Address); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
genMiner := maddrs[i]
|
|
|
|
wa := genms[i].Worker
|
|
|
|
|
2021-01-08 15:28:38 +00:00
|
|
|
opts := def.Opts
|
|
|
|
if opts == nil {
|
|
|
|
opts = node.Options()
|
|
|
|
}
|
2021-05-19 10:47:37 +00:00
|
|
|
miners[i] = CreateTestStorageNode(ctx, t, wa, genMiner, pk, f, mn, opts)
|
|
|
|
if err := miners[i].StorageAddLocal(ctx, presealDirs[i]); err != nil {
|
2020-08-13 20:37:09 +00:00
|
|
|
t.Fatalf("%+v", err)
|
|
|
|
}
|
|
|
|
/*
|
2021-05-19 10:47:37 +00:00
|
|
|
sma := miners[i].StorageMiner.(*impl.StorageMinerAPI)
|
2020-08-13 20:37:09 +00:00
|
|
|
|
|
|
|
psd := presealDirs[i]
|
|
|
|
*/
|
2020-10-07 09:26:15 +00:00
|
|
|
if rpc {
|
2021-05-19 10:47:37 +00:00
|
|
|
miners[i] = storerRpc(t, miners[i])
|
2020-10-07 09:26:15 +00:00
|
|
|
}
|
2020-08-13 20:37:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := mn.LinkAll(); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
if len(miners) > 0 {
|
2020-08-13 20:37:09 +00:00
|
|
|
// Mine 2 blocks to setup some CE stuff in some actors
|
|
|
|
var wait sync.Mutex
|
|
|
|
wait.Lock()
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
bm := NewBlockMiner(t, miners[0])
|
2021-05-21 12:39:09 +00:00
|
|
|
t.Cleanup(bm.Stop)
|
2021-05-19 10:47:37 +00:00
|
|
|
|
|
|
|
bm.MineUntilBlock(ctx, fulls[0], func(epoch abi.ChainEpoch) {
|
2020-08-13 20:37:09 +00:00
|
|
|
wait.Unlock()
|
2020-08-25 22:07:10 +00:00
|
|
|
})
|
2020-08-27 00:51:16 +00:00
|
|
|
|
2020-08-13 20:37:09 +00:00
|
|
|
wait.Lock()
|
2021-05-19 10:47:37 +00:00
|
|
|
bm.MineUntilBlock(ctx, fulls[0], func(epoch abi.ChainEpoch) {
|
2020-08-13 20:37:09 +00:00
|
|
|
wait.Unlock()
|
2020-08-25 22:07:10 +00:00
|
|
|
})
|
2020-08-13 20:37:09 +00:00
|
|
|
wait.Lock()
|
|
|
|
}
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
return fulls, miners
|
2020-08-13 20:37:09 +00:00
|
|
|
}
|
|
|
|
|
2021-05-20 11:17:41 +00:00
|
|
|
func mockMinerBuilderOpts(t *testing.T, fullOpts []FullNodeOpts, storage []StorageMiner, rpc bool) ([]TestFullNode, []TestMiner) {
|
2020-10-07 09:26:15 +00:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
2020-08-13 20:37:09 +00:00
|
|
|
mn := mocknet.New(ctx)
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
fulls := make([]TestFullNode, len(fullOpts))
|
|
|
|
miners := make([]TestMiner, len(storage))
|
2020-08-13 20:37:09 +00:00
|
|
|
|
|
|
|
var genbuf bytes.Buffer
|
|
|
|
|
|
|
|
// PRESEAL SECTION, TRY TO REPLACE WITH BETTER IN THE FUTURE
|
|
|
|
// TODO: would be great if there was a better way to fake the preseals
|
|
|
|
|
2021-05-20 15:12:42 +00:00
|
|
|
var (
|
|
|
|
genms []genesis.Miner
|
|
|
|
genaccs []genesis.Actor
|
|
|
|
maddrs []address.Address
|
|
|
|
keys []*wallet.Key
|
|
|
|
pidKeys []crypto.PrivKey
|
|
|
|
)
|
2020-08-13 20:37:09 +00:00
|
|
|
for i := 0; i < len(storage); i++ {
|
|
|
|
maddr, err := address.NewIDAddress(genesis2.MinerStart + uint64(i))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
preseals := storage[i].Preseal
|
2021-05-17 12:28:09 +00:00
|
|
|
if preseals == PresealGenesis {
|
|
|
|
preseals = GenesisPreseals
|
2020-08-13 20:37:09 +00:00
|
|
|
}
|
|
|
|
|
2020-11-05 12:43:05 +00:00
|
|
|
genm, k, err := mockstorage.PreSeal(abi.RegisteredSealProof_StackedDrg2KiBV1, maddr, preseals)
|
2020-08-13 20:37:09 +00:00
|
|
|
if err != nil {
|
|
|
|
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
|
|
|
|
|
|
|
|
wk, err := wallet.NewKey(*k)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genaccs = append(genaccs, genesis.Actor{
|
|
|
|
Type: genesis.TAccount,
|
2020-08-19 21:54:40 +00:00
|
|
|
Balance: big.Mul(big.NewInt(400000000), types.NewInt(build.FilecoinPrecision)),
|
2020-08-13 20:37:09 +00:00
|
|
|
Meta: (&genesis.AccountMeta{Owner: wk.Address}).ActorMeta(),
|
|
|
|
})
|
|
|
|
|
|
|
|
keys = append(keys, wk)
|
|
|
|
pidKeys = append(pidKeys, pk)
|
|
|
|
maddrs = append(maddrs, maddr)
|
|
|
|
genms = append(genms, *genm)
|
|
|
|
}
|
|
|
|
templ := &genesis.Template{
|
2020-08-19 21:54:40 +00:00
|
|
|
Accounts: genaccs,
|
|
|
|
Miners: genms,
|
2020-09-30 21:55:50 +00:00
|
|
|
NetworkName: "test",
|
2020-08-19 21:54:40 +00:00
|
|
|
Timestamp: uint64(time.Now().Unix()) - (build.BlockDelaySecs * 20000),
|
|
|
|
VerifregRootKey: gen.DefaultVerifregRootkeyActor,
|
|
|
|
RemainderAccount: gen.DefaultRemainderAccountActor,
|
2020-08-13 20:37:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// END PRESEAL SECTION
|
|
|
|
|
2020-10-07 09:26:15 +00:00
|
|
|
for i := 0; i < len(fullOpts); i++ {
|
2020-08-13 20:37:09 +00:00
|
|
|
var genesis node.Option
|
|
|
|
if i == 0 {
|
|
|
|
genesis = node.Override(new(modules.Genesis), testing2.MakeGenesisMem(&genbuf, *templ))
|
|
|
|
} else {
|
|
|
|
genesis = node.Override(new(modules.Genesis), modules.LoadGenesis(genbuf.Bytes()))
|
|
|
|
}
|
|
|
|
|
2020-10-08 22:59:06 +00:00
|
|
|
stop, err := node.New(ctx,
|
2020-10-09 16:43:22 +00:00
|
|
|
node.FullAPI(&fulls[i].FullNode, node.Lite(fullOpts[i].Lite)),
|
2020-08-13 20:37:09 +00:00
|
|
|
node.Online(),
|
|
|
|
node.Repo(repo.NewMemory(nil)),
|
|
|
|
node.MockHost(mn),
|
|
|
|
node.Test(),
|
|
|
|
|
|
|
|
node.Override(new(ffiwrapper.Verifier), mock.MockVerifier),
|
|
|
|
|
2021-05-21 18:46:58 +00:00
|
|
|
// so that we subscribe to pubsub topics immediately
|
|
|
|
node.Override(new(dtypes.Bootstrapper), dtypes.Bootstrapper(true)),
|
|
|
|
|
2020-08-13 20:37:09 +00:00
|
|
|
genesis,
|
2020-10-08 09:24:31 +00:00
|
|
|
|
|
|
|
fullOpts[i].Opts(fulls),
|
2020-08-13 20:37:09 +00:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("%+v", err)
|
|
|
|
}
|
2020-10-07 09:26:15 +00:00
|
|
|
|
2020-10-08 22:59:06 +00:00
|
|
|
t.Cleanup(func() { _ = stop(context.Background()) })
|
2020-10-07 09:26:15 +00:00
|
|
|
|
|
|
|
if rpc {
|
|
|
|
fulls[i] = fullRpc(t, fulls[i])
|
|
|
|
}
|
2021-04-23 12:29:46 +00:00
|
|
|
|
|
|
|
fulls[i].Stb = storageBuilder(fulls[i], mn, node.Options(
|
|
|
|
node.Override(new(sectorstorage.SectorManager), func() (sectorstorage.SectorManager, error) {
|
|
|
|
return mock.NewMockSectorMgr(nil), nil
|
|
|
|
}),
|
|
|
|
node.Override(new(ffiwrapper.Verifier), mock.MockVerifier),
|
|
|
|
node.Unset(new(*sectorstorage.Manager)),
|
|
|
|
))
|
2020-08-13 20:37:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for i, def := range storage {
|
|
|
|
// TODO: support non-bootstrap miners
|
|
|
|
|
|
|
|
minerID := abi.ActorID(genesis2.MinerStart + uint64(i))
|
|
|
|
|
|
|
|
if def.Full != 0 {
|
|
|
|
t.Fatal("storage nodes only supported on the first full node")
|
|
|
|
}
|
|
|
|
|
|
|
|
f := fulls[def.Full]
|
|
|
|
if _, err := f.FullNode.WalletImport(ctx, &keys[i].KeyInfo); err != nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
if err := f.FullNode.WalletSetDefault(ctx, keys[i].Address); err != nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
sectors := make([]abi.SectorID, len(genms[i].Sectors))
|
|
|
|
for i, sector := range genms[i].Sectors {
|
|
|
|
sectors[i] = abi.SectorID{
|
|
|
|
Miner: minerID,
|
|
|
|
Number: sector.SectorID,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-08 15:28:38 +00:00
|
|
|
opts := def.Opts
|
|
|
|
if opts == nil {
|
|
|
|
opts = node.Options()
|
|
|
|
}
|
2021-05-19 10:47:37 +00:00
|
|
|
miners[i] = CreateTestStorageNode(ctx, t, genms[i].Worker, maddrs[i], pidKeys[i], f, mn, node.Options(
|
2020-08-13 20:37:09 +00:00
|
|
|
node.Override(new(sectorstorage.SectorManager), func() (sectorstorage.SectorManager, error) {
|
2020-11-05 12:43:05 +00:00
|
|
|
return mock.NewMockSectorMgr(sectors), nil
|
2020-08-13 20:37:09 +00:00
|
|
|
}),
|
|
|
|
node.Override(new(ffiwrapper.Verifier), mock.MockVerifier),
|
|
|
|
node.Unset(new(*sectorstorage.Manager)),
|
2021-01-08 15:28:38 +00:00
|
|
|
opts,
|
2020-08-13 20:37:09 +00:00
|
|
|
))
|
2020-10-07 09:26:15 +00:00
|
|
|
|
|
|
|
if rpc {
|
2021-05-19 10:47:37 +00:00
|
|
|
miners[i] = storerRpc(t, miners[i])
|
2020-10-07 09:26:15 +00:00
|
|
|
}
|
2020-08-13 20:37:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := mn.LinkAll(); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
bm := NewBlockMiner(t, miners[0])
|
|
|
|
|
|
|
|
if len(miners) > 0 {
|
2020-08-13 20:37:09 +00:00
|
|
|
// Mine 2 blocks to setup some CE stuff in some actors
|
|
|
|
var wait sync.Mutex
|
|
|
|
wait.Lock()
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
bm.MineUntilBlock(ctx, fulls[0], func(abi.ChainEpoch) {
|
2020-08-13 20:37:09 +00:00
|
|
|
wait.Unlock()
|
2020-08-26 00:06:45 +00:00
|
|
|
})
|
2020-08-13 20:37:09 +00:00
|
|
|
wait.Lock()
|
2021-05-19 10:47:37 +00:00
|
|
|
bm.MineUntilBlock(ctx, fulls[0], func(abi.ChainEpoch) {
|
2020-08-13 20:37:09 +00:00
|
|
|
wait.Unlock()
|
2020-08-26 00:06:45 +00:00
|
|
|
})
|
2020-08-13 20:37:09 +00:00
|
|
|
wait.Lock()
|
|
|
|
}
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
return fulls, miners
|
2020-08-13 20:37:09 +00:00
|
|
|
}
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
func fullRpc(t *testing.T, nd TestFullNode) TestFullNode {
|
2021-04-05 19:34:03 +00:00
|
|
|
ma, listenAddr, err := CreateRPCServer(t, map[string]interface{}{
|
|
|
|
"/rpc/v1": nd,
|
|
|
|
"/rpc/v0": &v0api.WrapperV1Full{FullNode: nd},
|
|
|
|
})
|
2020-10-07 09:26:15 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2021-01-21 02:17:41 +00:00
|
|
|
var stop func()
|
2021-05-19 10:47:37 +00:00
|
|
|
var full TestFullNode
|
2021-04-05 19:34:03 +00:00
|
|
|
full.FullNode, stop, err = client.NewFullNodeRPCV1(context.Background(), listenAddr+"/rpc/v1", nil)
|
2020-10-07 09:26:15 +00:00
|
|
|
require.NoError(t, err)
|
2021-01-21 02:17:41 +00:00
|
|
|
t.Cleanup(stop)
|
2020-08-13 20:37:09 +00:00
|
|
|
|
2020-10-07 09:26:15 +00:00
|
|
|
full.ListenAddr = ma
|
|
|
|
return full
|
2020-08-13 20:37:09 +00:00
|
|
|
}
|
|
|
|
|
2021-05-19 10:47:37 +00:00
|
|
|
func storerRpc(t *testing.T, nd TestMiner) TestMiner {
|
2021-04-05 19:34:03 +00:00
|
|
|
ma, listenAddr, err := CreateRPCServer(t, map[string]interface{}{
|
|
|
|
"/rpc/v0": nd,
|
|
|
|
})
|
2020-10-07 09:26:15 +00:00
|
|
|
require.NoError(t, err)
|
2020-08-13 20:37:09 +00:00
|
|
|
|
2021-01-21 02:17:41 +00:00
|
|
|
var stop func()
|
2021-05-19 10:47:37 +00:00
|
|
|
var storer TestMiner
|
2021-04-05 19:34:03 +00:00
|
|
|
storer.StorageMiner, stop, err = client.NewStorageMinerRPCV0(context.Background(), listenAddr+"/rpc/v0", nil)
|
2020-10-07 09:26:15 +00:00
|
|
|
require.NoError(t, err)
|
2021-01-21 02:17:41 +00:00
|
|
|
t.Cleanup(stop)
|
2020-08-13 20:37:09 +00:00
|
|
|
|
2020-10-07 09:26:15 +00:00
|
|
|
storer.ListenAddr = ma
|
|
|
|
storer.MineOne = nd.MineOne
|
|
|
|
return storer
|
|
|
|
}
|
2020-08-13 20:37:09 +00:00
|
|
|
|
2021-04-05 19:34:03 +00:00
|
|
|
func CreateRPCServer(t *testing.T, handlers map[string]interface{}) (multiaddr.Multiaddr, string, error) {
|
|
|
|
m := mux.NewRouter()
|
|
|
|
for path, handler := range handlers {
|
|
|
|
rpcServer := jsonrpc.NewServer()
|
|
|
|
rpcServer.Register("Filecoin", handler)
|
|
|
|
m.Handle(path, rpcServer)
|
|
|
|
}
|
2021-05-18 20:32:10 +00:00
|
|
|
testServ := httptest.NewServer(m) // todo: close
|
2021-01-21 02:17:41 +00:00
|
|
|
t.Cleanup(testServ.Close)
|
|
|
|
t.Cleanup(testServ.CloseClientConnections)
|
2020-08-13 20:37:09 +00:00
|
|
|
|
2020-10-07 09:26:15 +00:00
|
|
|
addr := testServ.Listener.Addr()
|
|
|
|
listenAddr := "ws://" + addr.String()
|
|
|
|
ma, err := parseWSMultiAddr(addr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
2020-08-13 20:37:09 +00:00
|
|
|
}
|
2020-10-07 09:26:15 +00:00
|
|
|
return ma, listenAddr, err
|
2020-08-13 20:37:09 +00:00
|
|
|
}
|
|
|
|
|
2020-10-07 09:26:15 +00:00
|
|
|
func parseWSMultiAddr(addr net.Addr) (multiaddr.Multiaddr, error) {
|
2020-08-13 20:37:09 +00:00
|
|
|
host, port, err := net.SplitHostPort(addr.String())
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-10-07 09:26:15 +00:00
|
|
|
ma, err := multiaddr.NewMultiaddr("/ip4/" + host + "/" + addr.Network() + "/" + port + "/ws")
|
2020-08-13 20:37:09 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return ma, nil
|
|
|
|
}
|
2020-10-07 09:26:15 +00:00
|
|
|
|
|
|
|
func WSMultiAddrToString(addr multiaddr.Multiaddr) (string, error) {
|
|
|
|
parts := strings.Split(addr.String(), "/")
|
|
|
|
if len(parts) != 6 || parts[0] != "" {
|
|
|
|
return "", xerrors.Errorf("Malformed ws multiaddr %s", addr)
|
|
|
|
}
|
|
|
|
|
|
|
|
host := parts[2]
|
|
|
|
port := parts[4]
|
|
|
|
proto := parts[5]
|
|
|
|
|
|
|
|
return proto + "://" + host + ":" + port + "/rpc/v0", nil
|
|
|
|
}
|