From 88c6642330260ba2624b4edeb1e5f5e98c90020f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Wed, 19 May 2021 12:22:07 +0100 Subject: [PATCH 1/2] restructure gateway. Move the gateway implementation to the `gateway` top-level package. cmd/lotus-gateway now contains only the entrypoint. This separation is important for the testing refactors. --- cmd/lotus-gateway/api.go | 426 ------------------ cmd/lotus-gateway/endtoend_test.go | 3 +- cmd/lotus-gateway/main.go | 9 +- gateway/node.go | 419 +++++++++++++++++ .../api_test.go => gateway/node_test.go | 15 +- 5 files changed, 439 insertions(+), 433 deletions(-) delete mode 100644 cmd/lotus-gateway/api.go create mode 100644 gateway/node.go rename cmd/lotus-gateway/api_test.go => gateway/node_test.go (95%) diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go deleted file mode 100644 index 003625a84bf..00000000000 --- a/cmd/lotus-gateway/api.go +++ /dev/null @@ -1,426 +0,0 @@ -package main - -import ( - "context" - "fmt" - "time" - - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-bitfield" - "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/crypto" - "github.com/filecoin-project/go-state-types/dline" - "github.com/filecoin-project/go-state-types/network" - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/chain/actors/builtin/miner" - "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/lib/sigs" - _ "github.com/filecoin-project/lotus/lib/sigs/bls" - _ "github.com/filecoin-project/lotus/lib/sigs/secp" - "github.com/filecoin-project/lotus/node/impl/full" - "github.com/ipfs/go-cid" -) - -const ( - LookbackCap = time.Hour * 24 - StateWaitLookbackLimit = abi.ChainEpoch(20) -) - -var ( - ErrLookbackTooLong = fmt.Errorf("lookbacks of more than %s are disallowed", LookbackCap) -) - -// gatewayDepsAPI defines the API methods that the GatewayAPI depends on -// (to make it easy to mock for tests) -type gatewayDepsAPI interface { - Version(context.Context) (api.APIVersion, error) - ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) - ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) - ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) - ChainGetTipSet(ctx context.Context, 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) - 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) - 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) - MsigGetPending(ctx context.Context, addr address.Address, ts types.TipSetKey) ([]*api.MsigTransaction, 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) - 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) - StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) - StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) - StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) - StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) - StateMinerFaults(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) - StateMinerRecoveries(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) - StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) - StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]api.Deadline, error) - StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) - StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) - StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) - StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) - StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) - StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error) - WalletBalance(context.Context, address.Address) (types.BigInt, error) //perm:read -} - -var _ gatewayDepsAPI = *new(api.FullNode) // gateway depends on latest - -type GatewayAPI struct { - api gatewayDepsAPI - lookbackCap time.Duration - stateWaitLookbackLimit abi.ChainEpoch -} - -// NewGatewayAPI creates a new GatewayAPI with the default lookback cap -func NewGatewayAPI(api gatewayDepsAPI) *GatewayAPI { - return newGatewayAPI(api, LookbackCap, StateWaitLookbackLimit) -} - -// used by the tests -func newGatewayAPI(api gatewayDepsAPI, lookbackCap time.Duration, stateWaitLookbackLimit abi.ChainEpoch) *GatewayAPI { - return &GatewayAPI{api: api, lookbackCap: lookbackCap, stateWaitLookbackLimit: stateWaitLookbackLimit} -} - -func (a *GatewayAPI) checkTipsetKey(ctx context.Context, tsk types.TipSetKey) error { - if tsk.IsEmpty() { - return nil - } - - ts, err := a.api.ChainGetTipSet(ctx, tsk) - if err != nil { - return err - } - - return a.checkTipset(ts) -} - -func (a *GatewayAPI) checkTipset(ts *types.TipSet) error { - at := time.Unix(int64(ts.Blocks()[0].Timestamp), 0) - if err := a.checkTimestamp(at); err != nil { - return fmt.Errorf("bad tipset: %w", err) - } - return nil -} - -func (a *GatewayAPI) checkTipsetHeight(ts *types.TipSet, h abi.ChainEpoch) error { - tsBlock := ts.Blocks()[0] - heightDelta := time.Duration(uint64(tsBlock.Height-h)*build.BlockDelaySecs) * time.Second - timeAtHeight := time.Unix(int64(tsBlock.Timestamp), 0).Add(-heightDelta) - - if err := a.checkTimestamp(timeAtHeight); err != nil { - return fmt.Errorf("bad tipset height: %w", err) - } - return nil -} - -func (a *GatewayAPI) checkTimestamp(at time.Time) error { - if time.Since(at) > a.lookbackCap { - return ErrLookbackTooLong - } - - return nil -} - -func (a *GatewayAPI) Version(ctx context.Context) (api.APIVersion, error) { - 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) { - return a.api.ChainHasObj(ctx, c) -} - -func (a *GatewayAPI) ChainHead(ctx context.Context) (*types.TipSet, error) { - // TODO: cache and invalidate cache when timestamp is up (or have internal ChainNotify) - - 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) { - return a.api.ChainGetTipSet(ctx, tsk) -} - -func (a *GatewayAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) { - var ts *types.TipSet - if tsk.IsEmpty() { - head, err := a.api.ChainHead(ctx) - if err != nil { - return nil, err - } - ts = head - } else { - gts, err := a.api.ChainGetTipSet(ctx, tsk) - if err != nil { - return nil, err - } - ts = gts - } - - // Check if the tipset key refers to a tipset that's too far in the past - if err := a.checkTipset(ts); err != nil { - return nil, err - } - - // Check if the height is too far in the past - if err := a.checkTipsetHeight(ts, h); err != nil { - return nil, err - } - - return a.api.ChainGetTipSetByHeight(ctx, h, tsk) -} - -func (a *GatewayAPI) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) { - 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) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return nil, err - } - - return a.api.GasEstimateMessageGas(ctx, msg, spec, tsk) -} - -func (a *GatewayAPI) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) { - // TODO: additional anti-spam checks - return a.api.MpoolPushUntrusted(ctx, sm) -} - -func (a *GatewayAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return types.NewInt(0), err - } - - return a.api.MsigGetAvailableBalance(ctx, addr, tsk) -} - -func (a *GatewayAPI) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) { - if err := a.checkTipsetKey(ctx, start); err != nil { - return types.NewInt(0), err - } - if err := a.checkTipsetKey(ctx, end); err != nil { - return types.NewInt(0), err - } - - return a.api.MsigGetVested(ctx, addr, start, end) -} - -func (a *GatewayAPI) MsigGetPending(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.MsigTransaction, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return nil, err - } - - return a.api.MsigGetPending(ctx, addr, tsk) -} - -func (a *GatewayAPI) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return address.Undef, err - } - - 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) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return nil, err - } - - return a.api.StateGetActor(ctx, actor, 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) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return address.Undef, err - } - - 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) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) { - if limit == api.LookbackNoLimit { - limit = a.stateWaitLookbackLimit - } - if a.stateWaitLookbackLimit != api.LookbackNoLimit && limit > a.stateWaitLookbackLimit { - limit = a.stateWaitLookbackLimit - } - if err := a.checkTipsetKey(ctx, from); err != nil { - return nil, err - } - - return a.api.StateSearchMsg(ctx, from, msg, limit, allowReplaced) -} - -func (a *GatewayAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) { - if limit == api.LookbackNoLimit { - limit = a.stateWaitLookbackLimit - } - if a.stateWaitLookbackLimit != api.LookbackNoLimit && limit > a.stateWaitLookbackLimit { - limit = a.stateWaitLookbackLimit - } - - return a.api.StateWaitMsg(ctx, msg, confidence, limit, allowReplaced) -} - -func (a *GatewayAPI) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return nil, err - } - return a.api.StateReadState(ctx, actor, tsk) -} - -func (a *GatewayAPI) StateMinerPower(ctx context.Context, m address.Address, tsk types.TipSetKey) (*api.MinerPower, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return nil, err - } - return a.api.StateMinerPower(ctx, m, tsk) -} - -func (a *GatewayAPI) StateMinerFaults(ctx context.Context, m address.Address, tsk types.TipSetKey) (bitfield.BitField, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return bitfield.BitField{}, err - } - return a.api.StateMinerFaults(ctx, m, tsk) -} -func (a *GatewayAPI) StateMinerRecoveries(ctx context.Context, m address.Address, tsk types.TipSetKey) (bitfield.BitField, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return bitfield.BitField{}, err - } - return a.api.StateMinerRecoveries(ctx, m, tsk) -} - -func (a *GatewayAPI) StateMinerInfo(ctx context.Context, m address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return miner.MinerInfo{}, err - } - return a.api.StateMinerInfo(ctx, m, tsk) -} - -func (a *GatewayAPI) StateMinerDeadlines(ctx context.Context, m address.Address, tsk types.TipSetKey) ([]api.Deadline, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return nil, err - } - return a.api.StateMinerDeadlines(ctx, m, tsk) -} - -func (a *GatewayAPI) StateMinerAvailableBalance(ctx context.Context, m address.Address, tsk types.TipSetKey) (types.BigInt, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return types.BigInt{}, err - } - return a.api.StateMinerAvailableBalance(ctx, m, tsk) -} - -func (a *GatewayAPI) StateMinerProvingDeadline(ctx context.Context, m address.Address, tsk types.TipSetKey) (*dline.Info, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return nil, err - } - return a.api.StateMinerProvingDeadline(ctx, m, tsk) -} - -func (a *GatewayAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (abi.TokenAmount, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return types.BigInt{}, err - } - return a.api.StateCirculatingSupply(ctx, tsk) -} - -func (a *GatewayAPI) StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return nil, err - } - return a.api.StateSectorGetInfo(ctx, maddr, n, tsk) -} - -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) { - if err := a.checkTipsetKey(ctx, tsk); err != nil { - return api.CirculatingSupply{}, err - } - return a.api.StateVMCirculatingSupplyInternal(ctx, tsk) -} - -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 -} - -func (a *GatewayAPI) WalletBalance(ctx context.Context, k address.Address) (types.BigInt, error) { - return a.api.WalletBalance(ctx, k) -} - -var _ api.Gateway = (*GatewayAPI)(nil) -var _ full.ChainModuleAPI = (*GatewayAPI)(nil) -var _ full.GasModuleAPI = (*GatewayAPI)(nil) -var _ full.MpoolModuleAPI = (*GatewayAPI)(nil) -var _ full.StateModuleAPI = (*GatewayAPI)(nil) diff --git a/cmd/lotus-gateway/endtoend_test.go b/cmd/lotus-gateway/endtoend_test.go index 3fae221c337..373d9d59529 100644 --- a/cmd/lotus-gateway/endtoend_test.go +++ b/cmd/lotus-gateway/endtoend_test.go @@ -11,6 +11,7 @@ import ( "github.com/filecoin-project/lotus/cli" clitest "github.com/filecoin-project/lotus/cli/test" + "github.com/filecoin-project/lotus/gateway" init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" multisig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" @@ -275,7 +276,7 @@ func startNodes( fullNode := nodes[0] // Create a gateway server in front of the full node - gapiImpl := newGatewayAPI(fullNode, lookbackCap, stateWaitLookbackLimit) + gapiImpl := gateway.NewNode(fullNode, lookbackCap, stateWaitLookbackLimit) _, addr, err := builder.CreateRPCServer(t, map[string]interface{}{ "/rpc/v1": gapiImpl, "/rpc/v0": api.Wrap(new(v1api.FullNodeStruct), new(v0api.WrapperV1Full), gapiImpl), diff --git a/cmd/lotus-gateway/main.go b/cmd/lotus-gateway/main.go index 60f45f283f4..c35ab3cae4d 100644 --- a/cmd/lotus-gateway/main.go +++ b/cmd/lotus-gateway/main.go @@ -5,10 +5,12 @@ import ( "net" "net/http" "os" + "time" "contrib.go.opencensus.io/exporter/prometheus" "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/gateway" promclient "github.com/prometheus/client_golang/prometheus" "go.opencensus.io/tag" @@ -29,6 +31,11 @@ import ( var log = logging.Logger("gateway") +const ( + LookbackCap = time.Hour * 24 + StateWaitLookbackLimit = abi.ChainEpoch(20) +) + func main() { lotuslog.SetupLogLevels() @@ -122,7 +129,7 @@ var runCmd = &cli.Command{ waitLookback := abi.ChainEpoch(cctx.Int64("api-wait-lookback-limit")) - ma := metrics.MetricedGatewayAPI(newGatewayAPI(api, lookbackCap, waitLookback)) + ma := metrics.MetricedGatewayAPI(gateway.NewNode(api, lookbackCap, waitLookback)) serveRpc("/rpc/v1", ma) serveRpc("/rpc/v0", lapi.Wrap(new(v1api.FullNodeStruct), new(v0api.WrapperV1Full), ma)) diff --git a/gateway/node.go b/gateway/node.go new file mode 100644 index 00000000000..bd2ae3230a2 --- /dev/null +++ b/gateway/node.go @@ -0,0 +1,419 @@ +package gateway + +import ( + "context" + "fmt" + "time" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-bitfield" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/go-state-types/dline" + "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/lib/sigs" + _ "github.com/filecoin-project/lotus/lib/sigs/bls" + _ "github.com/filecoin-project/lotus/lib/sigs/secp" + "github.com/filecoin-project/lotus/node/impl/full" + "github.com/ipfs/go-cid" +) + +// TargetAPI defines the API methods that the Node depends on +// (to make it easy to mock for tests) +type TargetAPI interface { + Version(context.Context) (api.APIVersion, error) + ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) + ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) + ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) + ChainGetTipSet(ctx context.Context, 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) + 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) + 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) + MsigGetPending(ctx context.Context, addr address.Address, ts types.TipSetKey) ([]*api.MsigTransaction, 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) + 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) + StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) + StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) + StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) + StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) + StateMinerFaults(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) + StateMinerRecoveries(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) + StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) + StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]api.Deadline, error) + StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) + StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) + StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) + StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) + StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) + StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error) + WalletBalance(context.Context, address.Address) (types.BigInt, error) //perm:read +} + +var _ TargetAPI = *new(api.FullNode) // gateway depends on latest + +type Node struct { + target TargetAPI + lookbackCap time.Duration + stateWaitLookbackLimit abi.ChainEpoch + errLookback error +} + +var ( + _ api.Gateway = (*Node)(nil) + _ full.ChainModuleAPI = (*Node)(nil) + _ full.GasModuleAPI = (*Node)(nil) + _ full.MpoolModuleAPI = (*Node)(nil) + _ full.StateModuleAPI = (*Node)(nil) +) + +// NewNode creates a new gateway node. +func NewNode(api TargetAPI, lookbackCap time.Duration, stateWaitLookbackLimit abi.ChainEpoch) *Node { + return &Node{ + target: api, + lookbackCap: lookbackCap, + stateWaitLookbackLimit: stateWaitLookbackLimit, + errLookback: fmt.Errorf("lookbacks of more than %s are disallowed", lookbackCap), + } +} + +func (gw *Node) checkTipsetKey(ctx context.Context, tsk types.TipSetKey) error { + if tsk.IsEmpty() { + return nil + } + + ts, err := gw.target.ChainGetTipSet(ctx, tsk) + if err != nil { + return err + } + + return gw.checkTipset(ts) +} + +func (gw *Node) checkTipset(ts *types.TipSet) error { + at := time.Unix(int64(ts.Blocks()[0].Timestamp), 0) + if err := gw.checkTimestamp(at); err != nil { + return fmt.Errorf("bad tipset: %w", err) + } + return nil +} + +func (gw *Node) checkTipsetHeight(ts *types.TipSet, h abi.ChainEpoch) error { + tsBlock := ts.Blocks()[0] + heightDelta := time.Duration(uint64(tsBlock.Height-h)*build.BlockDelaySecs) * time.Second + timeAtHeight := time.Unix(int64(tsBlock.Timestamp), 0).Add(-heightDelta) + + if err := gw.checkTimestamp(timeAtHeight); err != nil { + return fmt.Errorf("bad tipset height: %w", err) + } + return nil +} + +func (gw *Node) checkTimestamp(at time.Time) error { + if time.Since(at) > gw.lookbackCap { + return gw.errLookback + } + return nil +} + +func (gw *Node) Version(ctx context.Context) (api.APIVersion, error) { + return gw.target.Version(ctx) +} + +func (gw *Node) ChainGetBlockMessages(ctx context.Context, c cid.Cid) (*api.BlockMessages, error) { + return gw.target.ChainGetBlockMessages(ctx, c) +} + +func (gw *Node) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) { + return gw.target.ChainHasObj(ctx, c) +} + +func (gw *Node) ChainHead(ctx context.Context) (*types.TipSet, error) { + // TODO: cache and invalidate cache when timestamp is up (or have internal ChainNotify) + + return gw.target.ChainHead(ctx) +} + +func (gw *Node) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) { + return gw.target.ChainGetMessage(ctx, mc) +} + +func (gw *Node) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) { + return gw.target.ChainGetTipSet(ctx, tsk) +} + +func (gw *Node) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) { + var ts *types.TipSet + if tsk.IsEmpty() { + head, err := gw.target.ChainHead(ctx) + if err != nil { + return nil, err + } + ts = head + } else { + gts, err := gw.target.ChainGetTipSet(ctx, tsk) + if err != nil { + return nil, err + } + ts = gts + } + + // Check if the tipset key refers to gw tipset that's too far in the past + if err := gw.checkTipset(ts); err != nil { + return nil, err + } + + // Check if the height is too far in the past + if err := gw.checkTipsetHeight(ts, h); err != nil { + return nil, err + } + + return gw.target.ChainGetTipSetByHeight(ctx, h, tsk) +} + +func (gw *Node) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) { + return gw.target.ChainGetNode(ctx, p) +} + +func (gw *Node) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) { + return gw.target.ChainNotify(ctx) +} + +func (gw *Node) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) { + return gw.target.ChainReadObj(ctx, c) +} + +func (gw *Node) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + + return gw.target.GasEstimateMessageGas(ctx, msg, spec, tsk) +} + +func (gw *Node) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) { + // TODO: additional anti-spam checks + return gw.target.MpoolPushUntrusted(ctx, sm) +} + +func (gw *Node) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return types.NewInt(0), err + } + + return gw.target.MsigGetAvailableBalance(ctx, addr, tsk) +} + +func (gw *Node) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) { + if err := gw.checkTipsetKey(ctx, start); err != nil { + return types.NewInt(0), err + } + if err := gw.checkTipsetKey(ctx, end); err != nil { + return types.NewInt(0), err + } + + return gw.target.MsigGetVested(ctx, addr, start, end) +} + +func (gw *Node) MsigGetPending(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.MsigTransaction, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + + return gw.target.MsigGetPending(ctx, addr, tsk) +} + +func (gw *Node) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return address.Undef, err + } + + return gw.target.StateAccountKey(ctx, addr, tsk) +} + +func (gw *Node) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return api.DealCollateralBounds{}, err + } + + return gw.target.StateDealProviderCollateralBounds(ctx, size, verified, tsk) +} + +func (gw *Node) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + + return gw.target.StateGetActor(ctx, actor, tsk) +} + +func (gw *Node) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + + return gw.target.StateListMiners(ctx, tsk) +} + +func (gw *Node) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return address.Undef, err + } + + return gw.target.StateLookupID(ctx, addr, tsk) +} + +func (gw *Node) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return api.MarketBalance{}, err + } + + return gw.target.StateMarketBalance(ctx, addr, tsk) +} + +func (gw *Node) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + + return gw.target.StateMarketStorageDeal(ctx, dealId, tsk) +} + +func (gw *Node) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return network.VersionMax, err + } + + return gw.target.StateNetworkVersion(ctx, tsk) +} + +func (gw *Node) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) { + if limit == api.LookbackNoLimit { + limit = gw.stateWaitLookbackLimit + } + if gw.stateWaitLookbackLimit != api.LookbackNoLimit && limit > gw.stateWaitLookbackLimit { + limit = gw.stateWaitLookbackLimit + } + if err := gw.checkTipsetKey(ctx, from); err != nil { + return nil, err + } + + return gw.target.StateSearchMsg(ctx, from, msg, limit, allowReplaced) +} + +func (gw *Node) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) { + if limit == api.LookbackNoLimit { + limit = gw.stateWaitLookbackLimit + } + if gw.stateWaitLookbackLimit != api.LookbackNoLimit && limit > gw.stateWaitLookbackLimit { + limit = gw.stateWaitLookbackLimit + } + + return gw.target.StateWaitMsg(ctx, msg, confidence, limit, allowReplaced) +} + +func (gw *Node) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + return gw.target.StateReadState(ctx, actor, tsk) +} + +func (gw *Node) StateMinerPower(ctx context.Context, m address.Address, tsk types.TipSetKey) (*api.MinerPower, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + return gw.target.StateMinerPower(ctx, m, tsk) +} + +func (gw *Node) StateMinerFaults(ctx context.Context, m address.Address, tsk types.TipSetKey) (bitfield.BitField, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return bitfield.BitField{}, err + } + return gw.target.StateMinerFaults(ctx, m, tsk) +} +func (gw *Node) StateMinerRecoveries(ctx context.Context, m address.Address, tsk types.TipSetKey) (bitfield.BitField, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return bitfield.BitField{}, err + } + return gw.target.StateMinerRecoveries(ctx, m, tsk) +} + +func (gw *Node) StateMinerInfo(ctx context.Context, m address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return miner.MinerInfo{}, err + } + return gw.target.StateMinerInfo(ctx, m, tsk) +} + +func (gw *Node) StateMinerDeadlines(ctx context.Context, m address.Address, tsk types.TipSetKey) ([]api.Deadline, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + return gw.target.StateMinerDeadlines(ctx, m, tsk) +} + +func (gw *Node) StateMinerAvailableBalance(ctx context.Context, m address.Address, tsk types.TipSetKey) (types.BigInt, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return types.BigInt{}, err + } + return gw.target.StateMinerAvailableBalance(ctx, m, tsk) +} + +func (gw *Node) StateMinerProvingDeadline(ctx context.Context, m address.Address, tsk types.TipSetKey) (*dline.Info, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + return gw.target.StateMinerProvingDeadline(ctx, m, tsk) +} + +func (gw *Node) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (abi.TokenAmount, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return types.BigInt{}, err + } + return gw.target.StateCirculatingSupply(ctx, tsk) +} + +func (gw *Node) StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + return gw.target.StateSectorGetInfo(ctx, maddr, n, tsk) +} + +func (gw *Node) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + return gw.target.StateVerifiedClientStatus(ctx, addr, tsk) +} + +func (gw *Node) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { + if err := gw.checkTipsetKey(ctx, tsk); err != nil { + return api.CirculatingSupply{}, err + } + return gw.target.StateVMCirculatingSupplyInternal(ctx, tsk) +} + +func (gw *Node) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) { + return sigs.Verify(sig, k, msg) == nil, nil +} + +func (gw *Node) WalletBalance(ctx context.Context, k address.Address) (types.BigInt, error) { + return gw.target.WalletBalance(ctx, k) +} diff --git a/cmd/lotus-gateway/api_test.go b/gateway/node_test.go similarity index 95% rename from cmd/lotus-gateway/api_test.go rename to gateway/node_test.go index 23d2cbf3afa..50f84601884 100644 --- a/cmd/lotus-gateway/api_test.go +++ b/gateway/node_test.go @@ -1,4 +1,4 @@ -package main +package gateway import ( "context" @@ -7,6 +7,7 @@ import ( "time" "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/build" @@ -17,15 +18,19 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" "github.com/ipfs/go-cid" ) +const ( + lookbackCap = time.Hour * 24 + stateWaitLookbackLimit = abi.ChainEpoch(20) +) + func TestGatewayAPIChainGetTipSetByHeight(t *testing.T) { ctx := context.Background() - lookbackTimestamp := uint64(time.Now().Unix()) - uint64(LookbackCap.Seconds()) + lookbackTimestamp := uint64(time.Now().Unix()) - uint64(lookbackCap.Seconds()) type args struct { h abi.ChainEpoch tskh abi.ChainEpoch @@ -91,7 +96,7 @@ func TestGatewayAPIChainGetTipSetByHeight(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { mock := &mockGatewayDepsAPI{} - a := NewGatewayAPI(mock) + a := NewNode(mock, lookbackCap, stateWaitLookbackLimit) // Create tipsets from genesis up to tskh and return the highest ts := mock.createTipSets(tt.args.tskh, tt.args.genesisTS) @@ -111,7 +116,7 @@ type mockGatewayDepsAPI struct { lk sync.RWMutex tipsets []*types.TipSet - gatewayDepsAPI // satisfies all interface requirements but will panic if + TargetAPI // satisfies all interface requirements but will panic if // methods are called. easier than filling out with panic stubs IMO } From ac4f3ab6840b550766c8847c0047fdef5f3e1298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Wed, 19 May 2021 17:30:06 +0100 Subject: [PATCH 2/2] remove duplicated vars. --- cmd/lotus-gateway/endtoend_test.go | 8 +++++--- cmd/lotus-gateway/main.go | 10 ++-------- gateway/node.go | 5 +++++ gateway/node_test.go | 25 +++++++++---------------- 4 files changed, 21 insertions(+), 27 deletions(-) diff --git a/cmd/lotus-gateway/endtoend_test.go b/cmd/lotus-gateway/endtoend_test.go index 373d9d59529..fc9f3d918f0 100644 --- a/cmd/lotus-gateway/endtoend_test.go +++ b/cmd/lotus-gateway/endtoend_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/cli" clitest "github.com/filecoin-project/lotus/cli/test" "github.com/filecoin-project/lotus/gateway" @@ -30,14 +31,15 @@ import ( "github.com/filecoin-project/lotus/api/v0api" "github.com/filecoin-project/lotus/api/v1api" "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/node" builder "github.com/filecoin-project/lotus/node/test" ) -const maxLookbackCap = time.Duration(math.MaxInt64) -const maxStateWaitLookbackLimit = stmgr.LookbackNoLimit +const ( + maxLookbackCap = time.Duration(math.MaxInt64) + maxStateWaitLookbackLimit = stmgr.LookbackNoLimit +) func init() { policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1) diff --git a/cmd/lotus-gateway/main.go b/cmd/lotus-gateway/main.go index c35ab3cae4d..8d4876b71bf 100644 --- a/cmd/lotus-gateway/main.go +++ b/cmd/lotus-gateway/main.go @@ -5,7 +5,6 @@ import ( "net" "net/http" "os" - "time" "contrib.go.opencensus.io/exporter/prometheus" "github.com/filecoin-project/go-jsonrpc" @@ -31,11 +30,6 @@ import ( var log = logging.Logger("gateway") -const ( - LookbackCap = time.Hour * 24 - StateWaitLookbackLimit = abi.ChainEpoch(20) -) - func main() { lotuslog.SetupLogLevels() @@ -81,12 +75,12 @@ var runCmd = &cli.Command{ &cli.DurationFlag{ Name: "api-max-lookback", Usage: "maximum duration allowable for tipset lookbacks", - Value: LookbackCap, + Value: gateway.DefaultLookbackCap, }, &cli.Int64Flag{ Name: "api-wait-lookback-limit", Usage: "maximum number of blocks to search back through for message inclusion", - Value: int64(StateWaitLookbackLimit), + Value: int64(gateway.DefaultStateWaitLookbackLimit), }, }, Action: func(cctx *cli.Context) error { diff --git a/gateway/node.go b/gateway/node.go index bd2ae3230a2..3c7a67196a0 100644 --- a/gateway/node.go +++ b/gateway/node.go @@ -22,6 +22,11 @@ import ( "github.com/ipfs/go-cid" ) +const ( + DefaultLookbackCap = time.Hour * 24 + DefaultStateWaitLookbackLimit = abi.ChainEpoch(20) +) + // TargetAPI defines the API methods that the Node depends on // (to make it easy to mock for tests) type TargetAPI interface { diff --git a/gateway/node_test.go b/gateway/node_test.go index 50f84601884..0d33daa3555 100644 --- a/gateway/node_test.go +++ b/gateway/node_test.go @@ -6,31 +6,24 @@ import ( "testing" "time" - "github.com/filecoin-project/go-state-types/network" - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/chain/actors/builtin/miner" - - "github.com/filecoin-project/lotus/build" - + "github.com/ipfs/go-cid" "github.com/stretchr/testify/require" - "github.com/filecoin-project/lotus/chain/types/mock" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/lotus/chain/types" - "github.com/ipfs/go-cid" -) + "github.com/filecoin-project/go-state-types/network" -const ( - lookbackCap = time.Hour * 24 - stateWaitLookbackLimit = abi.ChainEpoch(20) + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/mock" ) func TestGatewayAPIChainGetTipSetByHeight(t *testing.T) { ctx := context.Background() - lookbackTimestamp := uint64(time.Now().Unix()) - uint64(lookbackCap.Seconds()) + lookbackTimestamp := uint64(time.Now().Unix()) - uint64(DefaultLookbackCap.Seconds()) type args struct { h abi.ChainEpoch tskh abi.ChainEpoch @@ -96,7 +89,7 @@ func TestGatewayAPIChainGetTipSetByHeight(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { mock := &mockGatewayDepsAPI{} - a := NewNode(mock, lookbackCap, stateWaitLookbackLimit) + a := NewNode(mock, DefaultLookbackCap, DefaultStateWaitLookbackLimit) // Create tipsets from genesis up to tskh and return the highest ts := mock.createTipSets(tt.args.tskh, tt.args.genesisTS)