feat: add end-to-end test for lite mode
This commit is contained in:
parent
7b1bec91ed
commit
ef73b964fb
@ -37,7 +37,7 @@ func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
|||||||
|
|
||||||
func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeHeight abi.ChainEpoch) {
|
func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeHeight abi.ChainEpoch) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
n, sn := b(t, 1, OneMiner, node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
n, sn := b(t, OneFull, OneMiner, node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
||||||
Network: build.ActorUpgradeNetworkVersion,
|
Network: build.ActorUpgradeNetworkVersion,
|
||||||
Height: upgradeHeight,
|
Height: upgradeHeight,
|
||||||
Migration: stmgr.UpgradeActorsV2,
|
Migration: stmgr.UpgradeActorsV2,
|
||||||
|
@ -48,7 +48,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, OneMiner)
|
n, sn := b(t, OneFull, OneMiner)
|
||||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||||
miner := sn[0]
|
miner := sn[0]
|
||||||
|
|
||||||
@ -85,7 +85,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, OneMiner)
|
n, sn := b(t, OneFull, OneMiner)
|
||||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||||
miner := sn[0]
|
miner := sn[0]
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Durati
|
|||||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
n, sn := b(t, 1, OneMiner)
|
n, sn := b(t, OneFull, OneMiner)
|
||||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||||
miner := sn[0]
|
miner := sn[0]
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ func TestSenondDealRetrieval(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, OneMiner)
|
n, sn := b(t, OneFull, OneMiner)
|
||||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||||
miner := sn[0]
|
miner := sn[0]
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ 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, OneMiner)
|
apis, sn := ts.makeNodes(t, OneFull, OneMiner)
|
||||||
api := apis[0]
|
api := apis[0]
|
||||||
|
|
||||||
newHeads, err := api.ChainNotify(ctx)
|
newHeads, err := api.ChainNotify(ctx)
|
||||||
@ -54,7 +54,7 @@ func (ts *testSuite) testMiningReal(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
apis, sn := ts.makeNodes(t, 1, OneMiner)
|
apis, sn := ts.makeNodes(t, OneFull, OneMiner)
|
||||||
api := apis[0]
|
api := apis[0]
|
||||||
|
|
||||||
newHeads, err := api.ChainNotify(ctx)
|
newHeads, err := api.ChainNotify(ctx)
|
||||||
@ -93,7 +93,7 @@ func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExpo
|
|||||||
// test making a deal with a fresh miner, and see if it starts to mine
|
// test making a deal with a fresh miner, and see if it starts to mine
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
n, sn := b(t, 1, []StorageMiner{
|
n, sn := b(t, OneFull, []StorageMiner{
|
||||||
{Full: 0, Preseal: PresealGenesis},
|
{Full: 0, Preseal: PresealGenesis},
|
||||||
{Full: 0, Preseal: 0}, // TODO: Add support for miners on non-first full node
|
{Full: 0, Preseal: 0}, // TODO: Add support for miners on non-first full node
|
||||||
})
|
})
|
||||||
|
@ -33,7 +33,7 @@ func TestPaymentChannels(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, 2, OneMiner)
|
n, sn := b(t, TwoFull, OneMiner)
|
||||||
|
|
||||||
paymentCreator := n[0]
|
paymentCreator := n[0]
|
||||||
paymentReceiver := n[1]
|
paymentReceiver := n[1]
|
||||||
|
@ -40,12 +40,14 @@ type StorageMiner struct {
|
|||||||
Preseal int
|
Preseal int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OptionGenerator func([]TestNode) node.Option
|
||||||
|
|
||||||
// APIBuilder is a function which is invoked in test suite to provide
|
// APIBuilder is a function which is invoked in test suite to provide
|
||||||
// test nodes and networks
|
// test nodes and networks
|
||||||
//
|
//
|
||||||
// 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 []StorageMiner, opts ...node.Option) ([]TestNode, []TestStorageNode)
|
type APIBuilder func(t *testing.T, full []OptionGenerator, storage []StorageMiner, opts ...node.Option) ([]TestNode, []TestStorageNode)
|
||||||
type testSuite struct {
|
type testSuite struct {
|
||||||
makeNodes APIBuilder
|
makeNodes APIBuilder
|
||||||
}
|
}
|
||||||
@ -63,13 +65,25 @@ func TestApis(t *testing.T, b APIBuilder) {
|
|||||||
t.Run("testMiningReal", ts.testMiningReal)
|
t.Run("testMiningReal", ts.testMiningReal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DefaultFullOpts(nFull int) []OptionGenerator {
|
||||||
|
full := make([]OptionGenerator, nFull)
|
||||||
|
for i := range full {
|
||||||
|
full[i] = func(nodes []TestNode) node.Option {
|
||||||
|
return node.Options()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return full
|
||||||
|
}
|
||||||
|
|
||||||
var OneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}}
|
var OneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}}
|
||||||
|
var OneFull = DefaultFullOpts(1)
|
||||||
|
var TwoFull = DefaultFullOpts(2)
|
||||||
|
|
||||||
func (ts *testSuite) testVersion(t *testing.T) {
|
func (ts *testSuite) testVersion(t *testing.T) {
|
||||||
build.RunningNodeType = build.NodeFull
|
build.RunningNodeType = build.NodeFull
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
apis, _ := ts.makeNodes(t, 1, OneMiner)
|
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
|
||||||
api := apis[0]
|
api := apis[0]
|
||||||
|
|
||||||
v, err := api.Version(ctx)
|
v, err := api.Version(ctx)
|
||||||
@ -81,7 +95,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, OneMiner)
|
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
|
||||||
api := apis[0]
|
api := apis[0]
|
||||||
|
|
||||||
id, err := api.ID(ctx)
|
id, err := api.ID(ctx)
|
||||||
@ -93,7 +107,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, OneMiner)
|
apis, _ := ts.makeNodes(t, TwoFull, OneMiner)
|
||||||
|
|
||||||
p, err := apis[0].NetPeers(ctx)
|
p, err := apis[0].NetPeers(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -34,7 +34,7 @@ func init() {
|
|||||||
|
|
||||||
func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
|
func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
n, sn := b(t, 1, OneMiner)
|
n, sn := b(t, OneFull, OneMiner)
|
||||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||||
miner := sn[0]
|
miner := sn[0]
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ func testWindowPostUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration,
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
n, sn := b(t, 1, OneMiner, node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
n, sn := b(t, OneFull, OneMiner, node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
||||||
Network: build.ActorUpgradeNetworkVersion,
|
Network: build.ActorUpgradeNetworkVersion,
|
||||||
Height: upgradeHeight,
|
Height: upgradeHeight,
|
||||||
Migration: stmgr.UpgradeActorsV2,
|
Migration: stmgr.UpgradeActorsV2,
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/lotus/chain/messagepool"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
"github.com/filecoin-project/lotus/chain/wallet"
|
||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
@ -21,7 +20,7 @@ const dsKeyActorNonce = "ActorNextNonce"
|
|||||||
|
|
||||||
var log = logging.Logger("messagesigner")
|
var log = logging.Logger("messagesigner")
|
||||||
|
|
||||||
type mpoolAPI interface {
|
type MpoolNonceAPI interface {
|
||||||
GetNonce(address.Address) (uint64, error)
|
GetNonce(address.Address) (uint64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,15 +29,11 @@ type mpoolAPI interface {
|
|||||||
type MessageSigner struct {
|
type MessageSigner struct {
|
||||||
wallet *wallet.Wallet
|
wallet *wallet.Wallet
|
||||||
lk sync.Mutex
|
lk sync.Mutex
|
||||||
mpool mpoolAPI
|
mpool MpoolNonceAPI
|
||||||
ds datastore.Batching
|
ds datastore.Batching
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMessageSigner(wallet *wallet.Wallet, mpool *messagepool.MessagePool, ds dtypes.MetadataDS) *MessageSigner {
|
func NewMessageSigner(wallet *wallet.Wallet, mpool MpoolNonceAPI, ds dtypes.MetadataDS) *MessageSigner {
|
||||||
return newMessageSigner(wallet, mpool, ds)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newMessageSigner(wallet *wallet.Wallet, mpool mpoolAPI, ds dtypes.MetadataDS) *MessageSigner {
|
|
||||||
ds = namespace.Wrap(ds, datastore.NewKey("/message-signer/"))
|
ds = namespace.Wrap(ds, datastore.NewKey("/message-signer/"))
|
||||||
return &MessageSigner{
|
return &MessageSigner{
|
||||||
wallet: wallet,
|
wallet: wallet,
|
||||||
|
@ -177,7 +177,7 @@ func TestMessageSignerSignMessage(t *testing.T) {
|
|||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
mpool := newMockMpool()
|
mpool := newMockMpool()
|
||||||
ds := ds_sync.MutexWrap(datastore.NewMapDatastore())
|
ds := ds_sync.MutexWrap(datastore.NewMapDatastore())
|
||||||
ms := newMessageSigner(w, mpool, ds)
|
ms := NewMessageSigner(w, mpool, ds)
|
||||||
|
|
||||||
for _, m := range tt.msgs {
|
for _, m := range tt.msgs {
|
||||||
if len(m.mpoolNonce) == 1 {
|
if len(m.mpoolNonce) == 1 {
|
||||||
|
@ -390,7 +390,7 @@ func checkVoucherOutput(t *testing.T, list string, vouchers []voucherSpec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func startTwoNodesOneMiner(ctx context.Context, t *testing.T, blocktime time.Duration) ([]test.TestNode, []address.Address) {
|
func startTwoNodesOneMiner(ctx context.Context, t *testing.T, blocktime time.Duration) ([]test.TestNode, []address.Address) {
|
||||||
n, sn := builder.RPCMockSbBuilder(t, 2, test.OneMiner)
|
n, sn := builder.RPCMockSbBuilder(t, test.TwoFull, test.OneMiner)
|
||||||
|
|
||||||
paymentCreator := n[0]
|
paymentCreator := n[0]
|
||||||
paymentReceiver := n[1]
|
paymentReceiver := n[1]
|
||||||
|
183
cmd/lotus-gateway/api_test.go
Normal file
183
cmd/lotus-gateway/api_test.go
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/types/mock"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/ipfs/go-cid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGatewayAPIChainGetTipSetByHeight(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
lookbackTimestamp := uint64(time.Now().Unix()) - uint64(LookbackCap.Seconds())
|
||||||
|
type args struct {
|
||||||
|
h abi.ChainEpoch
|
||||||
|
tskh abi.ChainEpoch
|
||||||
|
genesisTS uint64
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
expErr bool
|
||||||
|
}{{
|
||||||
|
name: "basic",
|
||||||
|
args: args{
|
||||||
|
h: abi.ChainEpoch(1),
|
||||||
|
tskh: abi.ChainEpoch(5),
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "genesis",
|
||||||
|
args: args{
|
||||||
|
h: abi.ChainEpoch(0),
|
||||||
|
tskh: abi.ChainEpoch(5),
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "same epoch as tipset",
|
||||||
|
args: args{
|
||||||
|
h: abi.ChainEpoch(5),
|
||||||
|
tskh: abi.ChainEpoch(5),
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "tipset too old",
|
||||||
|
args: args{
|
||||||
|
// Tipset height is 5, genesis is at LookbackCap - 10 epochs.
|
||||||
|
// So resulting tipset height will be 5 epochs earlier than LookbackCap.
|
||||||
|
h: abi.ChainEpoch(1),
|
||||||
|
tskh: abi.ChainEpoch(5),
|
||||||
|
genesisTS: lookbackTimestamp - build.BlockDelaySecs*10,
|
||||||
|
},
|
||||||
|
expErr: true,
|
||||||
|
}, {
|
||||||
|
name: "lookup height too old",
|
||||||
|
args: args{
|
||||||
|
// Tipset height is 5, lookup height is 1, genesis is at LookbackCap - 3 epochs.
|
||||||
|
// So
|
||||||
|
// - lookup height will be 2 epochs earlier than LookbackCap.
|
||||||
|
// - tipset height will be 2 epochs later than LookbackCap.
|
||||||
|
h: abi.ChainEpoch(1),
|
||||||
|
tskh: abi.ChainEpoch(5),
|
||||||
|
genesisTS: lookbackTimestamp - build.BlockDelaySecs*3,
|
||||||
|
},
|
||||||
|
expErr: true,
|
||||||
|
}, {
|
||||||
|
name: "tipset and lookup height within acceptable range",
|
||||||
|
args: args{
|
||||||
|
// Tipset height is 5, lookup height is 1, genesis is at LookbackCap.
|
||||||
|
// So
|
||||||
|
// - lookup height will be 1 epoch later than LookbackCap.
|
||||||
|
// - tipset height will be 5 epochs later than LookbackCap.
|
||||||
|
h: abi.ChainEpoch(1),
|
||||||
|
tskh: abi.ChainEpoch(5),
|
||||||
|
genesisTS: lookbackTimestamp,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
mock := &mockRPCAPI{}
|
||||||
|
a := &GatewayAPI{rpc: mock}
|
||||||
|
|
||||||
|
// Create tipsets from genesis up to tskh and return the highest
|
||||||
|
ts := mock.createTipSets(tt.args.tskh, tt.args.genesisTS)
|
||||||
|
|
||||||
|
got, err := a.ChainGetTipSetByHeight(ctx, tt.args.h, ts.Key())
|
||||||
|
if tt.expErr {
|
||||||
|
require.Error(t, err)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, tt.args.h, got.Height())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockRPCAPI struct {
|
||||||
|
lk sync.RWMutex
|
||||||
|
tipsets []*types.TipSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockRPCAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||||
|
m.lk.RLock()
|
||||||
|
defer m.lk.RUnlock()
|
||||||
|
|
||||||
|
return m.tipsets[len(m.tipsets)-1], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockRPCAPI) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||||
|
m.lk.RLock()
|
||||||
|
defer m.lk.RUnlock()
|
||||||
|
|
||||||
|
for _, ts := range m.tipsets {
|
||||||
|
if ts.Key() == tsk {
|
||||||
|
return ts, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createTipSets creates tipsets from genesis up to tskh and returns the highest
|
||||||
|
func (m *mockRPCAPI) createTipSets(h abi.ChainEpoch, genesisTimestamp uint64) *types.TipSet {
|
||||||
|
m.lk.Lock()
|
||||||
|
defer m.lk.Unlock()
|
||||||
|
|
||||||
|
targeth := h + 1 // add one for genesis block
|
||||||
|
if genesisTimestamp == 0 {
|
||||||
|
genesisTimestamp = uint64(time.Now().Unix()) - build.BlockDelaySecs*uint64(targeth)
|
||||||
|
}
|
||||||
|
var currts *types.TipSet
|
||||||
|
for currh := abi.ChainEpoch(0); currh < targeth; currh++ {
|
||||||
|
blks := mock.MkBlock(currts, 1, 1)
|
||||||
|
if currh == 0 {
|
||||||
|
blks.Timestamp = genesisTimestamp
|
||||||
|
}
|
||||||
|
currts = mock.TipSet(blks)
|
||||||
|
m.tipsets = append(m.tipsets, currts)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.tipsets[len(m.tipsets)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockRPCAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||||
|
m.lk.Lock()
|
||||||
|
defer m.lk.Unlock()
|
||||||
|
|
||||||
|
return m.tipsets[h], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockRPCAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockRPCAPI) MpoolPushUntrusted(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockRPCAPI) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockRPCAPI) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockRPCAPI) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockRPCAPI) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
140
cmd/lotus-gateway/endtoend_test.go
Normal file
140
cmd/lotus-gateway/endtoend_test.go
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-address"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/node"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/api/client"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-jsonrpc"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/wallet"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
builder "github.com/filecoin-project/lotus/node/test"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/api/test"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
|
||||||
|
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
|
||||||
|
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEndToEnd(t *testing.T) {
|
||||||
|
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
|
|
||||||
|
blocktime := 5 * time.Millisecond
|
||||||
|
ctx := context.Background()
|
||||||
|
full, lite, closer := startNodes(ctx, t, blocktime)
|
||||||
|
defer closer()
|
||||||
|
|
||||||
|
// The full node starts with a wallet
|
||||||
|
fullWalletAddr, err := full.WalletDefaultAddress(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Check the full node's wallet balance from the lite node
|
||||||
|
balance, err := lite.WalletBalance(ctx, fullWalletAddr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
fmt.Println(balance)
|
||||||
|
|
||||||
|
// Create a wallet on the lite node
|
||||||
|
liteWalletAddr, err := lite.WalletNew(ctx, wallet.ActSigType("secp256k1"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Send some funds from the full node to the lite node
|
||||||
|
err = sendFunds(ctx, t, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Send some funds from the lite node back to the full node
|
||||||
|
err = sendFunds(ctx, t, lite, liteWalletAddr, fullWalletAddr, types.NewInt(100))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
data := []byte("hello")
|
||||||
|
sig, err := lite.WalletSign(ctx, liteWalletAddr, data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
ok, err := lite.WalletVerify(ctx, liteWalletAddr, data, sig)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendFunds(ctx context.Context, t *testing.T, fromNode test.TestNode, fromAddr address.Address, toAddr address.Address, amt types.BigInt) error {
|
||||||
|
msg := &types.Message{
|
||||||
|
From: fromAddr,
|
||||||
|
To: toAddr,
|
||||||
|
Value: amt,
|
||||||
|
}
|
||||||
|
|
||||||
|
sm, err := fromNode.MpoolPushMessage(ctx, msg, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := fromNode.StateWaitMsg(ctx, sm.Cid(), 1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if res.Receipt.ExitCode != 0 {
|
||||||
|
return xerrors.Errorf("send funds failed with exit code %d", res.Receipt.ExitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration) (test.TestNode, test.TestNode, jsonrpc.ClientCloser) {
|
||||||
|
var closer jsonrpc.ClientCloser
|
||||||
|
|
||||||
|
opts := append(
|
||||||
|
// Full node
|
||||||
|
test.OneFull,
|
||||||
|
// Lite node
|
||||||
|
func(nodes []test.TestNode) node.Option {
|
||||||
|
fullNode := nodes[0]
|
||||||
|
|
||||||
|
addr, err := builder.WSMultiAddrToString(fullNode.ListenAddr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Create a gateway API that connects to the full node
|
||||||
|
var gapi api.GatewayAPI
|
||||||
|
gapi, closer, err = client.NewGatewayRPC(ctx, addr, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return node.LiteModeOverrides(gapi)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
n, sn := builder.RPCMockSbBuilderWithOpts(t, opts, test.OneMiner)
|
||||||
|
|
||||||
|
full := n[0]
|
||||||
|
lite := n[1]
|
||||||
|
miner := sn[0]
|
||||||
|
|
||||||
|
// Get the listener address for the full node
|
||||||
|
fullAddr, err := full.NetAddrsListen(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Connect the miner and the full node
|
||||||
|
err = miner.NetConnect(ctx, fullAddr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Start mining blocks
|
||||||
|
bm := test.NewBlockMiner(ctx, t, miner, blocktime)
|
||||||
|
bm.MineBlocks()
|
||||||
|
|
||||||
|
return full, lite, closer
|
||||||
|
}
|
@ -64,8 +64,8 @@ func TestMinerAllInfo(t *testing.T) {
|
|||||||
require.NoError(t, infoAllCmd.Action(cctx))
|
require.NoError(t, infoAllCmd.Action(cctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
bp := func(t *testing.T, nFull int, storage []test.StorageMiner, opts ...node.Option) ([]test.TestNode, []test.TestStorageNode) {
|
bp := func(t *testing.T, fullOpts []test.OptionGenerator, storage []test.StorageMiner, opts ...node.Option) ([]test.TestNode, []test.TestStorageNode) {
|
||||||
n, sn = builder.Builder(t, nFull, storage, opts...)
|
n, sn = builder.Builder(t, fullOpts, storage, opts...)
|
||||||
|
|
||||||
t.Run("pre-info-all", run)
|
t.Run("pre-info-all", run)
|
||||||
|
|
||||||
|
@ -39,7 +39,6 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/lib/ulimit"
|
"github.com/filecoin-project/lotus/lib/ulimit"
|
||||||
"github.com/filecoin-project/lotus/metrics"
|
"github.com/filecoin-project/lotus/metrics"
|
||||||
"github.com/filecoin-project/lotus/node"
|
"github.com/filecoin-project/lotus/node"
|
||||||
"github.com/filecoin-project/lotus/node/impl/full"
|
|
||||||
"github.com/filecoin-project/lotus/node/modules"
|
"github.com/filecoin-project/lotus/node/modules"
|
||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
"github.com/filecoin-project/lotus/node/modules/testing"
|
"github.com/filecoin-project/lotus/node/modules/testing"
|
||||||
@ -255,20 +254,7 @@ var DaemonCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer closer()
|
defer closer()
|
||||||
|
liteMode = node.LiteModeOverrides(gapi)
|
||||||
liteMode = node.Options(
|
|
||||||
node.Override(new(api.GatewayAPI), gapi),
|
|
||||||
node.Override(new(full.ChainModuleAPI), node.From(new(api.GatewayAPI))),
|
|
||||||
node.Override(new(full.GasModuleAPI), node.From(new(api.GatewayAPI))),
|
|
||||||
node.Override(new(full.MpoolModuleAPI), node.From(new(api.GatewayAPI))),
|
|
||||||
node.Override(new(full.StateModuleAPI), node.From(new(api.GatewayAPI))),
|
|
||||||
node.Override(new(stmgr.StateManagerAPI), modules.NewRPCStateManager),
|
|
||||||
node.Unset(node.RunHelloKey),
|
|
||||||
node.Unset(node.RunChainExchangeKey),
|
|
||||||
node.Unset(node.RunPeerMgrKey),
|
|
||||||
node.Unset(node.HandleIncomingBlocksKey),
|
|
||||||
node.Unset(node.HandleIncomingMessagesKey),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var api api.FullNode
|
var api api.FullNode
|
||||||
|
@ -264,6 +264,7 @@ func Online() Option {
|
|||||||
Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule),
|
Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule),
|
||||||
Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))),
|
Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))),
|
||||||
Override(new(*wallet.Wallet), wallet.NewWallet),
|
Override(new(*wallet.Wallet), wallet.NewWallet),
|
||||||
|
Override(new(messagesigner.MpoolNonceAPI), From(new(*messagepool.MessagePool))),
|
||||||
Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner),
|
Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner),
|
||||||
|
|
||||||
Override(new(full.ChainModuleAPI), From(new(full.ChainModule))),
|
Override(new(full.ChainModuleAPI), From(new(full.ChainModule))),
|
||||||
@ -401,6 +402,23 @@ func StorageMiner(out *api.StorageMiner) Option {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LiteModeOverrides(gapi api.GatewayAPI) Option {
|
||||||
|
return Options(
|
||||||
|
Override(new(messagesigner.MpoolNonceAPI), From(new(modules.MpoolNonceAPI))),
|
||||||
|
Override(new(api.GatewayAPI), gapi),
|
||||||
|
Override(new(full.ChainModuleAPI), From(new(api.GatewayAPI))),
|
||||||
|
Override(new(full.GasModuleAPI), From(new(api.GatewayAPI))),
|
||||||
|
Override(new(full.MpoolModuleAPI), From(new(api.GatewayAPI))),
|
||||||
|
Override(new(full.StateModuleAPI), From(new(api.GatewayAPI))),
|
||||||
|
Override(new(stmgr.StateManagerAPI), modules.NewRPCStateManager),
|
||||||
|
Unset(RunHelloKey),
|
||||||
|
Unset(RunChainExchangeKey),
|
||||||
|
Unset(RunPeerMgrKey),
|
||||||
|
Unset(HandleIncomingBlocksKey),
|
||||||
|
Unset(HandleIncomingMessagesKey),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Config sets up constructors based on the provided Config
|
// Config sets up constructors based on the provided Config
|
||||||
func ConfigCommon(cfg *config.Common) Option {
|
func ConfigCommon(cfg *config.Common) Option {
|
||||||
return Options(
|
return Options(
|
||||||
|
@ -180,7 +180,7 @@ func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message, spe
|
|||||||
|
|
||||||
// Sign and push the message
|
// Sign and push the message
|
||||||
return a.MessageSigner.SignMessage(ctx, msg, func(smsg *types.SignedMessage) error {
|
return a.MessageSigner.SignMessage(ctx, msg, func(smsg *types.SignedMessage) error {
|
||||||
if _, err := a.Mpool.Push(smsg); err != nil {
|
if _, err := a.MpoolModuleAPI.MpoolPush(ctx, smsg); err != nil {
|
||||||
return xerrors.Errorf("mpool push: failed to push message: %w", err)
|
return xerrors.Errorf("mpool push: failed to push message: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
33
node/modules/mpoolnonceapi.go
Normal file
33
node/modules/mpoolnonceapi.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package modules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.uber.org/fx"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/node/impl/full"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/messagesigner"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-address"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MpoolNonceAPI substitutes the mpool nonce with an implementation that
|
||||||
|
// doesn't rely on the mpool - it just gets the nonce from actor state
|
||||||
|
type MpoolNonceAPI struct {
|
||||||
|
fx.In
|
||||||
|
|
||||||
|
StateAPI full.StateAPI
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNonce gets the nonce from actor state
|
||||||
|
func (a *MpoolNonceAPI) GetNonce(addr address.Address) (uint64, error) {
|
||||||
|
act, err := a.StateAPI.StateGetActor(context.Background(), addr, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return act.Nonce, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ messagesigner.MpoolNonceAPI = (*MpoolNonceAPI)(nil)
|
@ -7,10 +7,13 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-jsonrpc"
|
"github.com/filecoin-project/go-jsonrpc"
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
@ -117,6 +120,7 @@ func CreateTestStorageNode(ctx context.Context, t *testing.T, waddr address.Addr
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to construct node: %v", err)
|
t.Fatalf("failed to construct node: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Cleanup(func() { _ = stop(context.Background()) })
|
t.Cleanup(func() { _ = stop(context.Background()) })
|
||||||
|
|
||||||
/*// Bootstrap with full node
|
/*// Bootstrap with full node
|
||||||
@ -137,13 +141,33 @@ func CreateTestStorageNode(ctx context.Context, t *testing.T, waddr address.Addr
|
|||||||
return test.TestStorageNode{StorageMiner: minerapi, MineOne: mineOne}
|
return test.TestStorageNode{StorageMiner: minerapi, MineOne: mineOne}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Builder(t *testing.T, nFull int, storage []test.StorageMiner, opts ...node.Option) ([]test.TestNode, []test.TestStorageNode) {
|
func Builder(t *testing.T, fullOpts []test.OptionGenerator, storage []test.StorageMiner, opts ...node.Option) ([]test.TestNode, []test.TestStorageNode) {
|
||||||
|
return mockBuilderOpts(t, fullOpts, storage, opts, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MockSbBuilder(t *testing.T, fullOpts []test.OptionGenerator, storage []test.StorageMiner, opts ...node.Option) ([]test.TestNode, []test.TestStorageNode) {
|
||||||
|
return mockSbBuilderOpts(t, fullOpts, storage, opts, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RPCBuilder(t *testing.T, fullOpts []test.OptionGenerator, storage []test.StorageMiner, opts ...node.Option) ([]test.TestNode, []test.TestStorageNode) {
|
||||||
|
return mockBuilderOpts(t, fullOpts, storage, opts, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RPCMockSbBuilder(t *testing.T, fullOpts []test.OptionGenerator, storage []test.StorageMiner) ([]test.TestNode, []test.TestStorageNode) {
|
||||||
|
return mockSbBuilderOpts(t, fullOpts, storage, []node.Option{}, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RPCMockSbBuilderWithOpts(t *testing.T, fullOpts []test.OptionGenerator, storage []test.StorageMiner) ([]test.TestNode, []test.TestStorageNode) {
|
||||||
|
return mockSbBuilderOpts(t, fullOpts, storage, []node.Option{}, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mockBuilderOpts(t *testing.T, fullOpts []test.OptionGenerator, storage []test.StorageMiner, opts []node.Option, rpc bool) ([]test.TestNode, []test.TestStorageNode) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
t.Cleanup(cancel)
|
t.Cleanup(cancel)
|
||||||
|
|
||||||
mn := mocknet.New(ctx)
|
mn := mocknet.New(ctx)
|
||||||
|
|
||||||
fulls := make([]test.TestNode, nFull)
|
fulls := make([]test.TestNode, len(fullOpts))
|
||||||
storers := make([]test.TestStorageNode, len(storage))
|
storers := make([]test.TestStorageNode, len(storage))
|
||||||
|
|
||||||
pk, _, err := crypto.GenerateEd25519Key(rand.Reader)
|
pk, _, err := crypto.GenerateEd25519Key(rand.Reader)
|
||||||
@ -208,7 +232,7 @@ func Builder(t *testing.T, nFull int, storage []test.StorageMiner, opts ...node.
|
|||||||
|
|
||||||
// END PRESEAL SECTION
|
// END PRESEAL SECTION
|
||||||
|
|
||||||
for i := 0; i < nFull; i++ {
|
for i := 0; i < len(fullOpts); i++ {
|
||||||
var genesis node.Option
|
var genesis node.Option
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
genesis = node.Override(new(modules.Genesis), testing2.MakeGenesisMem(&genbuf, *templ))
|
genesis = node.Override(new(modules.Genesis), testing2.MakeGenesisMem(&genbuf, *templ))
|
||||||
@ -224,12 +248,18 @@ func Builder(t *testing.T, nFull int, storage []test.StorageMiner, opts ...node.
|
|||||||
node.Test(),
|
node.Test(),
|
||||||
|
|
||||||
genesis,
|
genesis,
|
||||||
|
fullOpts[i](fulls),
|
||||||
node.Options(opts...),
|
node.Options(opts...),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Cleanup(func() { _ = stop(context.Background()) })
|
t.Cleanup(func() { _ = stop(context.Background()) })
|
||||||
|
|
||||||
|
if rpc {
|
||||||
|
fulls[i] = fullRpc(t, fulls[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, def := range storage {
|
for i, def := range storage {
|
||||||
@ -261,6 +291,9 @@ func Builder(t *testing.T, nFull int, storage []test.StorageMiner, opts ...node.
|
|||||||
|
|
||||||
psd := presealDirs[i]
|
psd := presealDirs[i]
|
||||||
*/
|
*/
|
||||||
|
if rpc {
|
||||||
|
storers[i] = storerRpc(t, storers[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := mn.LinkAll(); err != nil {
|
if err := mn.LinkAll(); err != nil {
|
||||||
@ -286,11 +319,13 @@ func Builder(t *testing.T, nFull int, storage []test.StorageMiner, opts ...node.
|
|||||||
return fulls, storers
|
return fulls, storers
|
||||||
}
|
}
|
||||||
|
|
||||||
func MockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner, options ...node.Option) ([]test.TestNode, []test.TestStorageNode) {
|
func mockSbBuilderOpts(t *testing.T, fullOpts []test.OptionGenerator, storage []test.StorageMiner, options []node.Option, rpc bool) ([]test.TestNode, []test.TestStorageNode) {
|
||||||
ctx := context.Background()
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
t.Cleanup(cancel)
|
||||||
|
|
||||||
mn := mocknet.New(ctx)
|
mn := mocknet.New(ctx)
|
||||||
|
|
||||||
fulls := make([]test.TestNode, nFull)
|
fulls := make([]test.TestNode, len(fullOpts))
|
||||||
storers := make([]test.TestStorageNode, len(storage))
|
storers := make([]test.TestStorageNode, len(storage))
|
||||||
|
|
||||||
var genbuf bytes.Buffer
|
var genbuf bytes.Buffer
|
||||||
@ -354,7 +389,7 @@ func MockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner, options
|
|||||||
|
|
||||||
// END PRESEAL SECTION
|
// END PRESEAL SECTION
|
||||||
|
|
||||||
for i := 0; i < nFull; i++ {
|
for i := 0; i < len(fullOpts); i++ {
|
||||||
var genesis node.Option
|
var genesis node.Option
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
genesis = node.Override(new(modules.Genesis), testing2.MakeGenesisMem(&genbuf, *templ))
|
genesis = node.Override(new(modules.Genesis), testing2.MakeGenesisMem(&genbuf, *templ))
|
||||||
@ -374,12 +409,18 @@ func MockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner, options
|
|||||||
node.Override(new(ffiwrapper.Verifier), mock.MockVerifier),
|
node.Override(new(ffiwrapper.Verifier), mock.MockVerifier),
|
||||||
|
|
||||||
genesis,
|
genesis,
|
||||||
|
fullOpts[i](fulls),
|
||||||
node.Options(options...),
|
node.Options(options...),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%+v", err)
|
t.Fatalf("%+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Cleanup(func() { _ = stop(context.Background()) })
|
t.Cleanup(func() { _ = stop(context.Background()) })
|
||||||
|
|
||||||
|
if rpc {
|
||||||
|
fulls[i] = fullRpc(t, fulls[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, def := range storage {
|
for i, def := range storage {
|
||||||
@ -414,6 +455,10 @@ func MockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner, options
|
|||||||
node.Override(new(ffiwrapper.Verifier), mock.MockVerifier),
|
node.Override(new(ffiwrapper.Verifier), mock.MockVerifier),
|
||||||
node.Unset(new(*sectorstorage.Manager)),
|
node.Unset(new(*sectorstorage.Manager)),
|
||||||
))
|
))
|
||||||
|
|
||||||
|
if rpc {
|
||||||
|
storers[i] = storerRpc(t, storers[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := mn.LinkAll(); err != nil {
|
if err := mn.LinkAll(); err != nil {
|
||||||
@ -438,69 +483,66 @@ func MockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner, options
|
|||||||
return fulls, storers
|
return fulls, storers
|
||||||
}
|
}
|
||||||
|
|
||||||
func RPCBuilder(t *testing.T, nFull int, storage []test.StorageMiner, opts ...node.Option) ([]test.TestNode, []test.TestStorageNode) {
|
func fullRpc(t *testing.T, nd test.TestNode) test.TestNode {
|
||||||
return rpcWithBuilder(t, Builder, nFull, storage, opts...)
|
ma, listenAddr, err := CreateRPCServer(nd)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var full test.TestNode
|
||||||
|
full.FullNode, _, err = client.NewFullNodeRPC(context.Background(), listenAddr, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
full.ListenAddr = ma
|
||||||
|
return full
|
||||||
}
|
}
|
||||||
|
|
||||||
func RPCMockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner, opts ...node.Option) ([]test.TestNode, []test.TestStorageNode) {
|
func storerRpc(t *testing.T, nd test.TestStorageNode) test.TestStorageNode {
|
||||||
return rpcWithBuilder(t, MockSbBuilder, nFull, storage, opts...)
|
ma, listenAddr, err := CreateRPCServer(nd)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var storer test.TestStorageNode
|
||||||
|
storer.StorageMiner, _, err = client.NewStorageMinerRPC(context.Background(), listenAddr, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
storer.ListenAddr = ma
|
||||||
|
storer.MineOne = nd.MineOne
|
||||||
|
return storer
|
||||||
}
|
}
|
||||||
|
|
||||||
func rpcWithBuilder(t *testing.T, b test.APIBuilder, nFull int, storage []test.StorageMiner, opts ...node.Option) ([]test.TestNode, []test.TestStorageNode) {
|
func CreateRPCServer(handler interface{}) (multiaddr.Multiaddr, string, error) {
|
||||||
fullApis, storaApis := b(t, nFull, storage, opts...)
|
rpcServer := jsonrpc.NewServer()
|
||||||
fulls := make([]test.TestNode, nFull)
|
rpcServer.Register("Filecoin", handler)
|
||||||
storers := make([]test.TestStorageNode, len(storage))
|
testServ := httptest.NewServer(rpcServer) // todo: close
|
||||||
|
|
||||||
for i, a := range fullApis {
|
addr := testServ.Listener.Addr()
|
||||||
rpcServer := jsonrpc.NewServer()
|
listenAddr := "ws://" + addr.String()
|
||||||
rpcServer.Register("Filecoin", a)
|
ma, err := parseWSMultiAddr(addr)
|
||||||
testServ := httptest.NewServer(rpcServer) // todo: close
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
addr := testServ.Listener.Addr()
|
|
||||||
listenAddr := "ws://" + addr.String()
|
|
||||||
var err error
|
|
||||||
fulls[i].FullNode, _, err = client.NewFullNodeRPC(context.Background(), listenAddr, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
ma, err := parseWSSMultiAddr(addr)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fulls[i].ListenAddr = ma
|
|
||||||
}
|
}
|
||||||
|
return ma, listenAddr, err
|
||||||
for i, a := range storaApis {
|
|
||||||
rpcServer := jsonrpc.NewServer()
|
|
||||||
rpcServer.Register("Filecoin", a)
|
|
||||||
testServ := httptest.NewServer(rpcServer) // todo: close
|
|
||||||
|
|
||||||
addr := testServ.Listener.Addr()
|
|
||||||
listenAddr := "ws://" + addr.String()
|
|
||||||
var err error
|
|
||||||
storers[i].StorageMiner, _, err = client.NewStorageMinerRPC(context.Background(), listenAddr, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
ma, err := parseWSSMultiAddr(addr)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
storers[i].ListenAddr = ma
|
|
||||||
storers[i].MineOne = a.MineOne
|
|
||||||
}
|
|
||||||
|
|
||||||
return fulls, storers
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseWSSMultiAddr(addr net.Addr) (multiaddr.Multiaddr, error) {
|
func parseWSMultiAddr(addr net.Addr) (multiaddr.Multiaddr, error) {
|
||||||
host, port, err := net.SplitHostPort(addr.String())
|
host, port, err := net.SplitHostPort(addr.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ma, err := multiaddr.NewMultiaddr("/ip4/" + host + "/" + addr.Network() + "/" + port + "/wss")
|
ma, err := multiaddr.NewMultiaddr("/ip4/" + host + "/" + addr.Network() + "/" + port + "/ws")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return ma, nil
|
return ma, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user