Merge pull request #4263 from filecoin-project/feat/lite-market-client
lite-mode - market storage and retrieval clients
This commit is contained in:
commit
dbcba6477e
@ -3,24 +3,42 @@ package api
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/ipfs/go-cid"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
"github.com/filecoin-project/go-state-types/dline"
|
||||||
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type GatewayAPI interface {
|
type GatewayAPI interface {
|
||||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||||
ChainHead(ctx context.Context) (*types.TipSet, error)
|
ChainHead(ctx context.Context) (*types.TipSet, error)
|
||||||
|
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
|
||||||
|
ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error)
|
||||||
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
|
ChainNotify(context.Context) (<-chan []*HeadChange, error)
|
||||||
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||||
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||||
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||||
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||||
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
||||||
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||||
|
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (DealCollateralBounds, error)
|
||||||
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
||||||
|
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
|
||||||
|
StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
|
||||||
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||||
|
StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (MarketBalance, error)
|
||||||
|
StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*MarketDeal, error)
|
||||||
|
StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error)
|
||||||
|
StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
|
||||||
|
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error)
|
||||||
|
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
|
||||||
|
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
|
||||||
StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*MsgLookup, error)
|
StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*MsgLookup, error)
|
||||||
}
|
}
|
||||||
|
@ -374,19 +374,31 @@ type WorkerStruct struct {
|
|||||||
|
|
||||||
type GatewayStruct struct {
|
type GatewayStruct struct {
|
||||||
Internal struct {
|
Internal struct {
|
||||||
// TODO: does the gateway need perms?
|
ChainGetBlockMessages func(ctx context.Context, c cid.Cid) (*api.BlockMessages, error)
|
||||||
ChainHasObj func(context.Context, cid.Cid) (bool, error)
|
ChainGetMessage func(ctx context.Context, mc cid.Cid) (*types.Message, error)
|
||||||
ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
|
ChainHasObj func(context.Context, cid.Cid) (bool, error)
|
||||||
ChainHead func(ctx context.Context) (*types.TipSet, error)
|
ChainHead func(ctx context.Context) (*types.TipSet, error)
|
||||||
|
ChainNotify func(ctx context.Context) (<-chan []*api.HeadChange, error)
|
||||||
ChainReadObj func(context.Context, cid.Cid) ([]byte, error)
|
ChainReadObj func(context.Context, cid.Cid) ([]byte, error)
|
||||||
GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||||
MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||||
MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||||
MsigGetVested func(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
MsigGetVested func(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
||||||
StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||||
|
StateDealProviderCollateralBounds func(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error)
|
||||||
StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
||||||
|
StateGetReceipt func(ctx context.Context, c cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error)
|
||||||
StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||||
|
StateListMiners func(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
|
||||||
|
StateMinerInfo func(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error)
|
||||||
|
StateMinerProvingDeadline func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
|
||||||
|
StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error)
|
||||||
|
StateMarketBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error)
|
||||||
|
StateMarketStorageDeal func(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error)
|
||||||
|
StateNetworkVersion func(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error)
|
||||||
|
StateVerifiedClientStatus func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
|
||||||
StateWaitMsg func(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
|
StateWaitMsg func(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1450,12 +1462,12 @@ func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
|
|||||||
return w.Internal.Closing(ctx)
|
return w.Internal.Closing(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g GatewayStruct) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) {
|
func (g GatewayStruct) ChainGetBlockMessages(ctx context.Context, c cid.Cid) (*api.BlockMessages, error) {
|
||||||
return g.Internal.ChainHasObj(ctx, c)
|
return g.Internal.ChainGetBlockMessages(ctx, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
func (g GatewayStruct) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
|
||||||
return g.Internal.ChainHead(ctx)
|
return g.Internal.ChainGetMessage(ctx, mc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g GatewayStruct) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
|
func (g GatewayStruct) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||||
@ -1466,6 +1478,18 @@ func (g GatewayStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEp
|
|||||||
return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
|
return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) {
|
||||||
|
return g.Internal.ChainHasObj(ctx, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||||
|
return g.Internal.ChainHead(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) {
|
||||||
|
return g.Internal.ChainNotify(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (g GatewayStruct) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
|
func (g GatewayStruct) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
|
||||||
return g.Internal.ChainReadObj(ctx, c)
|
return g.Internal.ChainReadObj(ctx, c)
|
||||||
}
|
}
|
||||||
@ -1490,14 +1514,54 @@ func (g GatewayStruct) StateAccountKey(ctx context.Context, addr address.Address
|
|||||||
return g.Internal.StateAccountKey(ctx, addr, tsk)
|
return g.Internal.StateAccountKey(ctx, addr, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
|
||||||
|
return g.Internal.StateDealProviderCollateralBounds(ctx, size, verified, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
func (g GatewayStruct) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
|
func (g GatewayStruct) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
|
||||||
return g.Internal.StateGetActor(ctx, actor, ts)
|
return g.Internal.StateGetActor(ctx, actor, ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) StateGetReceipt(ctx context.Context, c cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) {
|
||||||
|
return g.Internal.StateGetReceipt(ctx, c, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
func (g GatewayStruct) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
func (g GatewayStruct) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||||
return g.Internal.StateLookupID(ctx, addr, tsk)
|
return g.Internal.StateLookupID(ctx, addr, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
|
||||||
|
return g.Internal.StateListMiners(ctx, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
|
||||||
|
return g.Internal.StateMarketBalance(ctx, addr, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
|
||||||
|
return g.Internal.StateMarketStorageDeal(ctx, dealId, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) {
|
||||||
|
return g.Internal.StateMinerInfo(ctx, actor, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) {
|
||||||
|
return g.Internal.StateMinerProvingDeadline(ctx, addr, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) StateMinerPower(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*api.MinerPower, error) {
|
||||||
|
return g.Internal.StateMinerPower(ctx, addr, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) {
|
||||||
|
return g.Internal.StateNetworkVersion(ctx, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
|
||||||
|
return g.Internal.StateVerifiedClientStatus(ctx, addr, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
func (g GatewayStruct) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
|
func (g GatewayStruct) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
|
||||||
return g.Internal.StateWaitMsg(ctx, msg, confidence)
|
return g.Internal.StateWaitMsg(ctx, msg, confidence)
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeH
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
makeDeal(t, ctx, 6, client, miner, false, false)
|
MakeDeal(t, ctx, 6, client, miner, false, false)
|
||||||
|
|
||||||
// Validate upgrade
|
// Validate upgrade
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
makeDeal(t, ctx, 6, client, miner, carExport, fastRet)
|
MakeDeal(t, ctx, 6, client, miner, carExport, fastRet)
|
||||||
|
|
||||||
atomic.AddInt64(&mine, -1)
|
atomic.AddInt64(&mine, -1)
|
||||||
fmt.Println("shutting down mining")
|
fmt.Println("shutting down mining")
|
||||||
@ -97,24 +97,21 @@ func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
makeDeal(t, ctx, 6, client, miner, false, false)
|
MakeDeal(t, ctx, 6, client, miner, false, false)
|
||||||
makeDeal(t, ctx, 7, client, miner, false, false)
|
MakeDeal(t, ctx, 7, client, miner, false, false)
|
||||||
|
|
||||||
atomic.AddInt64(&mine, -1)
|
atomic.AddInt64(&mine, -1)
|
||||||
fmt.Println("shutting down mining")
|
fmt.Println("shutting down mining")
|
||||||
<-done
|
<-done
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeDeal(t *testing.T, ctx context.Context, rseed int, client *impl.FullNodeAPI, miner TestStorageNode, carExport, fastRet bool) {
|
func MakeDeal(t *testing.T, ctx context.Context, rseed int, client api.FullNode, miner TestStorageNode, carExport, fastRet bool) {
|
||||||
data := make([]byte, 1600)
|
res, data, err := CreateClientFile(ctx, client, rseed)
|
||||||
rand.New(rand.NewSource(int64(rseed))).Read(data)
|
|
||||||
|
|
||||||
r := bytes.NewReader(data)
|
|
||||||
fcid, err := client.ClientImportLocal(ctx, r)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fcid := res.Root
|
||||||
fmt.Println("FILE CID: ", fcid)
|
fmt.Println("FILE CID: ", fcid)
|
||||||
|
|
||||||
deal := startDeal(t, ctx, miner, client, fcid, fastRet)
|
deal := startDeal(t, ctx, miner, client, fcid, fastRet)
|
||||||
@ -130,6 +127,28 @@ func makeDeal(t *testing.T, ctx context.Context, rseed int, client *impl.FullNod
|
|||||||
testRetrieval(t, ctx, client, fcid, &info.PieceCID, carExport, data)
|
testRetrieval(t, ctx, client, fcid, &info.PieceCID, carExport, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CreateClientFile(ctx context.Context, client api.FullNode, rseed int) (*api.ImportRes, []byte, error) {
|
||||||
|
data := make([]byte, 1600)
|
||||||
|
rand.New(rand.NewSource(int64(rseed))).Read(data)
|
||||||
|
|
||||||
|
dir, err := ioutil.TempDir(os.TempDir(), "test-make-deal-")
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
path := filepath.Join(dir, "sourcefile.dat")
|
||||||
|
err = ioutil.WriteFile(path, data, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := client.ClientImport(ctx, api.FileRef{Path: path})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return res, data, nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
@ -259,7 +278,7 @@ func TestSenondDealRetrieval(t *testing.T, b APIBuilder, blocktime time.Duration
|
|||||||
<-done
|
<-done
|
||||||
}
|
}
|
||||||
|
|
||||||
func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client *impl.FullNodeAPI, fcid cid.Cid, fastRet bool) *cid.Cid {
|
func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client api.FullNode, fcid cid.Cid, fastRet bool) *cid.Cid {
|
||||||
maddr, err := miner.ActorAddress(ctx)
|
maddr, err := miner.ActorAddress(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -286,7 +305,7 @@ func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client
|
|||||||
return deal
|
return deal
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitDealSealed(t *testing.T, ctx context.Context, miner TestStorageNode, client *impl.FullNodeAPI, deal *cid.Cid, noseal bool) {
|
func waitDealSealed(t *testing.T, ctx context.Context, miner TestStorageNode, client api.FullNode, deal *cid.Cid, noseal bool) {
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
di, err := client.ClientGetDealInfo(ctx, *deal)
|
di, err := client.ClientGetDealInfo(ctx, *deal)
|
||||||
@ -359,7 +378,7 @@ func startSealingWaiting(t *testing.T, ctx context.Context, miner TestStorageNod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testRetrieval(t *testing.T, ctx context.Context, client *impl.FullNodeAPI, fcid cid.Cid, piece *cid.Cid, carExport bool, data []byte) {
|
func testRetrieval(t *testing.T, ctx context.Context, client api.FullNode, fcid cid.Cid, piece *cid.Cid, carExport bool, data []byte) {
|
||||||
offers, err := client.ClientFindData(ctx, fcid, piece)
|
offers, err := client.ClientFindData(ctx, fcid, piece)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -46,6 +46,8 @@ const LookbackNoLimit = abi.ChainEpoch(-1)
|
|||||||
var log = logging.Logger("statemgr")
|
var log = logging.Logger("statemgr")
|
||||||
|
|
||||||
type StateManagerAPI interface {
|
type StateManagerAPI interface {
|
||||||
|
Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error)
|
||||||
|
GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error)
|
||||||
LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error)
|
LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error)
|
||||||
LookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
|
LookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
|
||||||
ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
|
ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
|
||||||
|
@ -255,25 +255,6 @@ func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *S
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func StateMinerInfo(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*miner.MinerInfo, error) {
|
|
||||||
act, err := sm.LoadActor(ctx, maddr, ts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("failed to load miner actor: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
mas, err := miner.Load(sm.cs.Store(ctx), act)
|
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
mi, err := mas.Info()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &mi, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (bool, error) {
|
func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (bool, error) {
|
||||||
act, err := sm.LoadActor(ctx, power.Address, ts)
|
act, err := sm.LoadActor(ctx, power.Address, ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -343,6 +343,7 @@ var clientDealCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
defer closer()
|
defer closer()
|
||||||
ctx := ReqContext(cctx)
|
ctx := ReqContext(cctx)
|
||||||
|
afmt := NewAppFmt(cctx.App)
|
||||||
|
|
||||||
if cctx.NArg() != 4 {
|
if cctx.NArg() != 4 {
|
||||||
return xerrors.New("expected 4 args: dataCid, miner, price, duration")
|
return xerrors.New("expected 4 args: dataCid, miner, price, duration")
|
||||||
@ -462,7 +463,7 @@ var clientDealCmd = &cli.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(encoder.Encode(*proposal))
|
afmt.Println(encoder.Encode(*proposal))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
@ -477,6 +478,7 @@ func interactiveDeal(cctx *cli.Context) error {
|
|||||||
ctx := ReqContext(cctx)
|
ctx := ReqContext(cctx)
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
afmt := NewAppFmt(cctx.App)
|
||||||
|
|
||||||
state := "import"
|
state := "import"
|
||||||
gib := types.NewInt(1 << 30)
|
gib := types.NewInt(1 << 30)
|
||||||
@ -517,10 +519,10 @@ func interactiveDeal(cctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printErr := func(err error) {
|
printErr := func(err error) {
|
||||||
fmt.Printf("%s %s\n", color.RedString("Error:"), err.Error())
|
afmt.Printf("%s %s\n", color.RedString("Error:"), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
cs := readline.NewCancelableStdin(os.Stdin)
|
cs := readline.NewCancelableStdin(afmt.Stdin)
|
||||||
go func() {
|
go func() {
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
cs.Close() // nolint:errcheck
|
cs.Close() // nolint:errcheck
|
||||||
@ -537,7 +539,7 @@ uiLoop:
|
|||||||
|
|
||||||
switch state {
|
switch state {
|
||||||
case "import":
|
case "import":
|
||||||
fmt.Print("Data CID (from " + color.YellowString("lotus client import") + "): ")
|
afmt.Print("Data CID (from " + color.YellowString("lotus client import") + "): ")
|
||||||
|
|
||||||
_cidStr, _, err := rl.ReadLine()
|
_cidStr, _, err := rl.ReadLine()
|
||||||
cidStr := string(_cidStr)
|
cidStr := string(_cidStr)
|
||||||
@ -560,7 +562,7 @@ uiLoop:
|
|||||||
|
|
||||||
state = "duration"
|
state = "duration"
|
||||||
case "duration":
|
case "duration":
|
||||||
fmt.Print("Deal duration (days): ")
|
afmt.Print("Deal duration (days): ")
|
||||||
|
|
||||||
_daystr, _, err := rl.ReadLine()
|
_daystr, _, err := rl.ReadLine()
|
||||||
daystr := string(_daystr)
|
daystr := string(_daystr)
|
||||||
@ -605,7 +607,7 @@ uiLoop:
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Print("\nMake this a verified deal? (yes/no): ")
|
afmt.Print("\nMake this a verified deal? (yes/no): ")
|
||||||
|
|
||||||
_yn, _, err := rl.ReadLine()
|
_yn, _, err := rl.ReadLine()
|
||||||
yn := string(_yn)
|
yn := string(_yn)
|
||||||
@ -619,13 +621,13 @@ uiLoop:
|
|||||||
case "no":
|
case "no":
|
||||||
verified = false
|
verified = false
|
||||||
default:
|
default:
|
||||||
fmt.Println("Type in full 'yes' or 'no'")
|
afmt.Println("Type in full 'yes' or 'no'")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
state = "miner"
|
state = "miner"
|
||||||
case "miner":
|
case "miner":
|
||||||
fmt.Print("Miner Addresses (f0.. f0..), none to find: ")
|
afmt.Print("Miner Addresses (f0.. f0..), none to find: ")
|
||||||
|
|
||||||
_maddrsStr, _, err := rl.ReadLine()
|
_maddrsStr, _, err := rl.ReadLine()
|
||||||
maddrsStr := string(_maddrsStr)
|
maddrsStr := string(_maddrsStr)
|
||||||
@ -664,11 +666,11 @@ uiLoop:
|
|||||||
candidateAsks = append(candidateAsks, ask)
|
candidateAsks = append(candidateAsks, ask)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Found %d candidate asks\n", len(candidateAsks))
|
afmt.Printf("Found %d candidate asks\n", len(candidateAsks))
|
||||||
state = "find-budget"
|
state = "find-budget"
|
||||||
case "find-budget":
|
case "find-budget":
|
||||||
fmt.Printf("Proposing from %s, Current Balance: %s\n", a, types.FIL(fromBal))
|
afmt.Printf("Proposing from %s, Current Balance: %s\n", a, types.FIL(fromBal))
|
||||||
fmt.Print("Maximum budget (FIL): ") // TODO: Propose some default somehow?
|
afmt.Print("Maximum budget (FIL): ") // TODO: Propose some default somehow?
|
||||||
|
|
||||||
_budgetStr, _, err := rl.ReadLine()
|
_budgetStr, _, err := rl.ReadLine()
|
||||||
budgetStr := string(_budgetStr)
|
budgetStr := string(_budgetStr)
|
||||||
@ -698,10 +700,10 @@ uiLoop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
candidateAsks = goodAsks
|
candidateAsks = goodAsks
|
||||||
fmt.Printf("%d asks within budget\n", len(candidateAsks))
|
afmt.Printf("%d asks within budget\n", len(candidateAsks))
|
||||||
state = "find-count"
|
state = "find-count"
|
||||||
case "find-count":
|
case "find-count":
|
||||||
fmt.Print("Deals to make (1): ")
|
afmt.Print("Deals to make (1): ")
|
||||||
dealcStr, _, err := rl.ReadLine()
|
dealcStr, _, err := rl.ReadLine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printErr(xerrors.Errorf("reading deal count: %w", err))
|
printErr(xerrors.Errorf("reading deal count: %w", err))
|
||||||
@ -780,12 +782,12 @@ uiLoop:
|
|||||||
case "confirm":
|
case "confirm":
|
||||||
// TODO: do some more or epochs math (round to miner PP, deal start buffer)
|
// TODO: do some more or epochs math (round to miner PP, deal start buffer)
|
||||||
|
|
||||||
fmt.Printf("-----\n")
|
afmt.Printf("-----\n")
|
||||||
fmt.Printf("Proposing from %s\n", a)
|
afmt.Printf("Proposing from %s\n", a)
|
||||||
fmt.Printf("\tBalance: %s\n", types.FIL(fromBal))
|
afmt.Printf("\tBalance: %s\n", types.FIL(fromBal))
|
||||||
fmt.Printf("\n")
|
afmt.Printf("\n")
|
||||||
fmt.Printf("Piece size: %s (Payload size: %s)\n", units.BytesSize(float64(ds.PieceSize)), units.BytesSize(float64(ds.PayloadSize)))
|
afmt.Printf("Piece size: %s (Payload size: %s)\n", units.BytesSize(float64(ds.PieceSize)), units.BytesSize(float64(ds.PayloadSize)))
|
||||||
fmt.Printf("Duration: %s\n", dur)
|
afmt.Printf("Duration: %s\n", dur)
|
||||||
|
|
||||||
pricePerGib := big.Zero()
|
pricePerGib := big.Zero()
|
||||||
for _, a := range ask {
|
for _, a := range ask {
|
||||||
@ -804,7 +806,7 @@ uiLoop:
|
|||||||
|
|
||||||
if len(ask) > 1 {
|
if len(ask) > 1 {
|
||||||
totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs)))
|
totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs)))
|
||||||
fmt.Printf("Miner %s (Power:%s) price: ~%s (%s per epoch)\n", color.YellowString(a.Miner.String()), color.GreenString(types.SizeStr(mpow.MinerPower.QualityAdjPower)), color.BlueString(types.FIL(totalPrice).String()), types.FIL(epochPrice))
|
afmt.Printf("Miner %s (Power:%s) price: ~%s (%s per epoch)\n", color.YellowString(a.Miner.String()), color.GreenString(types.SizeStr(mpow.MinerPower.QualityAdjPower)), color.BlueString(types.FIL(totalPrice).String()), types.FIL(epochPrice))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -812,12 +814,12 @@ uiLoop:
|
|||||||
epochPrice := types.BigDiv(types.BigMul(pricePerGib, types.NewInt(uint64(ds.PieceSize))), gib)
|
epochPrice := types.BigDiv(types.BigMul(pricePerGib, types.NewInt(uint64(ds.PieceSize))), gib)
|
||||||
totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs)))
|
totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs)))
|
||||||
|
|
||||||
fmt.Printf("Total price: ~%s (%s per epoch)\n", color.CyanString(types.FIL(totalPrice).String()), types.FIL(epochPrice))
|
afmt.Printf("Total price: ~%s (%s per epoch)\n", color.CyanString(types.FIL(totalPrice).String()), types.FIL(epochPrice))
|
||||||
fmt.Printf("Verified: %v\n", verified)
|
afmt.Printf("Verified: %v\n", verified)
|
||||||
|
|
||||||
state = "accept"
|
state = "accept"
|
||||||
case "accept":
|
case "accept":
|
||||||
fmt.Print("\nAccept (yes/no): ")
|
afmt.Print("\nAccept (yes/no): ")
|
||||||
|
|
||||||
_yn, _, err := rl.ReadLine()
|
_yn, _, err := rl.ReadLine()
|
||||||
yn := string(_yn)
|
yn := string(_yn)
|
||||||
@ -830,7 +832,7 @@ uiLoop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if yn != "yes" {
|
if yn != "yes" {
|
||||||
fmt.Println("Type in full 'yes' or 'no'")
|
afmt.Println("Type in full 'yes' or 'no'")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -861,7 +863,7 @@ uiLoop:
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Deal (%s) CID: %s\n", maddr, color.GreenString(encoder.Encode(*proposal)))
|
afmt.Printf("Deal (%s) CID: %s\n", maddr, color.GreenString(encoder.Encode(*proposal)))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -975,6 +977,7 @@ var clientRetrieveCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
defer closer()
|
defer closer()
|
||||||
ctx := ReqContext(cctx)
|
ctx := ReqContext(cctx)
|
||||||
|
afmt := NewAppFmt(cctx.App)
|
||||||
|
|
||||||
var payer address.Address
|
var payer address.Address
|
||||||
if cctx.String("from") != "" {
|
if cctx.String("from") != "" {
|
||||||
@ -1083,14 +1086,14 @@ var clientRetrieveCmd = &cli.Command{
|
|||||||
select {
|
select {
|
||||||
case evt, ok := <-updates:
|
case evt, ok := <-updates:
|
||||||
if ok {
|
if ok {
|
||||||
fmt.Printf("> Recv: %s, Paid %s, %s (%s)\n",
|
afmt.Printf("> Recv: %s, Paid %s, %s (%s)\n",
|
||||||
types.SizeStr(types.NewInt(evt.BytesReceived)),
|
types.SizeStr(types.NewInt(evt.BytesReceived)),
|
||||||
types.FIL(evt.FundsSpent),
|
types.FIL(evt.FundsSpent),
|
||||||
retrievalmarket.ClientEvents[evt.Event],
|
retrievalmarket.ClientEvents[evt.Event],
|
||||||
retrievalmarket.DealStatuses[evt.Status],
|
retrievalmarket.DealStatuses[evt.Status],
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Success")
|
afmt.Println("Success")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1269,8 +1272,9 @@ var clientQueryAskCmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
|
afmt := NewAppFmt(cctx.App)
|
||||||
if cctx.NArg() != 1 {
|
if cctx.NArg() != 1 {
|
||||||
fmt.Println("Usage: query-ask [minerAddress]")
|
afmt.Println("Usage: query-ask [minerAddress]")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1311,23 +1315,23 @@ var clientQueryAskCmd = &cli.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Ask: %s\n", maddr)
|
afmt.Printf("Ask: %s\n", maddr)
|
||||||
fmt.Printf("Price per GiB: %s\n", types.FIL(ask.Price))
|
afmt.Printf("Price per GiB: %s\n", types.FIL(ask.Price))
|
||||||
fmt.Printf("Verified Price per GiB: %s\n", types.FIL(ask.VerifiedPrice))
|
afmt.Printf("Verified Price per GiB: %s\n", types.FIL(ask.VerifiedPrice))
|
||||||
fmt.Printf("Max Piece size: %s\n", types.SizeStr(types.NewInt(uint64(ask.MaxPieceSize))))
|
afmt.Printf("Max Piece size: %s\n", types.SizeStr(types.NewInt(uint64(ask.MaxPieceSize))))
|
||||||
|
|
||||||
size := cctx.Int64("size")
|
size := cctx.Int64("size")
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
perEpoch := types.BigDiv(types.BigMul(ask.Price, types.NewInt(uint64(size))), types.NewInt(1<<30))
|
perEpoch := types.BigDiv(types.BigMul(ask.Price, types.NewInt(uint64(size))), types.NewInt(1<<30))
|
||||||
fmt.Printf("Price per Block: %s\n", types.FIL(perEpoch))
|
afmt.Printf("Price per Block: %s\n", types.FIL(perEpoch))
|
||||||
|
|
||||||
duration := cctx.Int64("duration")
|
duration := cctx.Int64("duration")
|
||||||
if duration == 0 {
|
if duration == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
fmt.Printf("Total Price: %s\n", types.FIL(types.BigMul(perEpoch, types.NewInt(uint64(duration)))))
|
afmt.Printf("Total Price: %s\n", types.FIL(types.BigMul(perEpoch, types.NewInt(uint64(duration)))))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
@ -1410,7 +1414,7 @@ var clientListDeals = &cli.Command{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return outputStorageDeals(ctx, os.Stdout, api, localDeals, cctx.Bool("verbose"), cctx.Bool("color"), showFailed)
|
return outputStorageDeals(ctx, cctx.App.Writer, api, localDeals, cctx.Bool("verbose"), cctx.Bool("color"), showFailed)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
cli/client_test.go
Normal file
22
cli/client_test.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
clitest "github.com/filecoin-project/lotus/cli/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestClient does a basic test to exercise the client CLI
|
||||||
|
// commands
|
||||||
|
func TestClient(t *testing.T) {
|
||||||
|
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
|
clitest.QuietMiningLogs()
|
||||||
|
|
||||||
|
blocktime := 5 * time.Millisecond
|
||||||
|
ctx := context.Background()
|
||||||
|
clientNode, _ := clitest.StartOneNodeOneMiner(ctx, t, blocktime)
|
||||||
|
clitest.RunClientTest(t, Commands, clientNode)
|
||||||
|
}
|
@ -2,15 +2,16 @@ package cli
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
ufcli "github.com/urfave/cli/v2"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PrintHelpErr struct {
|
type PrintHelpErr struct {
|
||||||
Err error
|
Err error
|
||||||
Ctx *cli.Context
|
Ctx *ufcli.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *PrintHelpErr) Error() string {
|
func (e *PrintHelpErr) Error() string {
|
||||||
@ -26,11 +27,11 @@ func (e *PrintHelpErr) Is(o error) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func ShowHelp(cctx *cli.Context, err error) error {
|
func ShowHelp(cctx *ufcli.Context, err error) error {
|
||||||
return &PrintHelpErr{Err: err, Ctx: cctx}
|
return &PrintHelpErr{Err: err, Ctx: cctx}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunApp(app *cli.App) {
|
func RunApp(app *ufcli.App) {
|
||||||
if err := app.Run(os.Args); err != nil {
|
if err := app.Run(os.Args); err != nil {
|
||||||
if os.Getenv("LOTUS_DEV") != "" {
|
if os.Getenv("LOTUS_DEV") != "" {
|
||||||
log.Warnf("%+v", err)
|
log.Warnf("%+v", err)
|
||||||
@ -39,8 +40,40 @@ func RunApp(app *cli.App) {
|
|||||||
}
|
}
|
||||||
var phe *PrintHelpErr
|
var phe *PrintHelpErr
|
||||||
if xerrors.As(err, &phe) {
|
if xerrors.As(err, &phe) {
|
||||||
_ = cli.ShowCommandHelp(phe.Ctx, phe.Ctx.Command.Name)
|
_ = ufcli.ShowCommandHelp(phe.Ctx, phe.Ctx.Command.Name)
|
||||||
}
|
}
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AppFmt struct {
|
||||||
|
app *ufcli.App
|
||||||
|
Stdin io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAppFmt(a *ufcli.App) *AppFmt {
|
||||||
|
var stdin io.Reader
|
||||||
|
istdin, ok := a.Metadata["stdin"]
|
||||||
|
if ok {
|
||||||
|
stdin = istdin.(io.Reader)
|
||||||
|
} else {
|
||||||
|
stdin = os.Stdin
|
||||||
|
}
|
||||||
|
return &AppFmt{app: a, Stdin: stdin}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppFmt) Print(args ...interface{}) {
|
||||||
|
fmt.Fprint(a.app.Writer, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppFmt) Println(args ...interface{}) {
|
||||||
|
fmt.Fprintln(a.app.Writer, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppFmt) Printf(fmtstr string, args ...interface{}) {
|
||||||
|
fmt.Fprintf(a.app.Writer, fmtstr, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppFmt) Scan(args ...interface{}) (int, error) {
|
||||||
|
return fmt.Fscan(a.Stdin, args...)
|
||||||
|
}
|
||||||
|
@ -6,50 +6,17 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/lotus/api/test"
|
|
||||||
clitest "github.com/filecoin-project/lotus/cli/test"
|
clitest "github.com/filecoin-project/lotus/cli/test"
|
||||||
builder "github.com/filecoin-project/lotus/node/test"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestMultisig does a basic test to exercise the multisig CLI
|
// TestMultisig does a basic test to exercise the multisig CLI
|
||||||
// commands
|
// commands
|
||||||
func TestMultisig(t *testing.T) {
|
func TestMultisig(t *testing.T) {
|
||||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
|
clitest.QuietMiningLogs()
|
||||||
|
|
||||||
blocktime := 5 * time.Millisecond
|
blocktime := 5 * time.Millisecond
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
nodes, _ := startNodes(ctx, t, blocktime)
|
clientNode, _ := clitest.StartOneNodeOneMiner(ctx, t, blocktime)
|
||||||
clientNode := nodes[0]
|
|
||||||
clitest.RunMultisigTest(t, Commands, clientNode)
|
clitest.RunMultisigTest(t, Commands, clientNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration) ([]test.TestNode, []address.Address) {
|
|
||||||
n, sn := builder.RPCMockSbBuilder(t, test.OneFull, test.OneMiner)
|
|
||||||
|
|
||||||
full := n[0]
|
|
||||||
miner := sn[0]
|
|
||||||
|
|
||||||
// Get everyone connected
|
|
||||||
addrs, err := full.NetAddrsListen(ctx)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := miner.NetConnect(ctx, addrs); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start mining blocks
|
|
||||||
bm := test.NewBlockMiner(ctx, t, miner, blocktime)
|
|
||||||
bm.MineBlocks()
|
|
||||||
|
|
||||||
// Get the creator's address
|
|
||||||
creatorAddr, err := full.WalletDefaultAddress(ctx)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create mock CLI
|
|
||||||
return n, []address.Address{creatorAddr}
|
|
||||||
}
|
|
||||||
|
115
cli/test/client.go
Normal file
115
cli/test/client.go
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/api/test"
|
||||||
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
lcli "github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RunClientTest exercises some of the client CLI commands
|
||||||
|
func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// Create mock CLI
|
||||||
|
mockCLI := newMockCLI(t, cmds)
|
||||||
|
clientCLI := mockCLI.client(clientNode.ListenAddr)
|
||||||
|
|
||||||
|
// Get the miner address
|
||||||
|
addrs, err := clientNode.StateListMiners(ctx, types.EmptyTSK)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, addrs, 1)
|
||||||
|
|
||||||
|
minerAddr := addrs[0]
|
||||||
|
fmt.Println("Miner:", minerAddr)
|
||||||
|
|
||||||
|
// client query-ask <miner addr>
|
||||||
|
cmd := []string{
|
||||||
|
"client", "query-ask", minerAddr.String(),
|
||||||
|
}
|
||||||
|
out := clientCLI.runCmd(cmd)
|
||||||
|
require.Regexp(t, regexp.MustCompile("Ask:"), out)
|
||||||
|
|
||||||
|
// Create a deal (non-interactive)
|
||||||
|
// client deal <cid> <miner addr> 1000000attofil <duration>
|
||||||
|
res, _, err := test.CreateClientFile(ctx, clientNode, 1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
dataCid := res.Root
|
||||||
|
price := "1000000attofil"
|
||||||
|
duration := fmt.Sprintf("%d", build.MinDealDuration)
|
||||||
|
cmd = []string{
|
||||||
|
"client", "deal", dataCid.String(), minerAddr.String(), price, duration,
|
||||||
|
}
|
||||||
|
out = clientCLI.runCmd(cmd)
|
||||||
|
fmt.Println("client deal", out)
|
||||||
|
|
||||||
|
// Create a deal (interactive)
|
||||||
|
// client deal
|
||||||
|
// <cid>
|
||||||
|
// <duration> (in days)
|
||||||
|
// <miner addr>
|
||||||
|
// "no" (verified client)
|
||||||
|
// "yes" (confirm deal)
|
||||||
|
res, _, err = test.CreateClientFile(ctx, clientNode, 2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
dataCid2 := res.Root
|
||||||
|
duration = fmt.Sprintf("%d", build.MinDealDuration/builtin.EpochsInDay)
|
||||||
|
cmd = []string{
|
||||||
|
"client", "deal",
|
||||||
|
}
|
||||||
|
interactiveCmds := []string{
|
||||||
|
dataCid2.String(),
|
||||||
|
duration,
|
||||||
|
minerAddr.String(),
|
||||||
|
"no",
|
||||||
|
"yes",
|
||||||
|
}
|
||||||
|
out = clientCLI.runInteractiveCmd(cmd, interactiveCmds)
|
||||||
|
fmt.Println("client deal:\n", out)
|
||||||
|
|
||||||
|
// Wait for provider to start sealing deal
|
||||||
|
dealStatus := ""
|
||||||
|
for dealStatus != "StorageDealSealing" {
|
||||||
|
// client list-deals
|
||||||
|
cmd = []string{"client", "list-deals"}
|
||||||
|
out = clientCLI.runCmd(cmd)
|
||||||
|
fmt.Println("list-deals:\n", out)
|
||||||
|
|
||||||
|
lines := strings.Split(out, "\n")
|
||||||
|
require.Len(t, lines, 2)
|
||||||
|
re := regexp.MustCompile(`\s+`)
|
||||||
|
parts := re.Split(lines[1], -1)
|
||||||
|
if len(parts) < 4 {
|
||||||
|
require.Fail(t, "bad list-deals output format")
|
||||||
|
}
|
||||||
|
dealStatus = parts[3]
|
||||||
|
fmt.Println(" Deal status:", dealStatus)
|
||||||
|
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the first file from the miner
|
||||||
|
// client retrieve <cid> <file path>
|
||||||
|
tmpdir, err := ioutil.TempDir(os.TempDir(), "test-cli-client")
|
||||||
|
require.NoError(t, err)
|
||||||
|
path := filepath.Join(tmpdir, "outfile.dat")
|
||||||
|
cmd = []string{
|
||||||
|
"client", "retrieve", dataCid.String(), path,
|
||||||
|
}
|
||||||
|
out = clientCLI.runCmd(cmd)
|
||||||
|
fmt.Println("retrieve:\n", out)
|
||||||
|
require.Regexp(t, regexp.MustCompile("Success"), out)
|
||||||
|
}
|
@ -122,3 +122,12 @@ func (c *mockCLIClient) flagSet(cmd *lcli.Command) *flag.FlagSet {
|
|||||||
}
|
}
|
||||||
return fs
|
return fs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *mockCLIClient) runInteractiveCmd(cmd []string, interactive []string) string {
|
||||||
|
c.toStdin(strings.Join(interactive, "\n") + "\n")
|
||||||
|
return c.runCmd(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mockCLIClient) toStdin(s string) {
|
||||||
|
c.cctx.App.Metadata["stdin"] = bytes.NewBufferString(s)
|
||||||
|
}
|
||||||
|
@ -10,19 +10,10 @@ import (
|
|||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/lotus/api/test"
|
"github.com/filecoin-project/lotus/api/test"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
logging "github.com/ipfs/go-log/v2"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
lcli "github.com/urfave/cli/v2"
|
lcli "github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func QuietMiningLogs() {
|
|
||||||
logging.SetLogLevel("miner", "ERROR")
|
|
||||||
logging.SetLogLevel("chainstore", "ERROR")
|
|
||||||
logging.SetLogLevel("chain", "ERROR")
|
|
||||||
logging.SetLogLevel("sub", "ERROR")
|
|
||||||
logging.SetLogLevel("storageminer", "ERROR")
|
|
||||||
}
|
|
||||||
|
|
||||||
func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) {
|
func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
41
cli/test/net.go
Normal file
41
cli/test/net.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/lotus/api/test"
|
||||||
|
test2 "github.com/filecoin-project/lotus/node/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StartOneNodeOneMiner(ctx context.Context, t *testing.T, blocktime time.Duration) (test.TestNode, address.Address) {
|
||||||
|
n, sn := test2.RPCMockSbBuilder(t, test.OneFull, test.OneMiner)
|
||||||
|
|
||||||
|
full := n[0]
|
||||||
|
miner := sn[0]
|
||||||
|
|
||||||
|
// Get everyone connected
|
||||||
|
addrs, err := full.NetAddrsListen(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := miner.NetConnect(ctx, addrs); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start mining blocks
|
||||||
|
bm := test.NewBlockMiner(ctx, t, miner, blocktime)
|
||||||
|
bm.MineBlocks()
|
||||||
|
|
||||||
|
// Get the full node's wallet address
|
||||||
|
fullAddr, err := full.WalletDefaultAddress(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create mock CLI
|
||||||
|
return full, fullAddr
|
||||||
|
}
|
12
cli/test/util.go
Normal file
12
cli/test/util.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import "github.com/ipfs/go-log/v2"
|
||||||
|
|
||||||
|
func QuietMiningLogs() {
|
||||||
|
_ = log.SetLogLevel("miner", "ERROR")
|
||||||
|
_ = log.SetLogLevel("chainstore", "ERROR")
|
||||||
|
_ = log.SetLogLevel("chain", "ERROR")
|
||||||
|
_ = log.SetLogLevel("sub", "ERROR")
|
||||||
|
_ = log.SetLogLevel("storageminer", "ERROR")
|
||||||
|
_ = log.SetLogLevel("pubsub", "ERROR")
|
||||||
|
}
|
@ -24,7 +24,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
LookbackCap = time.Hour * 24
|
LookbackCap = time.Hour * 24
|
||||||
stateWaitLookbackLimit = abi.ChainEpoch(20)
|
StateWaitLookbackLimit = abi.ChainEpoch(20)
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -35,20 +35,28 @@ var (
|
|||||||
// (to make it easy to mock for tests)
|
// (to make it easy to mock for tests)
|
||||||
type gatewayDepsAPI interface {
|
type gatewayDepsAPI interface {
|
||||||
Version(context.Context) (api.Version, error)
|
Version(context.Context) (api.Version, error)
|
||||||
|
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
|
||||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error)
|
||||||
ChainHead(ctx context.Context) (*types.TipSet, error)
|
ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error)
|
||||||
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
|
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||||
|
ChainHead(ctx context.Context) (*types.TipSet, error)
|
||||||
|
ChainNotify(context.Context) (<-chan []*api.HeadChange, error)
|
||||||
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||||
ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error)
|
|
||||||
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||||
MpoolPushUntrusted(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
MpoolPushUntrusted(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||||
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||||
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
||||||
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||||
|
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error)
|
||||||
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
||||||
|
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
|
||||||
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||||
|
StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
|
||||||
|
StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error)
|
||||||
|
StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error)
|
||||||
|
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
|
||||||
StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error)
|
StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error)
|
||||||
StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error)
|
StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error)
|
||||||
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error)
|
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error)
|
||||||
@ -59,23 +67,24 @@ type gatewayDepsAPI interface {
|
|||||||
StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
|
StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
|
||||||
StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error)
|
StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error)
|
||||||
StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error)
|
StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error)
|
||||||
|
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
|
||||||
StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error)
|
StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error)
|
||||||
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type GatewayAPI struct {
|
type GatewayAPI struct {
|
||||||
api gatewayDepsAPI
|
api gatewayDepsAPI
|
||||||
lookbackCap time.Duration
|
lookbackCap time.Duration
|
||||||
|
stateWaitLookbackLimit abi.ChainEpoch
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGatewayAPI creates a new GatewayAPI with the default lookback cap
|
// NewGatewayAPI creates a new GatewayAPI with the default lookback cap
|
||||||
func NewGatewayAPI(api gatewayDepsAPI) *GatewayAPI {
|
func NewGatewayAPI(api gatewayDepsAPI) *GatewayAPI {
|
||||||
return newGatewayAPI(api, LookbackCap)
|
return newGatewayAPI(api, LookbackCap, StateWaitLookbackLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
// used by the tests
|
// used by the tests
|
||||||
func newGatewayAPI(api gatewayDepsAPI, lookbackCap time.Duration) *GatewayAPI {
|
func newGatewayAPI(api gatewayDepsAPI, lookbackCap time.Duration, stateWaitLookbackLimit abi.ChainEpoch) *GatewayAPI {
|
||||||
return &GatewayAPI{api: api, lookbackCap: lookbackCap}
|
return &GatewayAPI{api: api, lookbackCap: lookbackCap, stateWaitLookbackLimit: stateWaitLookbackLimit}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) checkTipsetKey(ctx context.Context, tsk types.TipSetKey) error {
|
func (a *GatewayAPI) checkTipsetKey(ctx context.Context, tsk types.TipSetKey) error {
|
||||||
@ -122,6 +131,10 @@ func (a *GatewayAPI) Version(ctx context.Context) (api.Version, error) {
|
|||||||
return a.api.Version(ctx)
|
return a.api.Version(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) ChainGetBlockMessages(ctx context.Context, c cid.Cid) (*api.BlockMessages, error) {
|
||||||
|
return a.api.ChainGetBlockMessages(ctx, c)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) {
|
func (a *GatewayAPI) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) {
|
||||||
return a.api.ChainHasObj(ctx, c)
|
return a.api.ChainHasObj(ctx, c)
|
||||||
}
|
}
|
||||||
@ -132,6 +145,10 @@ func (a *GatewayAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
|||||||
return a.api.ChainHead(ctx)
|
return a.api.ChainHead(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
|
||||||
|
return a.api.ChainGetMessage(ctx, mc)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
|
func (a *GatewayAPI) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||||
return a.api.ChainGetTipSet(ctx, tsk)
|
return a.api.ChainGetTipSet(ctx, tsk)
|
||||||
}
|
}
|
||||||
@ -165,14 +182,18 @@ func (a *GatewayAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoc
|
|||||||
return a.api.ChainGetTipSetByHeight(ctx, h, tsk)
|
return a.api.ChainGetTipSetByHeight(ctx, h, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
|
|
||||||
return a.api.ChainReadObj(ctx, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *GatewayAPI) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) {
|
func (a *GatewayAPI) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) {
|
||||||
return a.api.ChainGetNode(ctx, p)
|
return a.api.ChainGetNode(ctx, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) {
|
||||||
|
return a.api.ChainNotify(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
|
||||||
|
return a.api.ChainReadObj(ctx, c)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
func (a *GatewayAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
||||||
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -213,6 +234,14 @@ func (a *GatewayAPI) StateAccountKey(ctx context.Context, addr address.Address,
|
|||||||
return a.api.StateAccountKey(ctx, addr, tsk)
|
return a.api.StateAccountKey(ctx, addr, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return api.DealCollateralBounds{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.api.StateDealProviderCollateralBounds(ctx, size, verified, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
|
func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
|
||||||
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -221,6 +250,22 @@ func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, t
|
|||||||
return a.api.StateGetActor(ctx, actor, tsk)
|
return a.api.StateGetActor(ctx, actor, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateGetReceipt(ctx context.Context, c cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.api.StateGetReceipt(ctx, c, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.api.StateListMiners(ctx, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
func (a *GatewayAPI) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
|
||||||
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
return address.Undef, err
|
return address.Undef, err
|
||||||
@ -229,8 +274,32 @@ func (a *GatewayAPI) StateLookupID(ctx context.Context, addr address.Address, ts
|
|||||||
return a.api.StateLookupID(ctx, addr, tsk)
|
return a.api.StateLookupID(ctx, addr, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return api.MarketBalance{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.api.StateMarketBalance(ctx, addr, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.api.StateMarketStorageDeal(ctx, dealId, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return network.VersionMax, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.api.StateNetworkVersion(ctx, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
|
func (a *GatewayAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
|
||||||
return a.api.StateWaitMsgLimited(ctx, msg, confidence, stateWaitLookbackLimit)
|
return a.api.StateWaitMsgLimited(ctx, msg, confidence, a.stateWaitLookbackLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) {
|
func (a *GatewayAPI) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) {
|
||||||
@ -296,6 +365,13 @@ func (a *GatewayAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSe
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return a.api.StateVerifiedClientStatus(ctx, addr, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
|
func (a *GatewayAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
|
||||||
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
return api.CirculatingSupply{}, err
|
return api.CirculatingSupply{}, err
|
||||||
@ -303,13 +379,6 @@ func (a *GatewayAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk t
|
|||||||
return a.api.StateVMCirculatingSupplyInternal(ctx, tsk)
|
return a.api.StateVMCirculatingSupplyInternal(ctx, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) {
|
|
||||||
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return a.api.StateNetworkVersion(ctx, tsk)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) {
|
func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) {
|
||||||
return sigs.Verify(sig, k, msg) == nil, nil
|
return sigs.Verify(sig, k, msg) == nil, nil
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -116,6 +119,38 @@ func (m *mockGatewayDepsAPI) ChainHasObj(context.Context, cid.Cid) (bool, error)
|
|||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *mockGatewayDepsAPI) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockGatewayDepsAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockGatewayDepsAPI) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockGatewayDepsAPI) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockGatewayDepsAPI) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockGatewayDepsAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockGatewayDepsAPI) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockGatewayDepsAPI) StateNetworkVersion(ctx context.Context, key types.TipSetKey) (network.Version, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
func (m *mockGatewayDepsAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
func (m *mockGatewayDepsAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||||
m.lk.RLock()
|
m.lk.RLock()
|
||||||
defer m.lk.RUnlock()
|
defer m.lk.RUnlock()
|
||||||
@ -165,10 +200,6 @@ func (m *mockGatewayDepsAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.C
|
|||||||
return m.tipsets[h], nil
|
return m.tipsets[h], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockGatewayDepsAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockGatewayDepsAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
func (m *mockGatewayDepsAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,14 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/api/client"
|
"github.com/filecoin-project/lotus/api/client"
|
||||||
"github.com/filecoin-project/lotus/api/test"
|
"github.com/filecoin-project/lotus/api/test"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||||
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/node"
|
"github.com/filecoin-project/lotus/node"
|
||||||
builder "github.com/filecoin-project/lotus/node/test"
|
builder "github.com/filecoin-project/lotus/node/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
const maxLookbackCap = time.Duration(math.MaxInt64)
|
const maxLookbackCap = time.Duration(math.MaxInt64)
|
||||||
|
const maxStateWaitLookbackLimit = stmgr.LookbackNoLimit
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
|
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
|
||||||
@ -38,15 +40,19 @@ func init() {
|
|||||||
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
|
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestEndToEndWalletMsig tests that wallet and msig API calls can be made
|
// TestWalletMsig tests that API calls to wallet and msig can be made on a lite
|
||||||
// on a lite node that is connected through a gateway to a full API node
|
// node that is connected through a gateway to a full API node
|
||||||
func TestEndToEndWalletMsig(t *testing.T) {
|
func TestWalletMsig(t *testing.T) {
|
||||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
|
clitest.QuietMiningLogs()
|
||||||
|
|
||||||
blocktime := 5 * time.Millisecond
|
blocktime := 5 * time.Millisecond
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
full, lite, closer := startNodes(ctx, t, blocktime, maxLookbackCap)
|
nodes := startNodes(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit)
|
||||||
defer closer()
|
defer nodes.closer()
|
||||||
|
|
||||||
|
lite := nodes.lite
|
||||||
|
full := nodes.full
|
||||||
|
|
||||||
// The full node starts with a wallet
|
// The full node starts with a wallet
|
||||||
fullWalletAddr, err := full.WalletDefaultAddress(ctx)
|
fullWalletAddr, err := full.WalletDefaultAddress(ctx)
|
||||||
@ -141,56 +147,83 @@ func TestEndToEndWalletMsig(t *testing.T) {
|
|||||||
require.True(t, approveReturn.Applied)
|
require.True(t, approveReturn.Applied)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestEndToEndMsigCLI tests that msig CLI calls can be made
|
// TestMsigCLI tests that msig CLI calls can be made
|
||||||
// on a lite node that is connected through a gateway to a full API node
|
// on a lite node that is connected through a gateway to a full API node
|
||||||
func TestEndToEndMsigCLI(t *testing.T) {
|
func TestMsigCLI(t *testing.T) {
|
||||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
clitest.QuietMiningLogs()
|
clitest.QuietMiningLogs()
|
||||||
|
|
||||||
blocktime := 5 * time.Millisecond
|
blocktime := 5 * time.Millisecond
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
full, lite, closer := startNodes(ctx, t, blocktime, maxLookbackCap)
|
nodes := startNodesWithFunds(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit)
|
||||||
defer closer()
|
defer nodes.closer()
|
||||||
|
|
||||||
// The full node starts with a wallet
|
|
||||||
fullWalletAddr, err := full.WalletDefaultAddress(ctx)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Create a wallet on the lite node
|
|
||||||
liteWalletAddr, err := lite.WalletNew(ctx, types.KTSecp256k1)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Send some funds from the full node to the lite node
|
|
||||||
err = sendFunds(ctx, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18))
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
|
lite := nodes.lite
|
||||||
clitest.RunMultisigTest(t, cli.Commands, lite)
|
clitest.RunMultisigTest(t, cli.Commands, lite)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendFunds(ctx context.Context, fromNode test.TestNode, fromAddr address.Address, toAddr address.Address, amt types.BigInt) error {
|
func TestDealFlow(t *testing.T) {
|
||||||
msg := &types.Message{
|
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
From: fromAddr,
|
clitest.QuietMiningLogs()
|
||||||
To: toAddr,
|
|
||||||
Value: amt,
|
blocktime := 5 * time.Millisecond
|
||||||
|
ctx := context.Background()
|
||||||
|
nodes := startNodesWithFunds(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit)
|
||||||
|
defer nodes.closer()
|
||||||
|
|
||||||
|
test.MakeDeal(t, ctx, 6, nodes.lite, nodes.miner, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
sm, err := fromNode.MpoolPushMessage(ctx, msg, nil)
|
func TestCLIDealFlow(t *testing.T) {
|
||||||
if err != nil {
|
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
return err
|
clitest.QuietMiningLogs()
|
||||||
|
|
||||||
|
blocktime := 5 * time.Millisecond
|
||||||
|
ctx := context.Background()
|
||||||
|
nodes := startNodesWithFunds(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit)
|
||||||
|
defer nodes.closer()
|
||||||
|
|
||||||
|
clitest.RunClientTest(t, cli.Commands, nodes.lite)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := fromNode.StateWaitMsg(ctx, sm.Cid(), 1)
|
type testNodes struct {
|
||||||
if err != nil {
|
lite test.TestNode
|
||||||
return err
|
full test.TestNode
|
||||||
}
|
miner test.TestStorageNode
|
||||||
if res.Receipt.ExitCode != 0 {
|
closer jsonrpc.ClientCloser
|
||||||
return xerrors.Errorf("send funds failed with exit code %d", res.Receipt.ExitCode)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
func startNodesWithFunds(
|
||||||
|
ctx context.Context,
|
||||||
|
t *testing.T,
|
||||||
|
blocktime time.Duration,
|
||||||
|
lookbackCap time.Duration,
|
||||||
|
stateWaitLookbackLimit abi.ChainEpoch,
|
||||||
|
) *testNodes {
|
||||||
|
nodes := startNodes(ctx, t, blocktime, lookbackCap, stateWaitLookbackLimit)
|
||||||
|
|
||||||
|
// The full node starts with a wallet
|
||||||
|
fullWalletAddr, err := nodes.full.WalletDefaultAddress(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Create a wallet on the lite node
|
||||||
|
liteWalletAddr, err := nodes.lite.WalletNew(ctx, types.KTSecp256k1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Send some funds from the full node to the lite node
|
||||||
|
err = sendFunds(ctx, nodes.full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration, lookbackCap time.Duration) (test.TestNode, test.TestNode, jsonrpc.ClientCloser) {
|
func startNodes(
|
||||||
|
ctx context.Context,
|
||||||
|
t *testing.T,
|
||||||
|
blocktime time.Duration,
|
||||||
|
lookbackCap time.Duration,
|
||||||
|
stateWaitLookbackLimit abi.ChainEpoch,
|
||||||
|
) *testNodes {
|
||||||
var closer jsonrpc.ClientCloser
|
var closer jsonrpc.ClientCloser
|
||||||
|
|
||||||
// Create one miner and two full nodes.
|
// Create one miner and two full nodes.
|
||||||
@ -207,7 +240,8 @@ func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration, look
|
|||||||
fullNode := nodes[0]
|
fullNode := nodes[0]
|
||||||
|
|
||||||
// Create a gateway server in front of the full node
|
// Create a gateway server in front of the full node
|
||||||
_, addr, err := builder.CreateRPCServer(newGatewayAPI(fullNode, lookbackCap))
|
gapiImpl := newGatewayAPI(fullNode, lookbackCap, stateWaitLookbackLimit)
|
||||||
|
_, addr, err := builder.CreateRPCServer(gapiImpl)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Create a gateway client API that connects to the gateway server
|
// Create a gateway client API that connects to the gateway server
|
||||||
@ -234,9 +268,39 @@ func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration, look
|
|||||||
err = miner.NetConnect(ctx, fullAddr)
|
err = miner.NetConnect(ctx, fullAddr)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Connect the miner and the lite node (so that the lite node can send
|
||||||
|
// data to the miner)
|
||||||
|
liteAddr, err := lite.NetAddrsListen(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = miner.NetConnect(ctx, liteAddr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Start mining blocks
|
// Start mining blocks
|
||||||
bm := test.NewBlockMiner(ctx, t, miner, blocktime)
|
bm := test.NewBlockMiner(ctx, t, miner, blocktime)
|
||||||
bm.MineBlocks()
|
bm.MineBlocks()
|
||||||
|
|
||||||
return full, lite, closer
|
return &testNodes{lite: lite, full: full, miner: miner, closer: closer}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendFunds(ctx context.Context, 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
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,6 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/events"
|
"github.com/filecoin-project/lotus/chain/events"
|
||||||
"github.com/filecoin-project/lotus/chain/events/state"
|
"github.com/filecoin-project/lotus/chain/events/state"
|
||||||
"github.com/filecoin-project/lotus/chain/market"
|
"github.com/filecoin-project/lotus/chain/market"
|
||||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
|
||||||
"github.com/filecoin-project/lotus/chain/store"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/lib/sigs"
|
"github.com/filecoin-project/lotus/lib/sigs"
|
||||||
"github.com/filecoin-project/lotus/markets/utils"
|
"github.com/filecoin-project/lotus/markets/utils"
|
||||||
@ -40,8 +38,6 @@ type ClientNodeAdapter struct {
|
|||||||
full.ChainAPI
|
full.ChainAPI
|
||||||
full.MpoolAPI
|
full.MpoolAPI
|
||||||
|
|
||||||
sm *stmgr.StateManager
|
|
||||||
cs *store.ChainStore
|
|
||||||
fm *market.FundMgr
|
fm *market.FundMgr
|
||||||
ev *events.Events
|
ev *events.Events
|
||||||
}
|
}
|
||||||
@ -51,14 +47,12 @@ type clientApi struct {
|
|||||||
full.StateAPI
|
full.StateAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientNodeAdapter(state full.StateAPI, chain full.ChainAPI, mpool full.MpoolAPI, sm *stmgr.StateManager, cs *store.ChainStore, fm *market.FundMgr) storagemarket.StorageClientNode {
|
func NewClientNodeAdapter(state full.StateAPI, chain full.ChainAPI, mpool full.MpoolAPI, fm *market.FundMgr) storagemarket.StorageClientNode {
|
||||||
return &ClientNodeAdapter{
|
return &ClientNodeAdapter{
|
||||||
StateAPI: state,
|
StateAPI: state,
|
||||||
ChainAPI: chain,
|
ChainAPI: chain,
|
||||||
MpoolAPI: mpool,
|
MpoolAPI: mpool,
|
||||||
|
|
||||||
sm: sm,
|
|
||||||
cs: cs,
|
|
||||||
fm: fm,
|
fm: fm,
|
||||||
ev: events.NewEvents(context.TODO(), &clientApi{chain, state}),
|
ev: events.NewEvents(context.TODO(), &clientApi{chain, state}),
|
||||||
}
|
}
|
||||||
@ -138,12 +132,12 @@ func (c *ClientNodeAdapter) GetBalance(ctx context.Context, addr address.Address
|
|||||||
func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal storagemarket.ClientDeal) (abi.DealID, error) {
|
func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal storagemarket.ClientDeal) (abi.DealID, error) {
|
||||||
log.Infow("DEAL ACCEPTED!")
|
log.Infow("DEAL ACCEPTED!")
|
||||||
|
|
||||||
pubmsg, err := c.cs.GetMessage(*deal.PublishMessage)
|
pubmsg, err := c.ChainGetMessage(ctx, *deal.PublishMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, xerrors.Errorf("getting deal publish message: %w", err)
|
return 0, xerrors.Errorf("getting deal publish message: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mi, err := stmgr.StateMinerInfo(ctx, c.sm, c.cs.GetHeaviestTipSet(), deal.Proposal.Provider)
|
mi, err := c.StateMinerInfo(ctx, deal.Proposal.Provider, types.EmptyTSK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, xerrors.Errorf("getting miner worker failed: %w", err)
|
return 0, xerrors.Errorf("getting miner worker failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -189,16 +183,16 @@ func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal stor
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: timeout
|
// TODO: timeout
|
||||||
_, ret, _, err := c.sm.WaitForMessage(ctx, *deal.PublishMessage, build.MessageConfidence, stmgr.LookbackNoLimit)
|
ret, err := c.StateWaitMsg(ctx, *deal.PublishMessage, build.MessageConfidence)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, xerrors.Errorf("waiting for deal publish message: %w", err)
|
return 0, xerrors.Errorf("waiting for deal publish message: %w", err)
|
||||||
}
|
}
|
||||||
if ret.ExitCode != 0 {
|
if ret.Receipt.ExitCode != 0 {
|
||||||
return 0, xerrors.Errorf("deal publish failed: exit=%d", ret.ExitCode)
|
return 0, xerrors.Errorf("deal publish failed: exit=%d", ret.Receipt.ExitCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
var res market2.PublishStorageDealsReturn
|
var res market2.PublishStorageDealsReturn
|
||||||
if err := res.UnmarshalCBOR(bytes.NewReader(ret.Return)); err != nil {
|
if err := res.UnmarshalCBOR(bytes.NewReader(ret.Receipt.Return)); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +212,7 @@ func (c *ClientNodeAdapter) DealProviderCollateralBounds(ctx context.Context, si
|
|||||||
|
|
||||||
func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider address.Address, dealId abi.DealID, cb storagemarket.DealSectorCommittedCallback) error {
|
func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider address.Address, dealId abi.DealID, cb storagemarket.DealSectorCommittedCallback) error {
|
||||||
checkFunc := func(ts *types.TipSet) (done bool, more bool, err error) {
|
checkFunc := func(ts *types.TipSet) (done bool, more bool, err error) {
|
||||||
sd, err := stmgr.GetStorageDeal(ctx, c.StateManager, dealId, ts)
|
sd, err := c.StateMarketStorageDeal(ctx, dealId, ts.Key())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: This may be fine for some errors
|
// TODO: This may be fine for some errors
|
||||||
@ -245,7 +239,7 @@ func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sd, err := stmgr.GetStorageDeal(ctx, c.StateManager, dealId, ts)
|
sd, err := c.StateMarketStorageDeal(ctx, dealId, ts.Key())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, xerrors.Errorf("failed to look up deal on chain: %w", err)
|
return false, xerrors.Errorf("failed to look up deal on chain: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -250,7 +250,6 @@ func Online() Option {
|
|||||||
Override(new(*store.ChainStore), modules.ChainStore),
|
Override(new(*store.ChainStore), modules.ChainStore),
|
||||||
Override(new(stmgr.UpgradeSchedule), stmgr.DefaultUpgradeSchedule()),
|
Override(new(stmgr.UpgradeSchedule), stmgr.DefaultUpgradeSchedule()),
|
||||||
Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule),
|
Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule),
|
||||||
Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))),
|
|
||||||
Override(new(*wallet.LocalWallet), wallet.NewWallet),
|
Override(new(*wallet.LocalWallet), wallet.NewWallet),
|
||||||
Override(new(wallet.Default), From(new(*wallet.LocalWallet))),
|
Override(new(wallet.Default), From(new(*wallet.LocalWallet))),
|
||||||
Override(new(api.WalletAPI), From(new(wallet.MultiWallet))),
|
Override(new(api.WalletAPI), From(new(wallet.MultiWallet))),
|
||||||
|
@ -65,9 +65,9 @@ type API struct {
|
|||||||
fx.In
|
fx.In
|
||||||
|
|
||||||
full.ChainAPI
|
full.ChainAPI
|
||||||
full.StateAPI
|
|
||||||
full.WalletAPI
|
full.WalletAPI
|
||||||
paych.PaychAPI
|
paych.PaychAPI
|
||||||
|
full.StateAPI
|
||||||
|
|
||||||
SMDealClient storagemarket.StorageClient
|
SMDealClient storagemarket.StorageClient
|
||||||
RetDiscovery discovery.PeerResolver
|
RetDiscovery discovery.PeerResolver
|
||||||
@ -117,7 +117,7 @@ func (a *API) ClientStartDeal(ctx context.Context, params *api.StartDealParams)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
walletKey, err := a.StateAPI.StateManager.ResolveToKeyAddress(ctx, params.Wallet, nil)
|
walletKey, err := a.StateAccountKey(ctx, params.Wallet, types.EmptyTSK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed resolving params.Wallet addr: %w", params.Wallet)
|
return nil, xerrors.Errorf("failed resolving params.Wallet addr: %w", params.Wallet)
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,11 @@ import (
|
|||||||
var log = logging.Logger("fullnode")
|
var log = logging.Logger("fullnode")
|
||||||
|
|
||||||
type ChainModuleAPI interface {
|
type ChainModuleAPI interface {
|
||||||
|
ChainNotify(context.Context) (<-chan []*api.HeadChange, error)
|
||||||
|
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
|
||||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||||
ChainHead(context.Context) (*types.TipSet, error)
|
ChainHead(context.Context) (*types.TipSet, error)
|
||||||
|
ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error)
|
||||||
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||||
@ -67,8 +70,8 @@ type ChainAPI struct {
|
|||||||
Chain *store.ChainStore
|
Chain *store.ChainStore
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ChainAPI) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) {
|
func (m *ChainModule) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) {
|
||||||
return a.Chain.SubHeadChanges(ctx), nil
|
return m.Chain.SubHeadChanges(ctx), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ChainModule) ChainHead(context.Context) (*types.TipSet, error) {
|
func (m *ChainModule) ChainHead(context.Context) (*types.TipSet, error) {
|
||||||
@ -101,13 +104,13 @@ func (m *ChainModule) ChainGetTipSet(ctx context.Context, key types.TipSetKey) (
|
|||||||
return m.Chain.LoadTipSet(key)
|
return m.Chain.LoadTipSet(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ChainAPI) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (*api.BlockMessages, error) {
|
func (m *ChainModule) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (*api.BlockMessages, error) {
|
||||||
b, err := a.Chain.GetBlock(msg)
|
b, err := m.Chain.GetBlock(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
bmsgs, smsgs, err := a.Chain.MessagesForBlock(b)
|
bmsgs, smsgs, err := m.Chain.MessagesForBlock(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -532,8 +535,8 @@ func (a *ChainAPI) ChainGetNode(ctx context.Context, p string) (*api.IpldObject,
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ChainAPI) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
|
func (m *ChainModule) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
|
||||||
cm, err := a.Chain.GetCMessage(mc)
|
cm, err := m.Chain.GetCMessage(mc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -40,12 +40,22 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type StateModuleAPI interface {
|
type StateModuleAPI interface {
|
||||||
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
|
||||||
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
|
|
||||||
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
|
||||||
StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
|
|
||||||
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||||
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
|
||||||
|
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||||
|
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error)
|
||||||
|
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
|
||||||
|
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
|
||||||
|
StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
|
||||||
|
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||||
|
StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error)
|
||||||
|
StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error)
|
||||||
|
StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error)
|
||||||
|
StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
|
||||||
|
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error)
|
||||||
|
StateNetworkVersion(ctx context.Context, key types.TipSetKey) (network.Version, error)
|
||||||
|
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
|
||||||
|
StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StateModule provides a default implementation of StateModuleAPI.
|
// StateModule provides a default implementation of StateModuleAPI.
|
||||||
@ -112,13 +122,13 @@ func (a *StateAPI) StateMinerActiveSectors(ctx context.Context, maddr address.Ad
|
|||||||
return stmgr.GetMinerSectorSet(ctx, a.StateManager, ts, maddr, &activeSectors)
|
return stmgr.GetMinerSectorSet(ctx, a.StateManager, ts, maddr, &activeSectors)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) {
|
func (m *StateModule) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) {
|
||||||
act, err := a.StateManager.LoadActorTsk(ctx, actor, tsk)
|
act, err := m.StateManager.LoadActorTsk(ctx, actor, tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return miner.MinerInfo{}, xerrors.Errorf("failed to load miner actor: %w", err)
|
return miner.MinerInfo{}, xerrors.Errorf("failed to load miner actor: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mas, err := miner.Load(a.StateManager.ChainStore().Store(ctx), act)
|
mas, err := miner.Load(m.StateManager.ChainStore().Store(ctx), act)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return miner.MinerInfo{}, xerrors.Errorf("failed to load miner actor state: %w", err)
|
return miner.MinerInfo{}, xerrors.Errorf("failed to load miner actor state: %w", err)
|
||||||
}
|
}
|
||||||
@ -215,18 +225,18 @@ func (a *StateAPI) StateMinerPartitions(ctx context.Context, m address.Address,
|
|||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) {
|
func (m *StateModule) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) {
|
||||||
ts, err := a.StateManager.ChainStore().GetTipSetFromKey(tsk)
|
ts, err := m.Chain.GetTipSetFromKey(tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
act, err := a.StateManager.LoadActor(ctx, addr, ts)
|
act, err := m.StateManager.LoadActor(ctx, addr, ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to load miner actor: %w", err)
|
return nil, xerrors.Errorf("failed to load miner actor: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mas, err := miner.Load(a.StateManager.ChainStore().Store(ctx), act)
|
mas, err := miner.Load(m.StateManager.ChainStore().Store(ctx), act)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
|
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
|
||||||
}
|
}
|
||||||
@ -310,19 +320,19 @@ func (a *StateAPI) StateMinerRecoveries(ctx context.Context, addr address.Addres
|
|||||||
return miner.AllPartSectors(mas, miner.Partition.RecoveringSectors)
|
return miner.AllPartSectors(mas, miner.Partition.RecoveringSectors)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateMinerPower(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*api.MinerPower, error) {
|
func (m *StateModule) StateMinerPower(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*api.MinerPower, error) {
|
||||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
ts, err := m.Chain.GetTipSetFromKey(tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
m, net, hmp, err := stmgr.GetPower(ctx, a.StateManager, ts, addr)
|
mp, net, hmp, err := stmgr.GetPower(ctx, m.StateManager, ts, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &api.MinerPower{
|
return &api.MinerPower{
|
||||||
MinerPower: m,
|
MinerPower: mp,
|
||||||
TotalPower: net,
|
TotalPower: net,
|
||||||
HasMinPower: hmp,
|
HasMinPower: hmp,
|
||||||
}, nil
|
}, nil
|
||||||
@ -563,20 +573,20 @@ func (a *StateAPI) StateSearchMsg(ctx context.Context, msg cid.Cid) (*api.MsgLoo
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateGetReceipt(ctx context.Context, msg cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) {
|
func (m *StateModule) StateGetReceipt(ctx context.Context, msg cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) {
|
||||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
ts, err := m.Chain.GetTipSetFromKey(tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||||
}
|
}
|
||||||
return a.StateManager.GetReceipt(ctx, msg, ts)
|
return m.StateManager.GetReceipt(ctx, msg, ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
|
func (m *StateModule) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
|
||||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
ts, err := m.Chain.GetTipSetFromKey(tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||||
}
|
}
|
||||||
return stmgr.ListMinerActors(ctx, a.StateManager, ts)
|
return stmgr.ListMinerActors(ctx, m.StateManager, ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateListActors(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
|
func (a *StateAPI) StateListActors(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
|
||||||
@ -587,12 +597,12 @@ func (a *StateAPI) StateListActors(ctx context.Context, tsk types.TipSetKey) ([]
|
|||||||
return a.StateManager.ListAllActors(ctx, ts)
|
return a.StateManager.ListAllActors(ctx, ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
|
func (m *StateModule) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
|
||||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
ts, err := m.Chain.GetTipSetFromKey(tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.MarketBalance{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
return api.MarketBalance{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||||
}
|
}
|
||||||
return a.StateManager.MarketBalance(ctx, addr, ts)
|
return m.StateManager.MarketBalance(ctx, addr, ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateMarketParticipants(ctx context.Context, tsk types.TipSetKey) (map[string]api.MarketBalance, error) {
|
func (a *StateAPI) StateMarketParticipants(ctx context.Context, tsk types.TipSetKey) (map[string]api.MarketBalance, error) {
|
||||||
@ -676,12 +686,12 @@ func (a *StateAPI) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (m
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
|
func (m *StateModule) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
|
||||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
ts, err := m.Chain.GetTipSetFromKey(tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||||
}
|
}
|
||||||
return stmgr.GetStorageDeal(ctx, a.StateManager, dealId, ts)
|
return stmgr.GetStorageDeal(ctx, m.StateManager, dealId, ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateChangedActors(ctx context.Context, old cid.Cid, new cid.Cid) (map[string]types.Actor, error) {
|
func (a *StateAPI) StateChangedActors(ctx context.Context, old cid.Cid, new cid.Cid) (map[string]types.Actor, error) {
|
||||||
@ -1158,19 +1168,19 @@ func (a *StateAPI) StateVerifierStatus(ctx context.Context, addr address.Address
|
|||||||
// StateVerifiedClientStatus returns the data cap for the given address.
|
// StateVerifiedClientStatus returns the data cap for the given address.
|
||||||
// Returns zero if there is no entry in the data cap table for the
|
// Returns zero if there is no entry in the data cap table for the
|
||||||
// address.
|
// address.
|
||||||
func (a *StateAPI) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
|
func (m *StateModule) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
|
||||||
act, err := a.StateGetActor(ctx, verifreg.Address, tsk)
|
act, err := m.StateGetActor(ctx, verifreg.Address, tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
aid, err := a.StateLookupID(ctx, addr, tsk)
|
aid, err := m.StateLookupID(ctx, addr, tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("lookup failure %v", err)
|
log.Warnf("lookup failure %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
vrs, err := verifreg.Load(a.StateManager.ChainStore().Store(ctx), act)
|
vrs, err := verifreg.Load(m.StateManager.ChainStore().Store(ctx), act)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to load verified registry state: %w", err)
|
return nil, xerrors.Errorf("failed to load verified registry state: %w", err)
|
||||||
}
|
}
|
||||||
@ -1205,33 +1215,33 @@ var dealProviderCollateralDen = types.NewInt(100)
|
|||||||
|
|
||||||
// StateDealProviderCollateralBounds returns the min and max collateral a storage provider
|
// StateDealProviderCollateralBounds returns the min and max collateral a storage provider
|
||||||
// can issue. It takes the deal size and verified status as parameters.
|
// can issue. It takes the deal size and verified status as parameters.
|
||||||
func (a *StateAPI) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
|
func (m *StateModule) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
|
||||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
ts, err := m.Chain.GetTipSetFromKey(tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.DealCollateralBounds{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
return api.DealCollateralBounds{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pact, err := a.StateGetActor(ctx, power.Address, tsk)
|
pact, err := m.StateGetActor(ctx, power.Address, tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.DealCollateralBounds{}, xerrors.Errorf("failed to load power actor: %w", err)
|
return api.DealCollateralBounds{}, xerrors.Errorf("failed to load power actor: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ract, err := a.StateGetActor(ctx, reward.Address, tsk)
|
ract, err := m.StateGetActor(ctx, reward.Address, tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.DealCollateralBounds{}, xerrors.Errorf("failed to load reward actor: %w", err)
|
return api.DealCollateralBounds{}, xerrors.Errorf("failed to load reward actor: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pst, err := power.Load(a.StateManager.ChainStore().Store(ctx), pact)
|
pst, err := power.Load(m.StateManager.ChainStore().Store(ctx), pact)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.DealCollateralBounds{}, xerrors.Errorf("failed to load power actor state: %w", err)
|
return api.DealCollateralBounds{}, xerrors.Errorf("failed to load power actor state: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rst, err := reward.Load(a.StateManager.ChainStore().Store(ctx), ract)
|
rst, err := reward.Load(m.StateManager.ChainStore().Store(ctx), ract)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.DealCollateralBounds{}, xerrors.Errorf("failed to load reward actor state: %w", err)
|
return api.DealCollateralBounds{}, xerrors.Errorf("failed to load reward actor state: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
circ, err := a.StateVMCirculatingSupplyInternal(ctx, ts.Key())
|
circ, err := stateVMCirculatingSupplyInternal(ctx, ts.Key(), m.Chain, m.StateManager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.DealCollateralBounds{}, xerrors.Errorf("getting total circulating supply: %w", err)
|
return api.DealCollateralBounds{}, xerrors.Errorf("getting total circulating supply: %w", err)
|
||||||
}
|
}
|
||||||
@ -1252,7 +1262,7 @@ func (a *StateAPI) StateDealProviderCollateralBounds(ctx context.Context, size a
|
|||||||
powClaim.QualityAdjPower,
|
powClaim.QualityAdjPower,
|
||||||
rewPow,
|
rewPow,
|
||||||
circ.FilCirculating,
|
circ.FilCirculating,
|
||||||
a.StateManager.GetNtwkVersion(ctx, ts.Height()))
|
m.StateManager.GetNtwkVersion(ctx, ts.Height()))
|
||||||
return api.DealCollateralBounds{
|
return api.DealCollateralBounds{
|
||||||
Min: types.BigDiv(types.BigMul(min, dealProviderCollateralNum), dealProviderCollateralDen),
|
Min: types.BigDiv(types.BigMul(min, dealProviderCollateralNum), dealProviderCollateralDen),
|
||||||
Max: max,
|
Max: max,
|
||||||
@ -1273,23 +1283,32 @@ func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetK
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
|
func (a *StateAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
|
||||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
return stateVMCirculatingSupplyInternal(ctx, tsk, a.Chain, a.StateManager)
|
||||||
|
}
|
||||||
|
func stateVMCirculatingSupplyInternal(
|
||||||
|
ctx context.Context,
|
||||||
|
tsk types.TipSetKey,
|
||||||
|
cstore *store.ChainStore,
|
||||||
|
smgr *stmgr.StateManager,
|
||||||
|
) (api.CirculatingSupply, error) {
|
||||||
|
ts, err := cstore.GetTipSetFromKey(tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.CirculatingSupply{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
return api.CirculatingSupply{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sTree, err := a.stateForTs(ctx, ts)
|
sTree, err := stateForTs(ctx, ts, cstore, smgr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.CirculatingSupply{}, err
|
return api.CirculatingSupply{}, err
|
||||||
}
|
}
|
||||||
return a.StateManager.GetVMCirculatingSupplyDetailed(ctx, ts.Height(), sTree)
|
|
||||||
|
return smgr.GetVMCirculatingSupplyDetailed(ctx, ts.Height(), sTree)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) {
|
func (m *StateModule) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) {
|
||||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
ts, err := m.Chain.GetTipSetFromKey(tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return network.VersionMax, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
return network.VersionMax, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.StateManager.GetNtwkVersion(ctx, ts.Height()), nil
|
return m.StateManager.GetNtwkVersion(ctx, ts.Height()), nil
|
||||||
}
|
}
|
||||||
|
@ -13,17 +13,12 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
full "github.com/filecoin-project/lotus/node/impl/full"
|
|
||||||
"github.com/filecoin-project/lotus/paychmgr"
|
"github.com/filecoin-project/lotus/paychmgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PaychAPI struct {
|
type PaychAPI struct {
|
||||||
fx.In
|
fx.In
|
||||||
|
|
||||||
full.MpoolAPI
|
|
||||||
full.WalletAPI
|
|
||||||
full.ChainAPI
|
|
||||||
|
|
||||||
PaychMgr *paychmgr.Manager
|
PaychMgr *paychmgr.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,19 +3,40 @@ package modules
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
"github.com/filecoin-project/lotus/api/apibstore"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RPCStateManager struct {
|
type RPCStateManager struct {
|
||||||
gapi api.GatewayAPI
|
gapi api.GatewayAPI
|
||||||
|
cstore *cbor.BasicIpldStore
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRPCStateManager(api api.GatewayAPI) *RPCStateManager {
|
func NewRPCStateManager(api api.GatewayAPI) *RPCStateManager {
|
||||||
return &RPCStateManager{gapi: api}
|
cstore := cbor.NewCborStore(apibstore.NewAPIBlockstore(api))
|
||||||
|
return &RPCStateManager{gapi: api, cstore: cstore}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RPCStateManager) GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error) {
|
||||||
|
act, err := s.gapi.StateGetActor(ctx, addr, ts.Key())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
actState, err := paych.Load(adt.WrapStore(ctx, s.cstore), act)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return act, actState, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RPCStateManager) LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error) {
|
func (s *RPCStateManager) LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error) {
|
||||||
@ -30,4 +51,8 @@ func (s *RPCStateManager) ResolveToKeyAddress(ctx context.Context, addr address.
|
|||||||
return s.gapi.StateAccountKey(ctx, addr, ts.Key())
|
return s.gapi.StateAccountKey(ctx, addr, ts.Key())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *RPCStateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) {
|
||||||
|
return nil, xerrors.Errorf("RPCStateManager does not implement StateManager.Call")
|
||||||
|
}
|
||||||
|
|
||||||
var _ stmgr.StateManagerAPI = (*RPCStateManager)(nil)
|
var _ stmgr.StateManagerAPI = (*RPCStateManager)(nil)
|
||||||
|
@ -16,7 +16,6 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/network"
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
@ -61,14 +60,10 @@ type managerAPI interface {
|
|||||||
|
|
||||||
// managerAPIImpl is used to create a composite that implements managerAPI
|
// managerAPIImpl is used to create a composite that implements managerAPI
|
||||||
type managerAPIImpl struct {
|
type managerAPIImpl struct {
|
||||||
*stmgr.StateManager
|
stmgr.StateManagerAPI
|
||||||
paychAPI
|
paychAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *managerAPIImpl) AdtStore(ctx context.Context) adt.Store {
|
|
||||||
return m.ChainStore().Store(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
// The Manager context is used to terminate wait operations on shutdown
|
// The Manager context is used to terminate wait operations on shutdown
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@ -82,11 +77,11 @@ type Manager struct {
|
|||||||
channels map[string]*channelAccessor
|
channels map[string]*channelAccessor
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewManager(mctx helpers.MetricsCtx, lc fx.Lifecycle, sm *stmgr.StateManager, pchstore *Store, api PaychAPI) *Manager {
|
func NewManager(mctx helpers.MetricsCtx, lc fx.Lifecycle, sm stmgr.StateManagerAPI, pchstore *Store, api PaychAPI) *Manager {
|
||||||
ctx := helpers.LifecycleCtx(mctx, lc)
|
ctx := helpers.LifecycleCtx(mctx, lc)
|
||||||
ctx, shutdown := context.WithCancel(ctx)
|
ctx, shutdown := context.WithCancel(ctx)
|
||||||
|
|
||||||
impl := &managerAPIImpl{StateManager: sm, paychAPI: &api}
|
impl := &managerAPIImpl{StateManagerAPI: sm, paychAPI: &api}
|
||||||
return &Manager{
|
return &Manager{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
shutdown: shutdown,
|
shutdown: shutdown,
|
||||||
|
Loading…
Reference in New Issue
Block a user