Merge branch 'master' into feat/other-network-images

This commit is contained in:
Cory Schwartz 2021-04-01 11:22:59 -07:00 committed by GitHub
commit 3cab4856b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
115 changed files with 4222 additions and 2015 deletions

View File

@ -388,6 +388,15 @@ jobs:
command: | command: |
curl --location https://github.com/stedolan/jq/releases/download/jq-1.6/jq-osx-amd64 --output /usr/local/bin/jq curl --location https://github.com/stedolan/jq/releases/download/jq-1.6/jq-osx-amd64 --output /usr/local/bin/jq
chmod +x /usr/local/bin/jq chmod +x /usr/local/bin/jq
- run:
name: Install hwloc
command: |
mkdir ~/hwloc
curl --location https://download.open-mpi.org/release/hwloc/v2.4/hwloc-2.4.1.tar.gz --output ~/hwloc/hwloc-2.4.1.tar.gz
cd ~/hwloc
tar -xvzpf hwloc-2.4.1.tar.gz
cd hwloc-2.4.1
./configure && make && sudo make install
- restore_cache: - restore_cache:
name: restore cargo cache name: restore cargo cache
key: v3-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.sum" }} key: v3-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.sum" }}
@ -438,9 +447,18 @@ jobs:
steps: steps:
- install-deps - install-deps
- prepare - prepare
- run: zcat build/openrpc/full.json.gz | jq > ../pre-openrpc-full
- run: zcat build/openrpc/miner.json.gz | jq > ../pre-openrpc-miner
- run: zcat build/openrpc/worker.json.gz | jq > ../pre-openrpc-worker
- run: make deps - run: make deps
- run: make docsgen - run: make docsgen
- run: zcat build/openrpc/full.json.gz | jq > ../post-openrpc-full
- run: zcat build/openrpc/miner.json.gz | jq > ../post-openrpc-miner
- run: zcat build/openrpc/worker.json.gz | jq > ../post-openrpc-worker
- run: git --no-pager diff - run: git --no-pager diff
- run: diff ../pre-openrpc-full ../post-openrpc-full
- run: diff ../pre-openrpc-miner ../post-openrpc-miner
- run: diff ../pre-openrpc-worker ../post-openrpc-worker
- run: git --no-pager diff --quiet - run: git --no-pager diff --quiet
lint: &lint lint: &lint

2
.gitignore vendored
View File

@ -14,6 +14,8 @@
/lotus-pcr /lotus-pcr
/lotus-wallet /lotus-wallet
/lotus-keygen /lotus-keygen
/docgen-md
/docgen-openrpc
/bench.json /bench.json
/lotuspond/front/node_modules /lotuspond/front/node_modules
/lotuspond/front/build /lotuspond/front/build

View File

@ -16,6 +16,12 @@ linters:
- deadcode - deadcode
- scopelint - scopelint
# We don't want to skip builtin/
skip-dirs-use-default: false
skip-dirs:
- vendor$
- testdata$
- examples$
issues: issues:
exclude: exclude:

View File

@ -1,5 +1,15 @@
# Lotus changelog # Lotus changelog
# 1.5.3 / 2021-03-24
This is a patch release of Lotus that introduces small fixes to the Storage FSM.
## Changes
- storagefsm: Fix double unlock with ready WaitDeals sectors (https://github.com/filecoin-project/lotus/pull/5783)
- backupds: Allow larger values in write log (https://github.com/filecoin-project/lotus/pull/5776)
- storagefsm: Don't log the SectorRestart event (https://github.com/filecoin-project/lotus/pull/5779)
# 1.5.2 / 2021-03-11 # 1.5.2 / 2021-03-11
This is an hotfix release of Lotus that fixes a critical bug introduced in v1.5.1 in the miner windowPoSt logic. This upgrade is only affecting miner nodes. This is an hotfix release of Lotus that fixes a critical bug introduced in v1.5.1 in the miner windowPoSt logic. This upgrade is only affecting miner nodes.

View File

@ -325,12 +325,41 @@ type-gen:
method-gen: method-gen:
(cd ./lotuspond/front/src/chain && go run ./methodgen.go) (cd ./lotuspond/front/src/chain && go run ./methodgen.go)
gen: type-gen method-gen api-gen:
go run ./gen/api > api/apistruct/struct.go
goimports -w api/apistruct
goimports -w api/apistruct
.PHONY: api-gen
docsgen: docsgen: docsgen-md docsgen-openrpc
go run ./api/docgen "api/api_full.go" "FullNode" > documentation/en/api-methods.md
go run ./api/docgen "api/api_storage.go" "StorageMiner" > documentation/en/api-methods-miner.md docsgen-md-bin:
go run ./api/docgen "api/api_worker.go" "WorkerAPI" > documentation/en/api-methods-worker.md go build $(GOFLAGS) -o docgen-md ./api/docgen/cmd
docsgen-openrpc-bin:
go build $(GOFLAGS) -o docgen-openrpc ./api/docgen-openrpc/cmd
docsgen-md: docsgen-md-full docsgen-md-storage docsgen-md-worker
docsgen-md-full: docsgen-md-bin
./docgen-md "api/api_full.go" "FullNode" > documentation/en/api-methods.md
docsgen-md-storage: docsgen-md-bin
./docgen-md "api/api_storage.go" "StorageMiner" > documentation/en/api-methods-miner.md
docsgen-md-worker: docsgen-md-bin
./docgen-md "api/api_worker.go" "Worker" > documentation/en/api-methods-worker.md
docsgen-openrpc: docsgen-openrpc-full docsgen-openrpc-storage docsgen-openrpc-worker
docsgen-openrpc-full: docsgen-openrpc-bin
./docgen-openrpc "api/api_full.go" "FullNode" -gzip > build/openrpc/full.json.gz
docsgen-openrpc-storage: docsgen-openrpc-bin
./docgen-openrpc "api/api_storage.go" "StorageMiner" -gzip > build/openrpc/miner.json.gz
docsgen-openrpc-worker: docsgen-openrpc-bin
./docgen-openrpc "api/api_worker.go" "Worker" -gzip > build/openrpc/worker.json.gz
.PHONY: docsgen docsgen-md-bin docsgen-openrpc-bin
gen: type-gen method-gen docsgen api-gen
.PHONY: gen
print-%: print-%:
@echo $*=$($*) @echo $*=$($*)

View File

@ -11,63 +11,68 @@ import (
"github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
protocol "github.com/libp2p/go-libp2p-core/protocol" protocol "github.com/libp2p/go-libp2p-core/protocol"
apitypes "github.com/filecoin-project/lotus/api/types"
) )
type Common interface { type Common interface {
// MethodGroup: Auth // MethodGroup: Auth
AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) //perm:read
AuthNew(ctx context.Context, perms []auth.Permission) ([]byte, error) AuthNew(ctx context.Context, perms []auth.Permission) ([]byte, error) //perm:admin
// MethodGroup: Net // MethodGroup: Net
NetConnectedness(context.Context, peer.ID) (network.Connectedness, error) NetConnectedness(context.Context, peer.ID) (network.Connectedness, error) //perm:read
NetPeers(context.Context) ([]peer.AddrInfo, error) NetPeers(context.Context) ([]peer.AddrInfo, error) //perm:read
NetConnect(context.Context, peer.AddrInfo) error NetConnect(context.Context, peer.AddrInfo) error //perm:write
NetAddrsListen(context.Context) (peer.AddrInfo, error) NetAddrsListen(context.Context) (peer.AddrInfo, error) //perm:read
NetDisconnect(context.Context, peer.ID) error NetDisconnect(context.Context, peer.ID) error //perm:write
NetFindPeer(context.Context, peer.ID) (peer.AddrInfo, error) NetFindPeer(context.Context, peer.ID) (peer.AddrInfo, error) //perm:read
NetPubsubScores(context.Context) ([]PubsubScore, error) NetPubsubScores(context.Context) ([]PubsubScore, error) //perm:read
NetAutoNatStatus(context.Context) (NatInfo, error) NetAutoNatStatus(context.Context) (NatInfo, error) //perm:read
NetAgentVersion(ctx context.Context, p peer.ID) (string, error) NetAgentVersion(ctx context.Context, p peer.ID) (string, error) //perm:read
NetPeerInfo(context.Context, peer.ID) (*ExtendedPeerInfo, error) NetPeerInfo(context.Context, peer.ID) (*ExtendedPeerInfo, error) //perm:read
// NetBandwidthStats returns statistics about the nodes total bandwidth // NetBandwidthStats returns statistics about the nodes total bandwidth
// usage and current rate across all peers and protocols. // usage and current rate across all peers and protocols.
NetBandwidthStats(ctx context.Context) (metrics.Stats, error) NetBandwidthStats(ctx context.Context) (metrics.Stats, error) //perm:read
// NetBandwidthStatsByPeer returns statistics about the nodes bandwidth // NetBandwidthStatsByPeer returns statistics about the nodes bandwidth
// usage and current rate per peer // usage and current rate per peer
NetBandwidthStatsByPeer(ctx context.Context) (map[string]metrics.Stats, error) NetBandwidthStatsByPeer(ctx context.Context) (map[string]metrics.Stats, error) //perm:read
// NetBandwidthStatsByProtocol returns statistics about the nodes bandwidth // NetBandwidthStatsByProtocol returns statistics about the nodes bandwidth
// usage and current rate per protocol // usage and current rate per protocol
NetBandwidthStatsByProtocol(ctx context.Context) (map[protocol.ID]metrics.Stats, error) NetBandwidthStatsByProtocol(ctx context.Context) (map[protocol.ID]metrics.Stats, error) //perm:read
// ConnectionGater API // ConnectionGater API
NetBlockAdd(ctx context.Context, acl NetBlockList) error NetBlockAdd(ctx context.Context, acl NetBlockList) error //perm:admin
NetBlockRemove(ctx context.Context, acl NetBlockList) error NetBlockRemove(ctx context.Context, acl NetBlockList) error //perm:admin
NetBlockList(ctx context.Context) (NetBlockList, error) NetBlockList(ctx context.Context) (NetBlockList, error) //perm:read
// MethodGroup: Common // MethodGroup: Common
// Discover returns an OpenRPC document describing an RPC API.
Discover(ctx context.Context) (apitypes.OpenRPCDocument, error) //perm:read
// ID returns peerID of libp2p node backing this API // ID returns peerID of libp2p node backing this API
ID(context.Context) (peer.ID, error) ID(context.Context) (peer.ID, error) //perm:read
// Version provides information about API provider // Version provides information about API provider
Version(context.Context) (APIVersion, error) Version(context.Context) (APIVersion, error) //perm:read
LogList(context.Context) ([]string, error) LogList(context.Context) ([]string, error) //perm:write
LogSetLevel(context.Context, string, string) error LogSetLevel(context.Context, string, string) error //perm:write
// trigger graceful shutdown // trigger graceful shutdown
Shutdown(context.Context) error Shutdown(context.Context) error //perm:admin
// Session returns a random UUID of api provider session // Session returns a random UUID of api provider session
Session(context.Context) (uuid.UUID, error) Session(context.Context) (uuid.UUID, error) //perm:read
Closing(context.Context) (<-chan struct{}, error) Closing(context.Context) (<-chan struct{}, error) //perm:read
} }
// APIVersion provides various build-time information // APIVersion provides various build-time information

View File

@ -6,14 +6,12 @@ import (
"fmt" "fmt"
"time" "time"
datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-state-types/network"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-bitfield"
datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/retrievalmarket"
"github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-multistore" "github.com/filecoin-project/go-multistore"
@ -21,11 +19,12 @@ import (
"github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/go-state-types/dline"
apitypes "github.com/filecoin-project/lotus/api/types"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/market" "github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/power" "github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
marketevents "github.com/filecoin-project/lotus/markets/loggers" marketevents "github.com/filecoin-project/lotus/markets/loggers"
@ -50,67 +49,78 @@ type FullNode interface {
// ChainNotify returns channel with chain head updates. // ChainNotify returns channel with chain head updates.
// First message is guaranteed to be of len == 1, and type == 'current'. // First message is guaranteed to be of len == 1, and type == 'current'.
ChainNotify(context.Context) (<-chan []*HeadChange, error) ChainNotify(context.Context) (<-chan []*HeadChange, error) //perm:read
// ChainHead returns the current head of the chain. // ChainHead returns the current head of the chain.
ChainHead(context.Context) (*types.TipSet, error) ChainHead(context.Context) (*types.TipSet, error) //perm:read
// ChainGetRandomnessFromTickets is used to sample the chain for randomness. // ChainGetRandomnessFromTickets is used to sample the chain for randomness.
ChainGetRandomnessFromTickets(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) ChainGetRandomnessFromTickets(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) //perm:read
// ChainGetRandomnessFromBeacon is used to sample the beacon for randomness. // ChainGetRandomnessFromBeacon is used to sample the beacon for randomness.
ChainGetRandomnessFromBeacon(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) ChainGetRandomnessFromBeacon(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) //perm:read
// ChainGetBlock returns the block specified by the given CID. // ChainGetBlock returns the block specified by the given CID.
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error) ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error) //perm:read
// ChainGetTipSet returns the tipset specified by the given TipSetKey. // ChainGetTipSet returns the tipset specified by the given TipSetKey.
ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error) ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error) //perm:read
// ChainGetBlockMessages returns messages stored in the specified block. // ChainGetBlockMessages returns messages stored in the specified block.
ChainGetBlockMessages(ctx context.Context, blockCid cid.Cid) (*BlockMessages, error) //
// Note: If there are multiple blocks in a tipset, it's likely that some
// messages will be duplicated. It's also possible for blocks in a tipset to have
// different messages from the same sender at the same nonce. When that happens,
// only the first message (in a block with lowest ticket) will be considered
// for execution
//
// NOTE: THIS METHOD SHOULD ONLY BE USED FOR GETTING MESSAGES IN A SPECIFIC BLOCK
//
// DO NOT USE THIS METHOD TO GET MESSAGES INCLUDED IN A TIPSET
// Use ChainGetParentMessages, which will perform correct message deduplication
ChainGetBlockMessages(ctx context.Context, blockCid cid.Cid) (*BlockMessages, error) //perm:read
// ChainGetParentReceipts returns receipts for messages in parent tipset of // ChainGetParentReceipts returns receipts for messages in parent tipset of
// the specified block. The receipts in the list returned is one-to-one with the // the specified block. The receipts in the list returned is one-to-one with the
// messages returned by a call to ChainGetParentMessages with the same blockCid. // messages returned by a call to ChainGetParentMessages with the same blockCid.
ChainGetParentReceipts(ctx context.Context, blockCid cid.Cid) ([]*types.MessageReceipt, error) ChainGetParentReceipts(ctx context.Context, blockCid cid.Cid) ([]*types.MessageReceipt, error) //perm:read
// ChainGetParentMessages returns messages stored in parent tipset of the // ChainGetParentMessages returns messages stored in parent tipset of the
// specified block. // specified block.
ChainGetParentMessages(ctx context.Context, blockCid cid.Cid) ([]Message, error) ChainGetParentMessages(ctx context.Context, blockCid cid.Cid) ([]Message, error) //perm:read
// ChainGetTipSetByHeight looks back for a tipset at the specified epoch. // ChainGetTipSetByHeight looks back for a tipset at the specified epoch.
// If there are no blocks at the specified epoch, a tipset at an earlier epoch // If there are no blocks at the specified epoch, a tipset at an earlier epoch
// will be returned. // will be returned.
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) //perm:read
// ChainReadObj reads ipld nodes referenced by the specified CID from chain // ChainReadObj reads ipld nodes referenced by the specified CID from chain
// blockstore and returns raw bytes. // blockstore and returns raw bytes.
ChainReadObj(context.Context, cid.Cid) ([]byte, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error) //perm:read
// ChainDeleteObj deletes node referenced by the given CID // ChainDeleteObj deletes node referenced by the given CID
ChainDeleteObj(context.Context, cid.Cid) error ChainDeleteObj(context.Context, cid.Cid) error //perm:admin
// ChainHasObj checks if a given CID exists in the chain blockstore. // ChainHasObj checks if a given CID exists in the chain blockstore.
ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHasObj(context.Context, cid.Cid) (bool, error) //perm:read
// ChainStatObj returns statistics about the graph referenced by 'obj'. // ChainStatObj returns statistics about the graph referenced by 'obj'.
// If 'base' is also specified, then the returned stat will be a diff // If 'base' is also specified, then the returned stat will be a diff
// between the two objects. // between the two objects.
ChainStatObj(ctx context.Context, obj cid.Cid, base cid.Cid) (ObjStat, error) ChainStatObj(ctx context.Context, obj cid.Cid, base cid.Cid) (ObjStat, error) //perm:read
// ChainSetHead forcefully sets current chain head. Use with caution. // ChainSetHead forcefully sets current chain head. Use with caution.
ChainSetHead(context.Context, types.TipSetKey) error ChainSetHead(context.Context, types.TipSetKey) error //perm:admin
// ChainGetGenesis returns the genesis tipset. // ChainGetGenesis returns the genesis tipset.
ChainGetGenesis(context.Context) (*types.TipSet, error) ChainGetGenesis(context.Context) (*types.TipSet, error) //perm:read
// ChainTipSetWeight computes weight for the specified tipset. // ChainTipSetWeight computes weight for the specified tipset.
ChainTipSetWeight(context.Context, types.TipSetKey) (types.BigInt, error) ChainTipSetWeight(context.Context, types.TipSetKey) (types.BigInt, error) //perm:read
ChainGetNode(ctx context.Context, p string) (*IpldObject, error) ChainGetNode(ctx context.Context, p string) (*IpldObject, error) //perm:read
// ChainGetMessage reads a message referenced by the specified CID from the // ChainGetMessage reads a message referenced by the specified CID from the
// chain blockstore. // chain blockstore.
ChainGetMessage(context.Context, cid.Cid) (*types.Message, error) ChainGetMessage(context.Context, cid.Cid) (*types.Message, error) //perm:read
// ChainGetPath returns a set of revert/apply operations needed to get from // ChainGetPath returns a set of revert/apply operations needed to get from
// one tipset to another, for example: // one tipset to another, for example:
@ -125,14 +135,14 @@ type FullNode interface {
// tRR // tRR
//``` //```
// Would return `[revert(tBA), apply(tAB), apply(tAA)]` // Would return `[revert(tBA), apply(tAB), apply(tAA)]`
ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*HeadChange, error) ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*HeadChange, error) //perm:read
// ChainExport returns a stream of bytes with CAR dump of chain data. // ChainExport returns a stream of bytes with CAR dump of chain data.
// The exported chain data includes the header chain from the given tipset // The exported chain data includes the header chain from the given tipset
// back to genesis, the entire genesis state, and the most recent 'nroots' // back to genesis, the entire genesis state, and the most recent 'nroots'
// state trees. // state trees.
// If oldmsgskip is set, messages from before the requested roots are also not included. // If oldmsgskip is set, messages from before the requested roots are also not included.
ChainExport(ctx context.Context, nroots abi.ChainEpoch, oldmsgskip bool, tsk types.TipSetKey) (<-chan []byte, error) ChainExport(ctx context.Context, nroots abi.ChainEpoch, oldmsgskip bool, tsk types.TipSetKey) (<-chan []byte, error) //perm:read
// MethodGroup: Beacon // MethodGroup: Beacon
// The Beacon method group contains methods for interacting with the random beacon (DRAND) // The Beacon method group contains methods for interacting with the random beacon (DRAND)
@ -140,74 +150,74 @@ type FullNode interface {
// BeaconGetEntry returns the beacon entry for the given filecoin epoch. If // BeaconGetEntry returns the beacon entry for the given filecoin epoch. If
// the entry has not yet been produced, the call will block until the entry // the entry has not yet been produced, the call will block until the entry
// becomes available // becomes available
BeaconGetEntry(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) BeaconGetEntry(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) //perm:read
// GasEstimateFeeCap estimates gas fee cap // GasEstimateFeeCap estimates gas fee cap
GasEstimateFeeCap(context.Context, *types.Message, int64, types.TipSetKey) (types.BigInt, error) GasEstimateFeeCap(context.Context, *types.Message, int64, types.TipSetKey) (types.BigInt, error) //perm:read
// GasEstimateGasLimit estimates gas used by the message and returns it. // GasEstimateGasLimit estimates gas used by the message and returns it.
// It fails if message fails to execute. // It fails if message fails to execute.
GasEstimateGasLimit(context.Context, *types.Message, types.TipSetKey) (int64, error) GasEstimateGasLimit(context.Context, *types.Message, types.TipSetKey) (int64, error) //perm:read
// GasEstimateGasPremium estimates what gas price should be used for a // GasEstimateGasPremium estimates what gas price should be used for a
// message to have high likelihood of inclusion in `nblocksincl` epochs. // message to have high likelihood of inclusion in `nblocksincl` epochs.
GasEstimateGasPremium(_ context.Context, nblocksincl uint64, GasEstimateGasPremium(_ context.Context, nblocksincl uint64,
sender address.Address, gaslimit int64, tsk types.TipSetKey) (types.BigInt, error) sender address.Address, gaslimit int64, tsk types.TipSetKey) (types.BigInt, error) //perm:read
// GasEstimateMessageGas estimates gas values for unset message gas fields // GasEstimateMessageGas estimates gas values for unset message gas fields
GasEstimateMessageGas(context.Context, *types.Message, *MessageSendSpec, types.TipSetKey) (*types.Message, error) GasEstimateMessageGas(context.Context, *types.Message, *MessageSendSpec, types.TipSetKey) (*types.Message, error) //perm:read
// MethodGroup: Sync // MethodGroup: Sync
// The Sync method group contains methods for interacting with and // The Sync method group contains methods for interacting with and
// observing the lotus sync service. // observing the lotus sync service.
// SyncState returns the current status of the lotus sync system. // SyncState returns the current status of the lotus sync system.
SyncState(context.Context) (*SyncState, error) SyncState(context.Context) (*SyncState, error) //perm:read
// SyncSubmitBlock can be used to submit a newly created block to the. // SyncSubmitBlock can be used to submit a newly created block to the.
// network through this node // network through this node
SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error //perm:write
// SyncIncomingBlocks returns a channel streaming incoming, potentially not // SyncIncomingBlocks returns a channel streaming incoming, potentially not
// yet synced block headers. // yet synced block headers.
SyncIncomingBlocks(ctx context.Context) (<-chan *types.BlockHeader, error) SyncIncomingBlocks(ctx context.Context) (<-chan *types.BlockHeader, error) //perm:read
// SyncCheckpoint marks a blocks as checkpointed, meaning that it won't ever fork away from it. // SyncCheckpoint marks a blocks as checkpointed, meaning that it won't ever fork away from it.
SyncCheckpoint(ctx context.Context, tsk types.TipSetKey) error SyncCheckpoint(ctx context.Context, tsk types.TipSetKey) error //perm:admin
// SyncMarkBad marks a blocks as bad, meaning that it won't ever by synced. // SyncMarkBad marks a blocks as bad, meaning that it won't ever by synced.
// Use with extreme caution. // Use with extreme caution.
SyncMarkBad(ctx context.Context, bcid cid.Cid) error SyncMarkBad(ctx context.Context, bcid cid.Cid) error //perm:admin
// SyncUnmarkBad unmarks a blocks as bad, making it possible to be validated and synced again. // SyncUnmarkBad unmarks a blocks as bad, making it possible to be validated and synced again.
SyncUnmarkBad(ctx context.Context, bcid cid.Cid) error SyncUnmarkBad(ctx context.Context, bcid cid.Cid) error //perm:admin
// SyncUnmarkAllBad purges bad block cache, making it possible to sync to chains previously marked as bad // SyncUnmarkAllBad purges bad block cache, making it possible to sync to chains previously marked as bad
SyncUnmarkAllBad(ctx context.Context) error SyncUnmarkAllBad(ctx context.Context) error //perm:admin
// SyncCheckBad checks if a block was marked as bad, and if it was, returns // SyncCheckBad checks if a block was marked as bad, and if it was, returns
// the reason. // the reason.
SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) //perm:read
// SyncValidateTipset indicates whether the provided tipset is valid or not // SyncValidateTipset indicates whether the provided tipset is valid or not
SyncValidateTipset(ctx context.Context, tsk types.TipSetKey) (bool, error) SyncValidateTipset(ctx context.Context, tsk types.TipSetKey) (bool, error) //perm:read
// MethodGroup: Mpool // MethodGroup: Mpool
// The Mpool methods are for interacting with the message pool. The message pool // The Mpool methods are for interacting with the message pool. The message pool
// manages all incoming and outgoing 'messages' going over the network. // manages all incoming and outgoing 'messages' going over the network.
// MpoolPending returns pending mempool messages. // MpoolPending returns pending mempool messages.
MpoolPending(context.Context, types.TipSetKey) ([]*types.SignedMessage, error) MpoolPending(context.Context, types.TipSetKey) ([]*types.SignedMessage, error) //perm:read
// MpoolSelect returns a list of pending messages for inclusion in the next block // MpoolSelect returns a list of pending messages for inclusion in the next block
MpoolSelect(context.Context, types.TipSetKey, float64) ([]*types.SignedMessage, error) MpoolSelect(context.Context, types.TipSetKey, float64) ([]*types.SignedMessage, error) //perm:read
// MpoolPush pushes a signed message to mempool. // MpoolPush pushes a signed message to mempool.
MpoolPush(context.Context, *types.SignedMessage) (cid.Cid, error) MpoolPush(context.Context, *types.SignedMessage) (cid.Cid, error) //perm:write
// MpoolPushUntrusted pushes a signed message to mempool from untrusted sources. // MpoolPushUntrusted pushes a signed message to mempool from untrusted sources.
MpoolPushUntrusted(context.Context, *types.SignedMessage) (cid.Cid, error) MpoolPushUntrusted(context.Context, *types.SignedMessage) (cid.Cid, error) //perm:write
// MpoolPushMessage atomically assigns a nonce, signs, and pushes a message // MpoolPushMessage atomically assigns a nonce, signs, and pushes a message
// to mempool. // to mempool.
@ -215,34 +225,34 @@ type FullNode interface {
// //
// When maxFee is set to 0, MpoolPushMessage will guess appropriate fee // When maxFee is set to 0, MpoolPushMessage will guess appropriate fee
// based on current chain conditions // based on current chain conditions
MpoolPushMessage(ctx context.Context, msg *types.Message, spec *MessageSendSpec) (*types.SignedMessage, error) MpoolPushMessage(ctx context.Context, msg *types.Message, spec *MessageSendSpec) (*types.SignedMessage, error) //perm:sign
// MpoolBatchPush batch pushes a signed message to mempool. // MpoolBatchPush batch pushes a signed message to mempool.
MpoolBatchPush(context.Context, []*types.SignedMessage) ([]cid.Cid, error) MpoolBatchPush(context.Context, []*types.SignedMessage) ([]cid.Cid, error) //perm:write
// MpoolBatchPushUntrusted batch pushes a signed message to mempool from untrusted sources. // MpoolBatchPushUntrusted batch pushes a signed message to mempool from untrusted sources.
MpoolBatchPushUntrusted(context.Context, []*types.SignedMessage) ([]cid.Cid, error) MpoolBatchPushUntrusted(context.Context, []*types.SignedMessage) ([]cid.Cid, error) //perm:write
// MpoolBatchPushMessage batch pushes a unsigned message to mempool. // MpoolBatchPushMessage batch pushes a unsigned message to mempool.
MpoolBatchPushMessage(context.Context, []*types.Message, *MessageSendSpec) ([]*types.SignedMessage, error) MpoolBatchPushMessage(context.Context, []*types.Message, *MessageSendSpec) ([]*types.SignedMessage, error) //perm:sign
// MpoolGetNonce gets next nonce for the specified sender. // MpoolGetNonce gets next nonce for the specified sender.
// Note that this method may not be atomic. Use MpoolPushMessage instead. // Note that this method may not be atomic. Use MpoolPushMessage instead.
MpoolGetNonce(context.Context, address.Address) (uint64, error) MpoolGetNonce(context.Context, address.Address) (uint64, error) //perm:read
MpoolSub(context.Context) (<-chan MpoolUpdate, error) MpoolSub(context.Context) (<-chan MpoolUpdate, error) //perm:read
// MpoolClear clears pending messages from the mpool // MpoolClear clears pending messages from the mpool
MpoolClear(context.Context, bool) error MpoolClear(context.Context, bool) error //perm:write
// MpoolGetConfig returns (a copy of) the current mpool config // MpoolGetConfig returns (a copy of) the current mpool config
MpoolGetConfig(context.Context) (*types.MpoolConfig, error) MpoolGetConfig(context.Context) (*types.MpoolConfig, error) //perm:read
// MpoolSetConfig sets the mpool config to (a copy of) the supplied config // MpoolSetConfig sets the mpool config to (a copy of) the supplied config
MpoolSetConfig(context.Context, *types.MpoolConfig) error MpoolSetConfig(context.Context, *types.MpoolConfig) error //perm:admin
// MethodGroup: Miner // MethodGroup: Miner
MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*MiningBaseInfo, error) MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*MiningBaseInfo, error) //perm:read
MinerCreateBlock(context.Context, *BlockTemplate) (*types.BlockMsg, error) MinerCreateBlock(context.Context, *BlockTemplate) (*types.BlockMsg, error) //perm:write
// // UX ? // // UX ?
@ -251,32 +261,32 @@ type FullNode interface {
// WalletNew creates a new address in the wallet with the given sigType. // WalletNew creates a new address in the wallet with the given sigType.
// Available key types: bls, secp256k1, secp256k1-ledger // Available key types: bls, secp256k1, secp256k1-ledger
// Support for numerical types: 1 - secp256k1, 2 - BLS is deprecated // Support for numerical types: 1 - secp256k1, 2 - BLS is deprecated
WalletNew(context.Context, types.KeyType) (address.Address, error) WalletNew(context.Context, types.KeyType) (address.Address, error) //perm:write
// WalletHas indicates whether the given address is in the wallet. // WalletHas indicates whether the given address is in the wallet.
WalletHas(context.Context, address.Address) (bool, error) WalletHas(context.Context, address.Address) (bool, error) //perm:write
// WalletList lists all the addresses in the wallet. // WalletList lists all the addresses in the wallet.
WalletList(context.Context) ([]address.Address, error) WalletList(context.Context) ([]address.Address, error) //perm:write
// WalletBalance returns the balance of the given address at the current head of the chain. // WalletBalance returns the balance of the given address at the current head of the chain.
WalletBalance(context.Context, address.Address) (types.BigInt, error) WalletBalance(context.Context, address.Address) (types.BigInt, error) //perm:read
// WalletSign signs the given bytes using the given address. // WalletSign signs the given bytes using the given address.
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error) WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error) //perm:sign
// WalletSignMessage signs the given message using the given address. // WalletSignMessage signs the given message using the given address.
WalletSignMessage(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) WalletSignMessage(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) //perm:sign
// WalletVerify takes an address, a signature, and some bytes, and indicates whether the signature is valid. // WalletVerify takes an address, a signature, and some bytes, and indicates whether the signature is valid.
// The address does not have to be in the wallet. // The address does not have to be in the wallet.
WalletVerify(context.Context, address.Address, []byte, *crypto.Signature) (bool, error) WalletVerify(context.Context, address.Address, []byte, *crypto.Signature) (bool, error) //perm:read
// WalletDefaultAddress returns the address marked as default in the wallet. // WalletDefaultAddress returns the address marked as default in the wallet.
WalletDefaultAddress(context.Context) (address.Address, error) WalletDefaultAddress(context.Context) (address.Address, error) //perm:write
// WalletSetDefault marks the given address as as the default one. // WalletSetDefault marks the given address as as the default one.
WalletSetDefault(context.Context, address.Address) error WalletSetDefault(context.Context, address.Address) error //perm:write
// WalletExport returns the private key of an address in the wallet. // WalletExport returns the private key of an address in the wallet.
WalletExport(context.Context, address.Address) (*types.KeyInfo, error) WalletExport(context.Context, address.Address) (*types.KeyInfo, error) //perm:admin
// WalletImport receives a KeyInfo, which includes a private key, and imports it into the wallet. // WalletImport receives a KeyInfo, which includes a private key, and imports it into the wallet.
WalletImport(context.Context, *types.KeyInfo) (address.Address, error) WalletImport(context.Context, *types.KeyInfo) (address.Address, error) //perm:admin
// WalletDelete deletes an address from the wallet. // WalletDelete deletes an address from the wallet.
WalletDelete(context.Context, address.Address) error WalletDelete(context.Context, address.Address) error //perm:admin
// WalletValidateAddress validates whether a given string can be decoded as a well-formed address // WalletValidateAddress validates whether a given string can be decoded as a well-formed address
WalletValidateAddress(context.Context, string) (address.Address, error) WalletValidateAddress(context.Context, string) (address.Address, error) //perm:read
// Other // Other
@ -285,56 +295,59 @@ type FullNode interface {
// retrieval markets as a client // retrieval markets as a client
// ClientImport imports file under the specified path into filestore. // ClientImport imports file under the specified path into filestore.
ClientImport(ctx context.Context, ref FileRef) (*ImportRes, error) ClientImport(ctx context.Context, ref FileRef) (*ImportRes, error) //perm:admin
// ClientRemoveImport removes file import // ClientRemoveImport removes file import
ClientRemoveImport(ctx context.Context, importID multistore.StoreID) error ClientRemoveImport(ctx context.Context, importID multistore.StoreID) error //perm:admin
// ClientStartDeal proposes a deal with a miner. // ClientStartDeal proposes a deal with a miner.
ClientStartDeal(ctx context.Context, params *StartDealParams) (*cid.Cid, error) ClientStartDeal(ctx context.Context, params *StartDealParams) (*cid.Cid, error) //perm:admin
// ClientGetDealInfo returns the latest information about a given deal. // ClientGetDealInfo returns the latest information about a given deal.
ClientGetDealInfo(context.Context, cid.Cid) (*DealInfo, error) ClientGetDealInfo(context.Context, cid.Cid) (*DealInfo, error) //perm:read
// ClientListDeals returns information about the deals made by the local client. // ClientListDeals returns information about the deals made by the local client.
ClientListDeals(ctx context.Context) ([]DealInfo, error) ClientListDeals(ctx context.Context) ([]DealInfo, error) //perm:write
// ClientGetDealUpdates returns the status of updated deals // ClientGetDealUpdates returns the status of updated deals
ClientGetDealUpdates(ctx context.Context) (<-chan DealInfo, error) ClientGetDealUpdates(ctx context.Context) (<-chan DealInfo, error) //perm:write
// ClientGetDealStatus returns status given a code // ClientGetDealStatus returns status given a code
ClientGetDealStatus(ctx context.Context, statusCode uint64) (string, error) ClientGetDealStatus(ctx context.Context, statusCode uint64) (string, error) //perm:read
// ClientHasLocal indicates whether a certain CID is locally stored. // ClientHasLocal indicates whether a certain CID is locally stored.
ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error) ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error) //perm:write
// ClientFindData identifies peers that have a certain file, and returns QueryOffers (one per peer). // ClientFindData identifies peers that have a certain file, and returns QueryOffers (one per peer).
ClientFindData(ctx context.Context, root cid.Cid, piece *cid.Cid) ([]QueryOffer, error) ClientFindData(ctx context.Context, root cid.Cid, piece *cid.Cid) ([]QueryOffer, error) //perm:read
// ClientMinerQueryOffer returns a QueryOffer for the specific miner and file. // ClientMinerQueryOffer returns a QueryOffer for the specific miner and file.
ClientMinerQueryOffer(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (QueryOffer, error) ClientMinerQueryOffer(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (QueryOffer, error) //perm:read
// ClientRetrieve initiates the retrieval of a file, as specified in the order. // ClientRetrieve initiates the retrieval of a file, as specified in the order.
ClientRetrieve(ctx context.Context, order RetrievalOrder, ref *FileRef) error ClientRetrieve(ctx context.Context, order RetrievalOrder, ref *FileRef) error //perm:admin
// ClientRetrieveWithEvents initiates the retrieval of a file, as specified in the order, and provides a channel // ClientRetrieveWithEvents initiates the retrieval of a file, as specified in the order, and provides a channel
// of status updates. // of status updates.
ClientRetrieveWithEvents(ctx context.Context, order RetrievalOrder, ref *FileRef) (<-chan marketevents.RetrievalEvent, error) ClientRetrieveWithEvents(ctx context.Context, order RetrievalOrder, ref *FileRef) (<-chan marketevents.RetrievalEvent, error) //perm:admin
// ClientQueryAsk returns a signed StorageAsk from the specified miner. // ClientQueryAsk returns a signed StorageAsk from the specified miner.
ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error) //perm:read
// ClientCalcCommP calculates the CommP and data size of the specified CID // ClientCalcCommP calculates the CommP and data size of the specified CID
ClientDealPieceCID(ctx context.Context, root cid.Cid) (DataCIDSize, error) ClientDealPieceCID(ctx context.Context, root cid.Cid) (DataCIDSize, error) //perm:read
// ClientCalcCommP calculates the CommP for a specified file // ClientCalcCommP calculates the CommP for a specified file
ClientCalcCommP(ctx context.Context, inpath string) (*CommPRet, error) ClientCalcCommP(ctx context.Context, inpath string) (*CommPRet, error) //perm:write
// ClientGenCar generates a CAR file for the specified file. // ClientGenCar generates a CAR file for the specified file.
ClientGenCar(ctx context.Context, ref FileRef, outpath string) error ClientGenCar(ctx context.Context, ref FileRef, outpath string) error //perm:write
// ClientDealSize calculates real deal data size // ClientDealSize calculates real deal data size
ClientDealSize(ctx context.Context, root cid.Cid) (DataSize, error) ClientDealSize(ctx context.Context, root cid.Cid) (DataSize, error) //perm:read
// ClientListTransfers returns the status of all ongoing transfers of data // ClientListTransfers returns the status of all ongoing transfers of data
ClientListDataTransfers(ctx context.Context) ([]DataTransferChannel, error) ClientListDataTransfers(ctx context.Context) ([]DataTransferChannel, error) //perm:write
ClientDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error) ClientDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error) //perm:write
// ClientRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer // ClientRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer
ClientRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error ClientRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error //perm:write
// ClientCancelDataTransfer cancels a data transfer with the given transfer ID and other peer // ClientCancelDataTransfer cancels a data transfer with the given transfer ID and other peer
ClientCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error ClientCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error //perm:write
// ClientRetrieveTryRestartInsufficientFunds attempts to restart stalled retrievals on a given payment channel // ClientRetrieveTryRestartInsufficientFunds attempts to restart stalled retrievals on a given payment channel
// which are stuck due to insufficient funds // which are stuck due to insufficient funds
ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error //perm:write
// ClientCancelRetrievalDeal cancels an ongoing retrieval deal based on DealID
ClientCancelRetrievalDeal(ctx context.Context, dealid retrievalmarket.DealID) error //perm:write
// ClientUnimport removes references to the specified file from filestore // ClientUnimport removes references to the specified file from filestore
//ClientUnimport(path string) //ClientUnimport(path string)
// ClientListImports lists imported files and their root CIDs // ClientListImports lists imported files and their root CIDs
ClientListImports(ctx context.Context) ([]Import, error) ClientListImports(ctx context.Context) ([]Import, error) //perm:write
//ClientListAsks() []Ask //ClientListAsks() []Ask
@ -348,60 +361,75 @@ type FullNode interface {
// StateCall applies the message to the tipset's parent state. The // StateCall applies the message to the tipset's parent state. The
// message is not applied on-top-of the messages in the passed-in // message is not applied on-top-of the messages in the passed-in
// tipset. // tipset.
StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error) StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error) //perm:read
// StateReplay replays a given message, assuming it was included in a block in the specified tipset. // StateReplay replays a given message, assuming it was included in a block in the specified tipset.
// If no tipset key is provided, the appropriate tipset is looked up. //
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error) // If a tipset key is provided, and a replacing message is found on chain,
// the method will return an error saying that the message wasn't found
//
// If no tipset key is provided, the appropriate tipset is looked up, and if
// the message was gas-repriced, the on-chain message will be replayed - in
// that case the returned InvocResult.MsgCid will not match the Cid param
//
// If the caller wants to ensure that exactly the requested message was executed,
// they MUST check that InvocResult.MsgCid is equal to the provided Cid.
// Without this check both the requested and original message may appear as
// successfully executed on-chain, which may look like a double-spend.
//
// A replacing message is a message with a different CID, any of Gas values, and
// different signature, but with all other parameters matching (source/destination,
// nonce, params, etc.)
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error) //perm:read
// StateGetActor returns the indicated actor's nonce and balance. // StateGetActor returns the indicated actor's nonce and balance.
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) //perm:read
// StateReadState returns the indicated actor's state. // StateReadState returns the indicated actor's state.
StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*ActorState, error) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*ActorState, error) //perm:read
// StateListMessages looks back and returns all messages with a matching to or from address, stopping at the given height. // StateListMessages looks back and returns all messages with a matching to or from address, stopping at the given height.
StateListMessages(ctx context.Context, match *MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) StateListMessages(ctx context.Context, match *MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) //perm:read
// StateDecodeParams attempts to decode the provided params, based on the recipient actor address and method number. // StateDecodeParams attempts to decode the provided params, based on the recipient actor address and method number.
StateDecodeParams(ctx context.Context, toAddr address.Address, method abi.MethodNum, params []byte, tsk types.TipSetKey) (interface{}, error) StateDecodeParams(ctx context.Context, toAddr address.Address, method abi.MethodNum, params []byte, tsk types.TipSetKey) (interface{}, error) //perm:read
// StateNetworkName returns the name of the network the node is synced to // StateNetworkName returns the name of the network the node is synced to
StateNetworkName(context.Context) (dtypes.NetworkName, error) StateNetworkName(context.Context) (dtypes.NetworkName, error) //perm:read
// StateMinerSectors returns info about the given miner's sectors. If the filter bitfield is nil, all sectors are included. // StateMinerSectors returns info about the given miner's sectors. If the filter bitfield is nil, all sectors are included.
StateMinerSectors(context.Context, address.Address, *bitfield.BitField, types.TipSetKey) ([]*miner.SectorOnChainInfo, error) StateMinerSectors(context.Context, address.Address, *bitfield.BitField, types.TipSetKey) ([]*miner.SectorOnChainInfo, error) //perm:read
// StateMinerActiveSectors returns info about sectors that a given miner is actively proving. // StateMinerActiveSectors returns info about sectors that a given miner is actively proving.
StateMinerActiveSectors(context.Context, address.Address, types.TipSetKey) ([]*miner.SectorOnChainInfo, error) StateMinerActiveSectors(context.Context, address.Address, types.TipSetKey) ([]*miner.SectorOnChainInfo, error) //perm:read
// StateMinerProvingDeadline calculates the deadline at some epoch for a proving period // StateMinerProvingDeadline calculates the deadline at some epoch for a proving period
// and returns the deadline-related calculations. // and returns the deadline-related calculations.
StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) //perm:read
// StateMinerPower returns the power of the indicated miner // StateMinerPower returns the power of the indicated miner
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error) //perm:read
// StateMinerInfo returns info about the indicated miner // StateMinerInfo returns info about the indicated miner
StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) //perm:read
// StateMinerDeadlines returns all the proving deadlines for the given miner // StateMinerDeadlines returns all the proving deadlines for the given miner
StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]Deadline, error) StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]Deadline, error) //perm:read
// StateMinerPartitions returns all partitions in the specified deadline // StateMinerPartitions returns all partitions in the specified deadline
StateMinerPartitions(ctx context.Context, m address.Address, dlIdx uint64, tsk types.TipSetKey) ([]Partition, error) StateMinerPartitions(ctx context.Context, m address.Address, dlIdx uint64, tsk types.TipSetKey) ([]Partition, error) //perm:read
// StateMinerFaults returns a bitfield indicating the faulty sectors of the given miner // StateMinerFaults returns a bitfield indicating the faulty sectors of the given miner
StateMinerFaults(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) StateMinerFaults(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) //perm:read
// StateAllMinerFaults returns all non-expired Faults that occur within lookback epochs of the given tipset // StateAllMinerFaults returns all non-expired Faults that occur within lookback epochs of the given tipset
StateAllMinerFaults(ctx context.Context, lookback abi.ChainEpoch, ts types.TipSetKey) ([]*Fault, error) StateAllMinerFaults(ctx context.Context, lookback abi.ChainEpoch, ts types.TipSetKey) ([]*Fault, error) //perm:read
// StateMinerRecoveries returns a bitfield indicating the recovering sectors of the given miner // StateMinerRecoveries returns a bitfield indicating the recovering sectors of the given miner
StateMinerRecoveries(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) StateMinerRecoveries(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) //perm:read
// StateMinerInitialPledgeCollateral returns the precommit deposit for the specified miner's sector // StateMinerInitialPledgeCollateral returns the precommit deposit for the specified miner's sector
StateMinerPreCommitDepositForPower(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (types.BigInt, error) StateMinerPreCommitDepositForPower(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (types.BigInt, error) //perm:read
// StateMinerInitialPledgeCollateral returns the initial pledge collateral for the specified miner's sector // StateMinerInitialPledgeCollateral returns the initial pledge collateral for the specified miner's sector
StateMinerInitialPledgeCollateral(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (types.BigInt, error) StateMinerInitialPledgeCollateral(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (types.BigInt, error) //perm:read
// StateMinerAvailableBalance returns the portion of a miner's balance that can be withdrawn or spent // StateMinerAvailableBalance returns the portion of a miner's balance that can be withdrawn or spent
StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) //perm:read
// StateMinerSectorAllocated checks if a sector is allocated // StateMinerSectorAllocated checks if a sector is allocated
StateMinerSectorAllocated(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (bool, error) StateMinerSectorAllocated(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (bool, error) //perm:read
// StateSectorPreCommitInfo returns the PreCommit info for the specified miner's sector // StateSectorPreCommitInfo returns the PreCommit info for the specified miner's sector
StateSectorPreCommitInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) StateSectorPreCommitInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) //perm:read
// StateSectorGetInfo returns the on-chain info for the specified miner's sector. Returns null in case the sector info isn't found // StateSectorGetInfo returns the on-chain info for the specified miner's sector. Returns null in case the sector info isn't found
// NOTE: returned info.Expiration may not be accurate in some cases, use StateSectorExpiration to get accurate // NOTE: returned info.Expiration may not be accurate in some cases, use StateSectorExpiration to get accurate
// expiration epoch // expiration epoch
StateSectorGetInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error) StateSectorGetInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error) //perm:read
// StateSectorExpiration returns epoch at which given sector will expire // StateSectorExpiration returns epoch at which given sector will expire
StateSectorExpiration(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorExpiration, error) StateSectorExpiration(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorExpiration, error) //perm:read
// StateSectorPartition finds deadline/partition with the specified sector // StateSectorPartition finds deadline/partition with the specified sector
StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*miner.SectorLocation, error) StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*miner.SectorLocation, error) //perm:read
// StateSearchMsg searches for a message in the chain, and returns its receipt and the tipset where it was executed // StateSearchMsg searches for a message in the chain, and returns its receipt and the tipset where it was executed
// //
// NOTE: If a replacing message is found on chain, this method will return // NOTE: If a replacing message is found on chain, this method will return
@ -417,7 +445,7 @@ type FullNode interface {
// A replacing message is a message with a different CID, any of Gas values, and // A replacing message is a message with a different CID, any of Gas values, and
// different signature, but with all other parameters matching (source/destination, // different signature, but with all other parameters matching (source/destination,
// nonce, params, etc.) // nonce, params, etc.)
StateSearchMsg(context.Context, cid.Cid) (*MsgLookup, error) StateSearchMsg(context.Context, cid.Cid) (*MsgLookup, error) //perm:read
// StateSearchMsgLimited looks back up to limit epochs in the chain for a message, and returns its receipt and the tipset where it was executed // StateSearchMsgLimited looks back up to limit epochs in the chain for a message, and returns its receipt and the tipset where it was executed
// //
// NOTE: If a replacing message is found on chain, this method will return // NOTE: If a replacing message is found on chain, this method will return
@ -433,7 +461,7 @@ type FullNode interface {
// A replacing message is a message with a different CID, any of Gas values, and // A replacing message is a message with a different CID, any of Gas values, and
// different signature, but with all other parameters matching (source/destination, // different signature, but with all other parameters matching (source/destination,
// nonce, params, etc.) // nonce, params, etc.)
StateSearchMsgLimited(ctx context.Context, msg cid.Cid, limit abi.ChainEpoch) (*MsgLookup, error) StateSearchMsgLimited(ctx context.Context, msg cid.Cid, limit abi.ChainEpoch) (*MsgLookup, error) //perm:read
// StateWaitMsg looks back in the chain for a message. If not found, it blocks until the // StateWaitMsg looks back in the chain for a message. If not found, it blocks until the
// message arrives on chain, and gets to the indicated confidence depth. // message arrives on chain, and gets to the indicated confidence depth.
// //
@ -450,7 +478,7 @@ type FullNode interface {
// A replacing message is a message with a different CID, any of Gas values, and // A replacing message is a message with a different CID, any of Gas values, and
// different signature, but with all other parameters matching (source/destination, // different signature, but with all other parameters matching (source/destination,
// nonce, params, etc.) // nonce, params, etc.)
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error) StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error) //perm:read
// StateWaitMsgLimited looks back up to limit epochs in the chain for a message. // StateWaitMsgLimited looks back up to limit epochs in the chain for a message.
// If not found, it blocks until the message arrives on chain, and gets to the // If not found, it blocks until the message arrives on chain, and gets to the
// indicated confidence depth. // indicated confidence depth.
@ -468,93 +496,123 @@ type FullNode interface {
// A replacing message is a message with a different CID, any of Gas values, and // A replacing message is a message with a different CID, any of Gas values, and
// different signature, but with all other parameters matching (source/destination, // different signature, but with all other parameters matching (source/destination,
// nonce, params, etc.) // nonce, params, etc.)
StateWaitMsgLimited(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch) (*MsgLookup, error) StateWaitMsgLimited(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch) (*MsgLookup, error) //perm:read
// StateListMiners returns the addresses of every miner that has claimed power in the Power Actor // StateListMiners returns the addresses of every miner that has claimed power in the Power Actor
StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error) StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error) //perm:read
// StateListActors returns the addresses of every actor in the state // StateListActors returns the addresses of every actor in the state
StateListActors(context.Context, types.TipSetKey) ([]address.Address, error) StateListActors(context.Context, types.TipSetKey) ([]address.Address, error) //perm:read
// StateMarketBalance looks up the Escrow and Locked balances of the given address in the Storage Market // StateMarketBalance looks up the Escrow and Locked balances of the given address in the Storage Market
StateMarketBalance(context.Context, address.Address, types.TipSetKey) (MarketBalance, error) StateMarketBalance(context.Context, address.Address, types.TipSetKey) (MarketBalance, error) //perm:read
// StateMarketParticipants returns the Escrow and Locked balances of every participant in the Storage Market // StateMarketParticipants returns the Escrow and Locked balances of every participant in the Storage Market
StateMarketParticipants(context.Context, types.TipSetKey) (map[string]MarketBalance, error) StateMarketParticipants(context.Context, types.TipSetKey) (map[string]MarketBalance, error) //perm:read
// StateMarketDeals returns information about every deal in the Storage Market // StateMarketDeals returns information about every deal in the Storage Market
StateMarketDeals(context.Context, types.TipSetKey) (map[string]MarketDeal, error) StateMarketDeals(context.Context, types.TipSetKey) (map[string]MarketDeal, error) //perm:read
// StateMarketStorageDeal returns information about the indicated deal // StateMarketStorageDeal returns information about the indicated deal
StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*MarketDeal, error) StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*MarketDeal, error) //perm:read
// StateLookupID retrieves the ID address of the given address // StateLookupID retrieves the ID address of the given address
StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error) StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error) //perm:read
// StateAccountKey returns the public key address of the given ID address // StateAccountKey returns the public key address of the given ID address
StateAccountKey(context.Context, address.Address, types.TipSetKey) (address.Address, error) StateAccountKey(context.Context, address.Address, types.TipSetKey) (address.Address, error) //perm:read
// StateChangedActors returns all the actors whose states change between the two given state CIDs // StateChangedActors returns all the actors whose states change between the two given state CIDs
// TODO: Should this take tipset keys instead? // TODO: Should this take tipset keys instead?
StateChangedActors(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) StateChangedActors(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) //perm:read
// StateGetReceipt returns the message receipt for the given message or for a // StateGetReceipt returns the message receipt for the given message or for a
// matching gas-repriced replacing message // matching gas-repriced replacing message
// //
// NOTE: If the requested message was replaced, this method will return the receipt // NOTE: If the requested message was replaced, this method will return the receipt
// for the replacing message - if the caller needs the receipt for exactly the // for the replacing message - if the caller needs the receipt for exactly the
// requested message, use StateSearchMsg().Receipt, and check that MsgLookup.Message // requested message, use StateSearchMsg().Receipt, and check that MsgLookup.Message
// is matching the requseted CID // is matching the requested CID
// //
// DEPRECATED: Use StateSearchMsg, this method won't be supported in v1 API // DEPRECATED: Use StateSearchMsg, this method won't be supported in v1 API
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) //perm:read
// StateMinerSectorCount returns the number of sectors in a miner's sector set and proving set // StateMinerSectorCount returns the number of sectors in a miner's sector set and proving set
StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error) StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error) //perm:read
// StateCompute is a flexible command that applies the given messages on the given tipset. // StateCompute is a flexible command that applies the given messages on the given tipset.
// The messages are run as though the VM were at the provided height. // The messages are run as though the VM were at the provided height.
StateCompute(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*ComputeStateOutput, error) //
// When called, StateCompute will:
// - Load the provided tipset, or use the current chain head if not provided
// - Compute the tipset state of the provided tipset on top of the parent state
// - (note that this step runs before vmheight is applied to the execution)
// - Execute state upgrade if any were scheduled at the epoch, or in null
// blocks preceding the tipset
// - Call the cron actor on null blocks preceding the tipset
// - For each block in the tipset
// - Apply messages in blocks in the specified
// - Award block reward by calling the reward actor
// - Call the cron actor for the current epoch
// - If the specified vmheight is higher than the current epoch, apply any
// needed state upgrades to the state
// - Apply the specified messages to the state
//
// The vmheight parameter sets VM execution epoch, and can be used to simulate
// message execution in different network versions. If the specified vmheight
// epoch is higher than the epoch of the specified tipset, any state upgrades
// until the vmheight will be executed on the state before applying messages
// specified by the user.
//
// Note that the initial tipset state computation is not affected by the
// vmheight parameter - only the messages in the `apply` set are
//
// If the caller wants to simply compute the state, vmheight should be set to
// the epoch of the specified tipset.
//
// Messages in the `apply` parameter must have the correct nonces, and gas
// values set.
StateCompute(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*ComputeStateOutput, error) //perm:read
// StateVerifierStatus returns the data cap for the given address. // StateVerifierStatus returns the data cap for the given address.
// Returns nil if there is no entry in the data cap table for the // Returns nil if there is no entry in the data cap table for the
// address. // address.
StateVerifierStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) StateVerifierStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) //perm:read
// StateVerifiedClientStatus returns the data cap for the given address. // StateVerifiedClientStatus returns the data cap for the given address.
// Returns nil if there is no entry in the data cap table for the // Returns nil if there is no entry in the data cap table for the
// address. // address.
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) //perm:read
// StateVerifiedClientStatus returns the address of the Verified Registry's root key // StateVerifiedClientStatus returns the address of the Verified Registry's root key
StateVerifiedRegistryRootKey(ctx context.Context, tsk types.TipSetKey) (address.Address, error) StateVerifiedRegistryRootKey(ctx context.Context, tsk types.TipSetKey) (address.Address, error) //perm:read
// 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.
StateDealProviderCollateralBounds(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (DealCollateralBounds, error) StateDealProviderCollateralBounds(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (DealCollateralBounds, error) //perm:read
// StateCirculatingSupply returns the exact circulating supply of Filecoin at the given tipset. // StateCirculatingSupply returns the exact circulating supply of Filecoin at the given tipset.
// This is not used anywhere in the protocol itself, and is only for external consumption. // This is not used anywhere in the protocol itself, and is only for external consumption.
StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) //perm:read
// StateVMCirculatingSupplyInternal returns an approximation of the circulating supply of Filecoin at the given tipset. // StateVMCirculatingSupplyInternal returns an approximation of the circulating supply of Filecoin at the given tipset.
// This is the value reported by the runtime interface to actors code. // This is the value reported by the runtime interface to actors code.
StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (CirculatingSupply, error) StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (CirculatingSupply, error) //perm:read
// StateNetworkVersion returns the network version at the given tipset // StateNetworkVersion returns the network version at the given tipset
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error) StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, error) //perm:read
// MethodGroup: Msig // MethodGroup: Msig
// The Msig methods are used to interact with multisig wallets on the // The Msig methods are used to interact with multisig wallets on the
// filecoin network // filecoin network
// MsigGetAvailableBalance returns the portion of a multisig's balance that can be withdrawn or spent // MsigGetAvailableBalance returns the portion of a multisig's balance that can be withdrawn or spent
MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) //perm:read
// MsigGetVestingSchedule returns the vesting details of a given multisig. // MsigGetVestingSchedule returns the vesting details of a given multisig.
MsigGetVestingSchedule(context.Context, address.Address, types.TipSetKey) (MsigVesting, error) MsigGetVestingSchedule(context.Context, address.Address, types.TipSetKey) (MsigVesting, error) //perm:read
// MsigGetVested returns the amount of FIL that vested in a multisig in a certain period. // MsigGetVested returns the amount of FIL that vested in a multisig in a certain period.
// It takes the following params: <multisig address>, <start epoch>, <end epoch> // It takes the following params: <multisig address>, <start epoch>, <end epoch>
MsigGetVested(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) MsigGetVested(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) //perm:read
//MsigGetPending returns pending transactions for the given multisig //MsigGetPending returns pending transactions for the given multisig
//wallet. Once pending transactions are fully approved, they will no longer //wallet. Once pending transactions are fully approved, they will no longer
//appear here. //appear here.
MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*MsigTransaction, error) MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*MsigTransaction, error) //perm:read
// MsigCreate creates a multisig wallet // MsigCreate creates a multisig wallet
// It takes the following params: <required number of senders>, <approving addresses>, <unlock duration> // It takes the following params: <required number of senders>, <approving addresses>, <unlock duration>
//<initial balance>, <sender address of the create msg>, <gas price> //<initial balance>, <sender address of the create msg>, <gas price>
MsigCreate(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) MsigCreate(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) //perm:sign
// MsigPropose proposes a multisig message // MsigPropose proposes a multisig message
// It takes the following params: <multisig address>, <recipient address>, <value to transfer>, // It takes the following params: <multisig address>, <recipient address>, <value to transfer>,
// <sender address of the propose msg>, <method to call in the proposed message>, <params to include in the proposed message> // <sender address of the propose msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigPropose(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) MsigPropose(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) //perm:sign
// MsigApprove approves a previously-proposed multisig message by transaction ID // MsigApprove approves a previously-proposed multisig message by transaction ID
// It takes the following params: <multisig address>, <proposed transaction ID> <signer address> // It takes the following params: <multisig address>, <proposed transaction ID> <signer address>
MsigApprove(context.Context, address.Address, uint64, address.Address) (cid.Cid, error) MsigApprove(context.Context, address.Address, uint64, address.Address) (cid.Cid, error) //perm:sign
// MsigApproveTxnHash approves a previously-proposed multisig message, specified // MsigApproveTxnHash approves a previously-proposed multisig message, specified
// using both transaction ID and a hash of the parameters used in the // using both transaction ID and a hash of the parameters used in the
@ -562,80 +620,80 @@ type FullNode interface {
// exactly the transaction you think you are. // exactly the transaction you think you are.
// It takes the following params: <multisig address>, <proposed message ID>, <proposer address>, <recipient address>, <value to transfer>, // It takes the following params: <multisig address>, <proposed message ID>, <proposer address>, <recipient address>, <value to transfer>,
// <sender address of the approve msg>, <method to call in the proposed message>, <params to include in the proposed message> // <sender address of the approve msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigApproveTxnHash(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) MsigApproveTxnHash(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) //perm:sign
// MsigCancel cancels a previously-proposed multisig message // MsigCancel cancels a previously-proposed multisig message
// It takes the following params: <multisig address>, <proposed transaction ID>, <recipient address>, <value to transfer>, // It takes the following params: <multisig address>, <proposed transaction ID>, <recipient address>, <value to transfer>,
// <sender address of the cancel msg>, <method to call in the proposed message>, <params to include in the proposed message> // <sender address of the cancel msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigCancel(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) MsigCancel(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) //perm:sign
// MsigAddPropose proposes adding a signer in the multisig // MsigAddPropose proposes adding a signer in the multisig
// It takes the following params: <multisig address>, <sender address of the propose msg>, // It takes the following params: <multisig address>, <sender address of the propose msg>,
// <new signer>, <whether the number of required signers should be increased> // <new signer>, <whether the number of required signers should be increased>
MsigAddPropose(context.Context, address.Address, address.Address, address.Address, bool) (cid.Cid, error) MsigAddPropose(context.Context, address.Address, address.Address, address.Address, bool) (cid.Cid, error) //perm:sign
// MsigAddApprove approves a previously proposed AddSigner message // MsigAddApprove approves a previously proposed AddSigner message
// It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>, // It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
// <proposer address>, <new signer>, <whether the number of required signers should be increased> // <proposer address>, <new signer>, <whether the number of required signers should be increased>
MsigAddApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, bool) (cid.Cid, error) MsigAddApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, bool) (cid.Cid, error) //perm:sign
// MsigAddCancel cancels a previously proposed AddSigner message // MsigAddCancel cancels a previously proposed AddSigner message
// It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>, // It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
// <new signer>, <whether the number of required signers should be increased> // <new signer>, <whether the number of required signers should be increased>
MsigAddCancel(context.Context, address.Address, address.Address, uint64, address.Address, bool) (cid.Cid, error) MsigAddCancel(context.Context, address.Address, address.Address, uint64, address.Address, bool) (cid.Cid, error) //perm:sign
// MsigSwapPropose proposes swapping 2 signers in the multisig // MsigSwapPropose proposes swapping 2 signers in the multisig
// It takes the following params: <multisig address>, <sender address of the propose msg>, // It takes the following params: <multisig address>, <sender address of the propose msg>,
// <old signer>, <new signer> // <old signer>, <new signer>
MsigSwapPropose(context.Context, address.Address, address.Address, address.Address, address.Address) (cid.Cid, error) MsigSwapPropose(context.Context, address.Address, address.Address, address.Address, address.Address) (cid.Cid, error) //perm:sign
// MsigSwapApprove approves a previously proposed SwapSigner // MsigSwapApprove approves a previously proposed SwapSigner
// It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>, // It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
// <proposer address>, <old signer>, <new signer> // <proposer address>, <old signer>, <new signer>
MsigSwapApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, address.Address) (cid.Cid, error) MsigSwapApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, address.Address) (cid.Cid, error) //perm:sign
// MsigSwapCancel cancels a previously proposed SwapSigner message // MsigSwapCancel cancels a previously proposed SwapSigner message
// It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>, // It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
// <old signer>, <new signer> // <old signer>, <new signer>
MsigSwapCancel(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error) MsigSwapCancel(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error) //perm:sign
// MsigRemoveSigner proposes the removal of a signer from the multisig. // MsigRemoveSigner proposes the removal of a signer from the multisig.
// It accepts the multisig to make the change on, the proposer address to // It accepts the multisig to make the change on, the proposer address to
// send the message from, the address to be removed, and a boolean // send the message from, the address to be removed, and a boolean
// indicating whether or not the signing threshold should be lowered by one // indicating whether or not the signing threshold should be lowered by one
// along with the address removal. // along with the address removal.
MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error) MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error) //perm:sign
// MarketAddBalance adds funds to the market actor // MarketAddBalance adds funds to the market actor
MarketAddBalance(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) MarketAddBalance(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) //perm:sign
// MarketGetReserved gets the amount of funds that are currently reserved for the address // MarketGetReserved gets the amount of funds that are currently reserved for the address
MarketGetReserved(ctx context.Context, addr address.Address) (types.BigInt, error) MarketGetReserved(ctx context.Context, addr address.Address) (types.BigInt, error) //perm:sign
// MarketReserveFunds reserves funds for a deal // MarketReserveFunds reserves funds for a deal
MarketReserveFunds(ctx context.Context, wallet address.Address, addr address.Address, amt types.BigInt) (cid.Cid, error) MarketReserveFunds(ctx context.Context, wallet address.Address, addr address.Address, amt types.BigInt) (cid.Cid, error) //perm:sign
// MarketReleaseFunds releases funds reserved by MarketReserveFunds // MarketReleaseFunds releases funds reserved by MarketReserveFunds
MarketReleaseFunds(ctx context.Context, addr address.Address, amt types.BigInt) error MarketReleaseFunds(ctx context.Context, addr address.Address, amt types.BigInt) error //perm:sign
// MarketWithdraw withdraws unlocked funds from the market actor // MarketWithdraw withdraws unlocked funds from the market actor
MarketWithdraw(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) MarketWithdraw(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) //perm:sign
// MethodGroup: Paych // MethodGroup: Paych
// The Paych methods are for interacting with and managing payment channels // The Paych methods are for interacting with and managing payment channels
PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*ChannelInfo, error) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*ChannelInfo, error) //perm:sign
PaychGetWaitReady(context.Context, cid.Cid) (address.Address, error) PaychGetWaitReady(context.Context, cid.Cid) (address.Address, error) //perm:sign
PaychAvailableFunds(ctx context.Context, ch address.Address) (*ChannelAvailableFunds, error) PaychAvailableFunds(ctx context.Context, ch address.Address) (*ChannelAvailableFunds, error) //perm:sign
PaychAvailableFundsByFromTo(ctx context.Context, from, to address.Address) (*ChannelAvailableFunds, error) PaychAvailableFundsByFromTo(ctx context.Context, from, to address.Address) (*ChannelAvailableFunds, error) //perm:sign
PaychList(context.Context) ([]address.Address, error) PaychList(context.Context) ([]address.Address, error) //perm:read
PaychStatus(context.Context, address.Address) (*PaychStatus, error) PaychStatus(context.Context, address.Address) (*PaychStatus, error) //perm:read
PaychSettle(context.Context, address.Address) (cid.Cid, error) PaychSettle(context.Context, address.Address) (cid.Cid, error) //perm:sign
PaychCollect(context.Context, address.Address) (cid.Cid, error) PaychCollect(context.Context, address.Address) (cid.Cid, error) //perm:sign
PaychAllocateLane(ctx context.Context, ch address.Address) (uint64, error) PaychAllocateLane(ctx context.Context, ch address.Address) (uint64, error) //perm:sign
PaychNewPayment(ctx context.Context, from, to address.Address, vouchers []VoucherSpec) (*PaymentInfo, error) PaychNewPayment(ctx context.Context, from, to address.Address, vouchers []VoucherSpec) (*PaymentInfo, error) //perm:sign
PaychVoucherCheckValid(context.Context, address.Address, *paych.SignedVoucher) error PaychVoucherCheckValid(context.Context, address.Address, *paych.SignedVoucher) error //perm:read
PaychVoucherCheckSpendable(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (bool, error) PaychVoucherCheckSpendable(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (bool, error) //perm:read
PaychVoucherCreate(context.Context, address.Address, types.BigInt, uint64) (*VoucherCreateResult, error) PaychVoucherCreate(context.Context, address.Address, types.BigInt, uint64) (*VoucherCreateResult, error) //perm:sign
PaychVoucherAdd(context.Context, address.Address, *paych.SignedVoucher, []byte, types.BigInt) (types.BigInt, error) PaychVoucherAdd(context.Context, address.Address, *paych.SignedVoucher, []byte, types.BigInt) (types.BigInt, error) //perm:write
PaychVoucherList(context.Context, address.Address) ([]*paych.SignedVoucher, error) PaychVoucherList(context.Context, address.Address) ([]*paych.SignedVoucher, error) //perm:write
PaychVoucherSubmit(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (cid.Cid, error) PaychVoucherSubmit(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (cid.Cid, error) //perm:sign
// CreateBackup creates node backup onder the specified file name. The // CreateBackup creates node backup onder the specified file name. The
// method requires that the lotus daemon is running with the // method requires that the lotus daemon is running with the
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that // LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
// the path specified when calling CreateBackup is within the base path // the path specified when calling CreateBackup is within the base path
CreateBackup(ctx context.Context, fpath string) error CreateBackup(ctx context.Context, fpath string) error //perm:admin
} }
type FileRef struct { type FileRef struct {
@ -670,6 +728,7 @@ type DealInfo struct {
ProposalCid cid.Cid ProposalCid cid.Cid
State storagemarket.StorageDealStatus State storagemarket.StorageDealStatus
Message string // more information about deal state, particularly errors Message string // more information about deal state, particularly errors
DealStages *storagemarket.DealStages
Provider address.Address Provider address.Address
DataRef *storagemarket.DataRef DataRef *storagemarket.DataRef

View File

@ -8,13 +8,13 @@ import (
"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/dline"
"github.com/filecoin-project/go-state-types/network"
apitypes "github.com/filecoin-project/lotus/api/types"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
type GatewayAPI interface { type Gateway 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) ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
@ -39,7 +39,7 @@ type GatewayAPI interface {
StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, 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) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error)
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error) StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, error)
StateSearchMsg(ctx context.Context, msg cid.Cid) (*MsgLookup, error) StateSearchMsg(ctx context.Context, msg cid.Cid) (*MsgLookup, error)
StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, 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) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)

View File

@ -5,6 +5,8 @@ import (
"context" "context"
"time" "time"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
@ -28,124 +30,150 @@ import (
type StorageMiner interface { type StorageMiner interface {
Common Common
ActorAddress(context.Context) (address.Address, error) ActorAddress(context.Context) (address.Address, error) //perm:read
ActorSectorSize(context.Context, address.Address) (abi.SectorSize, error) ActorSectorSize(context.Context, address.Address) (abi.SectorSize, error) //perm:read
ActorAddressConfig(ctx context.Context) (AddressConfig, error) ActorAddressConfig(ctx context.Context) (AddressConfig, error) //perm:read
MiningBase(context.Context) (*types.TipSet, error) MiningBase(context.Context) (*types.TipSet, error) //perm:read
// Temp api for testing // Temp api for testing
PledgeSector(context.Context) (abi.SectorID, error) PledgeSector(context.Context) (abi.SectorID, error) //perm:write
// Get the status of a given sector by ID // Get the status of a given sector by ID
SectorsStatus(ctx context.Context, sid abi.SectorNumber, showOnChainInfo bool) (SectorInfo, error) SectorsStatus(ctx context.Context, sid abi.SectorNumber, showOnChainInfo bool) (SectorInfo, error) //perm:read
// List all staged sectors // List all staged sectors
SectorsList(context.Context) ([]abi.SectorNumber, error) SectorsList(context.Context) ([]abi.SectorNumber, error) //perm:read
// Get summary info of sectors // Get summary info of sectors
SectorsSummary(ctx context.Context) (map[SectorState]int, error) SectorsSummary(ctx context.Context) (map[SectorState]int, error) //perm:read
// List sectors in particular states // List sectors in particular states
SectorsListInStates(context.Context, []SectorState) ([]abi.SectorNumber, error) SectorsListInStates(context.Context, []SectorState) ([]abi.SectorNumber, error) //perm:read
SectorsRefs(context.Context) (map[string][]SealedRef, error) SectorsRefs(context.Context) (map[string][]SealedRef, error) //perm:read
// SectorStartSealing can be called on sectors in Empty or WaitDeals states // SectorStartSealing can be called on sectors in Empty or WaitDeals states
// to trigger sealing early // to trigger sealing early
SectorStartSealing(context.Context, abi.SectorNumber) error SectorStartSealing(context.Context, abi.SectorNumber) error //perm:write
// SectorSetSealDelay sets the time that a newly-created sector // SectorSetSealDelay sets the time that a newly-created sector
// waits for more deals before it starts sealing // waits for more deals before it starts sealing
SectorSetSealDelay(context.Context, time.Duration) error SectorSetSealDelay(context.Context, time.Duration) error //perm:write
// SectorGetSealDelay gets the time that a newly-created sector // SectorGetSealDelay gets the time that a newly-created sector
// waits for more deals before it starts sealing // waits for more deals before it starts sealing
SectorGetSealDelay(context.Context) (time.Duration, error) SectorGetSealDelay(context.Context) (time.Duration, error) //perm:read
// SectorSetExpectedSealDuration sets the expected time for a sector to seal // SectorSetExpectedSealDuration sets the expected time for a sector to seal
SectorSetExpectedSealDuration(context.Context, time.Duration) error SectorSetExpectedSealDuration(context.Context, time.Duration) error //perm:write
// SectorGetExpectedSealDuration gets the expected time for a sector to seal // SectorGetExpectedSealDuration gets the expected time for a sector to seal
SectorGetExpectedSealDuration(context.Context) (time.Duration, error) SectorGetExpectedSealDuration(context.Context) (time.Duration, error) //perm:read
SectorsUpdate(context.Context, abi.SectorNumber, SectorState) error SectorsUpdate(context.Context, abi.SectorNumber, SectorState) error //perm:admin
// SectorRemove removes the sector from storage. It doesn't terminate it on-chain, which can // SectorRemove removes the sector from storage. It doesn't terminate it on-chain, which can
// be done with SectorTerminate. Removing and not terminating live sectors will cause additional penalties. // be done with SectorTerminate. Removing and not terminating live sectors will cause additional penalties.
SectorRemove(context.Context, abi.SectorNumber) error SectorRemove(context.Context, abi.SectorNumber) error //perm:admin
// SectorTerminate terminates the sector on-chain (adding it to a termination batch first), then // SectorTerminate terminates the sector on-chain (adding it to a termination batch first), then
// automatically removes it from storage // automatically removes it from storage
SectorTerminate(context.Context, abi.SectorNumber) error SectorTerminate(context.Context, abi.SectorNumber) error //perm:admin
// SectorTerminateFlush immediately sends a terminate message with sectors batched for termination. // SectorTerminateFlush immediately sends a terminate message with sectors batched for termination.
// Returns null if message wasn't sent // Returns null if message wasn't sent
SectorTerminateFlush(ctx context.Context) (*cid.Cid, error) SectorTerminateFlush(ctx context.Context) (*cid.Cid, error) //perm:admin
// SectorTerminatePending returns a list of pending sector terminations to be sent in the next batch message // SectorTerminatePending returns a list of pending sector terminations to be sent in the next batch message
SectorTerminatePending(ctx context.Context) ([]abi.SectorID, error) SectorTerminatePending(ctx context.Context) ([]abi.SectorID, error) //perm:admin
SectorMarkForUpgrade(ctx context.Context, id abi.SectorNumber) error SectorMarkForUpgrade(ctx context.Context, id abi.SectorNumber) error //perm:admin
StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error)
StorageLocal(ctx context.Context) (map[stores.ID]string, error)
StorageStat(ctx context.Context, id stores.ID) (fsutil.FsStat, error)
// WorkerConnect tells the node to connect to workers RPC // WorkerConnect tells the node to connect to workers RPC
WorkerConnect(context.Context, string) error WorkerConnect(context.Context, string) error //perm:admin retry:true
WorkerStats(context.Context) (map[uuid.UUID]storiface.WorkerStats, error) WorkerStats(context.Context) (map[uuid.UUID]storiface.WorkerStats, error) //perm:admin
WorkerJobs(context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) WorkerJobs(context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) //perm:admin
storiface.WorkerReturn
//storiface.WorkerReturn
ReturnAddPiece(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err *storiface.CallError) error //perm:admin retry:true
ReturnSealPreCommit1(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err *storiface.CallError) error //perm:admin retry:true
ReturnSealPreCommit2(ctx context.Context, callID storiface.CallID, sealed storage.SectorCids, err *storiface.CallError) error //perm:admin retry:true
ReturnSealCommit1(ctx context.Context, callID storiface.CallID, out storage.Commit1Out, err *storiface.CallError) error //perm:admin retry:true
ReturnSealCommit2(ctx context.Context, callID storiface.CallID, proof storage.Proof, err *storiface.CallError) error //perm:admin retry:true
ReturnFinalizeSector(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
ReturnReleaseUnsealed(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
ReturnMoveStorage(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
ReturnUnsealPiece(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
ReturnReadPiece(ctx context.Context, callID storiface.CallID, ok bool, err *storiface.CallError) error //perm:admin retry:true
ReturnFetch(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true
// SealingSchedDiag dumps internal sealing scheduler state // SealingSchedDiag dumps internal sealing scheduler state
SealingSchedDiag(ctx context.Context, doSched bool) (interface{}, error) SealingSchedDiag(ctx context.Context, doSched bool) (interface{}, error) //perm:admin
SealingAbort(ctx context.Context, call storiface.CallID) error SealingAbort(ctx context.Context, call storiface.CallID) error //perm:admin
stores.SectorIndex //stores.SectorIndex
StorageAttach(context.Context, stores.StorageInfo, fsutil.FsStat) error //perm:admin
StorageInfo(context.Context, stores.ID) (stores.StorageInfo, error) //perm:admin
StorageReportHealth(context.Context, stores.ID, stores.HealthReport) error //perm:admin
StorageDeclareSector(ctx context.Context, storageID stores.ID, s abi.SectorID, ft storiface.SectorFileType, primary bool) error //perm:admin
StorageDropSector(ctx context.Context, storageID stores.ID, s abi.SectorID, ft storiface.SectorFileType) error //perm:admin
StorageFindSector(ctx context.Context, sector abi.SectorID, ft storiface.SectorFileType, ssize abi.SectorSize, allowFetch bool) ([]stores.SectorStorageInfo, error) //perm:admin
StorageBestAlloc(ctx context.Context, allocate storiface.SectorFileType, ssize abi.SectorSize, pathType storiface.PathType) ([]stores.StorageInfo, error) //perm:admin
StorageLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) error //perm:admin
StorageTryLock(ctx context.Context, sector abi.SectorID, read storiface.SectorFileType, write storiface.SectorFileType) (bool, error) //perm:admin
MarketImportDealData(ctx context.Context, propcid cid.Cid, path string) error StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error) //perm:admin
MarketListDeals(ctx context.Context) ([]MarketDeal, error) StorageLocal(ctx context.Context) (map[stores.ID]string, error) //perm:admin
MarketListRetrievalDeals(ctx context.Context) ([]retrievalmarket.ProviderDealState, error) StorageStat(ctx context.Context, id stores.ID) (fsutil.FsStat, error) //perm:admin
MarketGetDealUpdates(ctx context.Context) (<-chan storagemarket.MinerDeal, error)
MarketListIncompleteDeals(ctx context.Context) ([]storagemarket.MinerDeal, error) MarketImportDealData(ctx context.Context, propcid cid.Cid, path string) error //perm:write
MarketSetAsk(ctx context.Context, price types.BigInt, verifiedPrice types.BigInt, duration abi.ChainEpoch, minPieceSize abi.PaddedPieceSize, maxPieceSize abi.PaddedPieceSize) error MarketListDeals(ctx context.Context) ([]MarketDeal, error) //perm:read
MarketGetAsk(ctx context.Context) (*storagemarket.SignedStorageAsk, error) MarketListRetrievalDeals(ctx context.Context) ([]retrievalmarket.ProviderDealState, error) //perm:read
MarketSetRetrievalAsk(ctx context.Context, rask *retrievalmarket.Ask) error MarketGetDealUpdates(ctx context.Context) (<-chan storagemarket.MinerDeal, error) //perm:read
MarketGetRetrievalAsk(ctx context.Context) (*retrievalmarket.Ask, error) MarketListIncompleteDeals(ctx context.Context) ([]storagemarket.MinerDeal, error) //perm:read
MarketListDataTransfers(ctx context.Context) ([]DataTransferChannel, error) MarketSetAsk(ctx context.Context, price types.BigInt, verifiedPrice types.BigInt, duration abi.ChainEpoch, minPieceSize abi.PaddedPieceSize, maxPieceSize abi.PaddedPieceSize) error //perm:admin
MarketDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error) MarketGetAsk(ctx context.Context) (*storagemarket.SignedStorageAsk, error) //perm:read
MarketSetRetrievalAsk(ctx context.Context, rask *retrievalmarket.Ask) error //perm:admin
MarketGetRetrievalAsk(ctx context.Context) (*retrievalmarket.Ask, error) //perm:read
MarketListDataTransfers(ctx context.Context) ([]DataTransferChannel, error) //perm:write
MarketDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error) //perm:write
// MarketRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer // MarketRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer
MarketRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error MarketRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error //perm:write
// MarketCancelDataTransfer cancels a data transfer with the given transfer ID and other peer // MarketCancelDataTransfer cancels a data transfer with the given transfer ID and other peer
MarketCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error MarketCancelDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error //perm:write
MarketPendingDeals(ctx context.Context) (PendingDealInfo, error) MarketPendingDeals(ctx context.Context) (PendingDealInfo, error) //perm:write
MarketPublishPendingDeals(ctx context.Context) error MarketPublishPendingDeals(ctx context.Context) error //perm:admin
DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error //perm:admin
DealsList(ctx context.Context) ([]MarketDeal, error) DealsList(ctx context.Context) ([]MarketDeal, error) //perm:admin
DealsConsiderOnlineStorageDeals(context.Context) (bool, error) DealsConsiderOnlineStorageDeals(context.Context) (bool, error) //perm:admin
DealsSetConsiderOnlineStorageDeals(context.Context, bool) error DealsSetConsiderOnlineStorageDeals(context.Context, bool) error //perm:admin
DealsConsiderOnlineRetrievalDeals(context.Context) (bool, error) DealsConsiderOnlineRetrievalDeals(context.Context) (bool, error) //perm:admin
DealsSetConsiderOnlineRetrievalDeals(context.Context, bool) error DealsSetConsiderOnlineRetrievalDeals(context.Context, bool) error //perm:admin
DealsPieceCidBlocklist(context.Context) ([]cid.Cid, error) DealsPieceCidBlocklist(context.Context) ([]cid.Cid, error) //perm:admin
DealsSetPieceCidBlocklist(context.Context, []cid.Cid) error DealsSetPieceCidBlocklist(context.Context, []cid.Cid) error //perm:admin
DealsConsiderOfflineStorageDeals(context.Context) (bool, error) DealsConsiderOfflineStorageDeals(context.Context) (bool, error) //perm:admin
DealsSetConsiderOfflineStorageDeals(context.Context, bool) error DealsSetConsiderOfflineStorageDeals(context.Context, bool) error //perm:admin
DealsConsiderOfflineRetrievalDeals(context.Context) (bool, error) DealsConsiderOfflineRetrievalDeals(context.Context) (bool, error) //perm:admin
DealsSetConsiderOfflineRetrievalDeals(context.Context, bool) error DealsSetConsiderOfflineRetrievalDeals(context.Context, bool) error //perm:admin
DealsConsiderVerifiedStorageDeals(context.Context) (bool, error) DealsConsiderVerifiedStorageDeals(context.Context) (bool, error) //perm:admin
DealsSetConsiderVerifiedStorageDeals(context.Context, bool) error DealsSetConsiderVerifiedStorageDeals(context.Context, bool) error //perm:admin
DealsConsiderUnverifiedStorageDeals(context.Context) (bool, error) DealsConsiderUnverifiedStorageDeals(context.Context) (bool, error) //perm:admin
DealsSetConsiderUnverifiedStorageDeals(context.Context, bool) error DealsSetConsiderUnverifiedStorageDeals(context.Context, bool) error //perm:admin
StorageAddLocal(ctx context.Context, path string) error StorageAddLocal(ctx context.Context, path string) error //perm:admin
PiecesListPieces(ctx context.Context) ([]cid.Cid, error) PiecesListPieces(ctx context.Context) ([]cid.Cid, error) //perm:read
PiecesListCidInfos(ctx context.Context) ([]cid.Cid, error) PiecesListCidInfos(ctx context.Context) ([]cid.Cid, error) //perm:read
PiecesGetPieceInfo(ctx context.Context, pieceCid cid.Cid) (*piecestore.PieceInfo, error) PiecesGetPieceInfo(ctx context.Context, pieceCid cid.Cid) (*piecestore.PieceInfo, error) //perm:read
PiecesGetCIDInfo(ctx context.Context, payloadCid cid.Cid) (*piecestore.CIDInfo, error) PiecesGetCIDInfo(ctx context.Context, payloadCid cid.Cid) (*piecestore.CIDInfo, error) //perm:read
// CreateBackup creates node backup onder the specified file name. The // CreateBackup creates node backup onder the specified file name. The
// method requires that the lotus-miner is running with the // method requires that the lotus-miner is running with the
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that // LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
// the path specified when calling CreateBackup is within the base path // the path specified when calling CreateBackup is within the base path
CreateBackup(ctx context.Context, fpath string) error CreateBackup(ctx context.Context, fpath string) error //perm:admin
CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef, expensive bool) (map[abi.SectorNumber]string, error) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef, expensive bool) (map[abi.SectorNumber]string, error) //perm:admin
ComputeProof(ctx context.Context, ssi []builtin.SectorInfo, rand abi.PoStRandomness) ([]builtin.PoStProof, error) //perm:read
} }
var _ storiface.WorkerReturn = *new(StorageMiner)
var _ stores.SectorIndex = *new(StorageMiner)
type SealRes struct { type SealRes struct {
Err string Err string
GoErr error `json:"-"` GoErr error `json:"-"`

View File

@ -37,6 +37,18 @@ func TestDoesntDependOnFFI(t *testing.T) {
} }
} }
func TestDoesntDependOnBuild(t *testing.T) {
deps, err := exec.Command(goCmd(), "list", "-deps", "github.com/filecoin-project/lotus/api").Output()
if err != nil {
t.Fatal(err)
}
for _, pkg := range strings.Fields(string(deps)) {
if pkg == "github.com/filecoin-project/build" {
t.Fatal("api depends on filecoin-ffi")
}
}
}
func TestReturnTypes(t *testing.T) { func TestReturnTypes(t *testing.T) {
errType := reflect.TypeOf(new(error)).Elem() errType := reflect.TypeOf(new(error)).Elem()
bareIface := reflect.TypeOf(new(interface{})).Elem() bareIface := reflect.TypeOf(new(interface{})).Elem()
@ -99,5 +111,5 @@ func TestReturnTypes(t *testing.T) {
t.Run("common", tst(new(Common))) t.Run("common", tst(new(Common)))
t.Run("full", tst(new(FullNode))) t.Run("full", tst(new(FullNode)))
t.Run("miner", tst(new(StorageMiner))) t.Run("miner", tst(new(StorageMiner)))
t.Run("worker", tst(new(WorkerAPI))) t.Run("worker", tst(new(Worker)))
} }

View File

@ -34,7 +34,7 @@ type MsgMeta struct {
Extra []byte Extra []byte
} }
type WalletAPI interface { type Wallet interface {
WalletNew(context.Context, types.KeyType) (address.Address, error) WalletNew(context.Context, types.KeyType) (address.Address, error)
WalletHas(context.Context, address.Address) (bool, error) WalletHas(context.Context, address.Address) (bool, error)
WalletList(context.Context) ([]address.Address, error) WalletList(context.Context) ([]address.Address, error)

View File

@ -2,46 +2,62 @@ package api
import ( import (
"context" "context"
"io"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks"
"github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/extern/sector-storage/stores"
"github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/lotus/extern/sector-storage/storiface"
"github.com/filecoin-project/specs-storage/storage"
) )
type WorkerAPI interface { type Worker interface {
Version(context.Context) (Version, error) Version(context.Context) (Version, error) //perm:admin
// TODO: Info() (name, ...) ?
TaskTypes(context.Context) (map[sealtasks.TaskType]struct{}, error) // TaskType -> Weight // TaskType -> Weight
Paths(context.Context) ([]stores.StoragePath, error) TaskTypes(context.Context) (map[sealtasks.TaskType]struct{}, error) //perm:admin
Info(context.Context) (storiface.WorkerInfo, error) Paths(context.Context) ([]stores.StoragePath, error) //perm:admin
Info(context.Context) (storiface.WorkerInfo, error) //perm:admin
storiface.WorkerCalls // storiface.WorkerCalls
AddPiece(ctx context.Context, sector storage.SectorRef, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage.Data) (storiface.CallID, error) //perm:admin
SealPreCommit1(ctx context.Context, sector storage.SectorRef, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) //perm:admin
SealPreCommit2(ctx context.Context, sector storage.SectorRef, pc1o storage.PreCommit1Out) (storiface.CallID, error) //perm:admin
SealCommit1(ctx context.Context, sector storage.SectorRef, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) //perm:admin
SealCommit2(ctx context.Context, sector storage.SectorRef, c1o storage.Commit1Out) (storiface.CallID, error) //perm:admin
FinalizeSector(ctx context.Context, sector storage.SectorRef, keepUnsealed []storage.Range) (storiface.CallID, error) //perm:admin
ReleaseUnsealed(ctx context.Context, sector storage.SectorRef, safeToFree []storage.Range) (storiface.CallID, error) //perm:admin
MoveStorage(ctx context.Context, sector storage.SectorRef, types storiface.SectorFileType) (storiface.CallID, error) //perm:admin
UnsealPiece(context.Context, storage.SectorRef, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (storiface.CallID, error) //perm:admin
ReadPiece(context.Context, io.Writer, storage.SectorRef, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) (storiface.CallID, error) //perm:admin
Fetch(context.Context, storage.SectorRef, storiface.SectorFileType, storiface.PathType, storiface.AcquireMode) (storiface.CallID, error) //perm:admin
TaskDisable(ctx context.Context, tt sealtasks.TaskType) error TaskDisable(ctx context.Context, tt sealtasks.TaskType) error //perm:admin
TaskEnable(ctx context.Context, tt sealtasks.TaskType) error TaskEnable(ctx context.Context, tt sealtasks.TaskType) error //perm:admin
// Storage / Other // Storage / Other
Remove(ctx context.Context, sector abi.SectorID) error Remove(ctx context.Context, sector abi.SectorID) error //perm:admin
StorageAddLocal(ctx context.Context, path string) error StorageAddLocal(ctx context.Context, path string) error //perm:admin
// SetEnabled marks the worker as enabled/disabled. Not that this setting // SetEnabled marks the worker as enabled/disabled. Not that this setting
// may take a few seconds to propagate to task scheduler // may take a few seconds to propagate to task scheduler
SetEnabled(ctx context.Context, enabled bool) error SetEnabled(ctx context.Context, enabled bool) error //perm:admin
Enabled(ctx context.Context) (bool, error) Enabled(ctx context.Context) (bool, error) //perm:admin
// WaitQuiet blocks until there are no tasks running // WaitQuiet blocks until there are no tasks running
WaitQuiet(ctx context.Context) error WaitQuiet(ctx context.Context) error //perm:admin
// returns a random UUID of worker session, generated randomly when worker // returns a random UUID of worker session, generated randomly when worker
// process starts // process starts
ProcessSession(context.Context) (uuid.UUID, error) ProcessSession(context.Context) (uuid.UUID, error) //perm:admin
// Like ProcessSession, but returns an error when worker is disabled // Like ProcessSession, but returns an error when worker is disabled
Session(context.Context) (uuid.UUID, error) Session(context.Context) (uuid.UUID, error) //perm:admin
} }
var _ storiface.WorkerCalls = *new(Worker)

View File

@ -31,13 +31,13 @@ func PermissionedFullAPI(a api.FullNode) api.FullNode {
return &out return &out
} }
func PermissionedWorkerAPI(a api.WorkerAPI) api.WorkerAPI { func PermissionedWorkerAPI(a api.Worker) api.Worker {
var out WorkerStruct var out WorkerStruct
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal) auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
return &out return &out
} }
func PermissionedWalletAPI(a api.WalletAPI) api.WalletAPI { func PermissionedWalletAPI(a api.Wallet) api.Wallet {
var out WalletStruct var out WalletStruct
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal) auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
return &out return &out

File diff suppressed because it is too large Load Diff

View File

@ -54,7 +54,7 @@ func NewStorageMinerRPC(ctx context.Context, addr string, requestHeader http.Hea
return &res, closer, err return &res, closer, err
} }
func NewWorkerRPC(ctx context.Context, addr string, requestHeader http.Header) (api.WorkerAPI, jsonrpc.ClientCloser, error) { func NewWorkerRPC(ctx context.Context, addr string, requestHeader http.Header) (api.Worker, jsonrpc.ClientCloser, error) {
u, err := url.Parse(addr) u, err := url.Parse(addr)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -84,7 +84,7 @@ func NewWorkerRPC(ctx context.Context, addr string, requestHeader http.Header) (
} }
// NewGatewayRPC creates a new http jsonrpc client for a gateway node. // NewGatewayRPC creates a new http jsonrpc client for a gateway node.
func NewGatewayRPC(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (api.GatewayAPI, jsonrpc.ClientCloser, error) { func NewGatewayRPC(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (api.Gateway, jsonrpc.ClientCloser, error) {
var res apistruct.GatewayStruct var res apistruct.GatewayStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin", closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{ []interface{}{
@ -97,7 +97,7 @@ func NewGatewayRPC(ctx context.Context, addr string, requestHeader http.Header,
return &res, closer, err return &res, closer, err
} }
func NewWalletRPC(ctx context.Context, addr string, requestHeader http.Header) (api.WalletAPI, jsonrpc.ClientCloser, error) { func NewWalletRPC(ctx context.Context, addr string, requestHeader http.Header) (api.Wallet, jsonrpc.ClientCloser, error) {
var res apistruct.WalletStruct var res apistruct.WalletStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin", closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{ []interface{}{

View File

@ -0,0 +1,77 @@
package main
import (
"compress/gzip"
"encoding/json"
"io"
"log"
"os"
"github.com/filecoin-project/lotus/api/apistruct"
docgen_openrpc "github.com/filecoin-project/lotus/api/docgen-openrpc"
)
/*
main defines a small program that writes an OpenRPC document describing
a Lotus API to stdout.
If the first argument is "miner", the document will describe the StorageMiner API.
If not (no, or any other args), the document will describe the Full API.
Use:
go run ./api/openrpc/cmd ["api/api_full.go"|"api/api_storage.go"|"api/api_worker.go"] ["FullNode"|"StorageMiner"|"Worker"]
With gzip compression: a '-gzip' flag is made available as an optional third argument. Note that position matters.
go run ./api/openrpc/cmd ["api/api_full.go"|"api/api_storage.go"|"api/api_worker.go"] ["FullNode"|"StorageMiner"|"Worker"] -gzip
*/
func main() {
doc := docgen_openrpc.NewLotusOpenRPCDocument()
switch os.Args[2] {
case "FullNode":
doc.RegisterReceiverName("Filecoin", &apistruct.FullNodeStruct{})
case "StorageMiner":
doc.RegisterReceiverName("Filecoin", &apistruct.StorageMinerStruct{})
case "Worker":
doc.RegisterReceiverName("Filecoin", &apistruct.WorkerStruct{})
}
out, err := doc.Discover()
if err != nil {
log.Fatalln(err)
}
var jsonOut []byte
var writer io.WriteCloser
// Use os.Args to handle a somewhat hacky flag for the gzip option.
// Could use flags package to handle this more cleanly, but that requires changes elsewhere
// the scope of which just isn't warranted by this one use case which will usually be run
// programmatically anyways.
if len(os.Args) > 3 && os.Args[3] == "-gzip" {
jsonOut, err = json.Marshal(out)
if err != nil {
log.Fatalln(err)
}
writer = gzip.NewWriter(os.Stdout)
} else {
jsonOut, err = json.MarshalIndent(out, "", " ")
if err != nil {
log.Fatalln(err)
}
writer = os.Stdout
}
_, err = writer.Write(jsonOut)
if err != nil {
log.Fatalln(err)
}
err = writer.Close()
if err != nil {
log.Fatalln(err)
}
}

View File

@ -0,0 +1,172 @@
package docgenopenrpc
import (
"encoding/json"
"go/ast"
"net"
"os"
"reflect"
"github.com/alecthomas/jsonschema"
go_openrpc_reflect "github.com/etclabscore/go-openrpc-reflect"
"github.com/filecoin-project/lotus/api/docgen"
"github.com/filecoin-project/lotus/build"
"github.com/ipfs/go-cid"
meta_schema "github.com/open-rpc/meta-schema"
)
// Comments holds API method comments collected by AST parsing.
var Comments map[string]string
// GroupDocs holds documentation for documentation groups.
var GroupDocs map[string]string
func init() {
Comments, GroupDocs = docgen.ParseApiASTInfo(os.Args[1], os.Args[2])
}
// schemaDictEntry represents a type association passed to the jsonschema reflector.
type schemaDictEntry struct {
example interface{}
rawJson string
}
const integerD = `{
"title": "number",
"type": "number",
"description": "Number is a number"
}`
const cidCidD = `{"title": "Content Identifier", "type": "string", "description": "Cid represents a self-describing content addressed identifier. It is formed by a Version, a Codec (which indicates a multicodec-packed content type) and a Multihash."}`
func OpenRPCSchemaTypeMapper(ty reflect.Type) *jsonschema.Type {
unmarshalJSONToJSONSchemaType := func(input string) *jsonschema.Type {
var js jsonschema.Type
err := json.Unmarshal([]byte(input), &js)
if err != nil {
panic(err)
}
return &js
}
if ty.Kind() == reflect.Ptr {
ty = ty.Elem()
}
if ty == reflect.TypeOf((*interface{})(nil)).Elem() {
return &jsonschema.Type{Type: "object", AdditionalProperties: []byte("true")}
}
// Second, handle other types.
// Use a slice instead of a map because it preserves order, as a logic safeguard/fallback.
dict := []schemaDictEntry{
{cid.Cid{}, cidCidD},
}
for _, d := range dict {
if reflect.TypeOf(d.example) == ty {
tt := unmarshalJSONToJSONSchemaType(d.rawJson)
return tt
}
}
// Handle primitive types in case there are generic cases
// specific to our services.
switch ty.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
// Return all integer types as the hex representation integer schemea.
ret := unmarshalJSONToJSONSchemaType(integerD)
return ret
case reflect.Uintptr:
return &jsonschema.Type{Type: "number", Title: "uintptr-title"}
case reflect.Struct:
case reflect.Map:
case reflect.Slice, reflect.Array:
case reflect.Float32, reflect.Float64:
case reflect.Bool:
case reflect.String:
case reflect.Ptr, reflect.Interface:
default:
}
return nil
}
// NewLotusOpenRPCDocument defines application-specific documentation and configuration for its OpenRPC document.
func NewLotusOpenRPCDocument() *go_openrpc_reflect.Document {
d := &go_openrpc_reflect.Document{}
// Register "Meta" document fields.
// These include getters for
// - Servers object
// - Info object
// - ExternalDocs object
//
// These objects represent server-specific data that cannot be
// reflected.
d.WithMeta(&go_openrpc_reflect.MetaT{
GetServersFn: func() func(listeners []net.Listener) (*meta_schema.Servers, error) {
return func(listeners []net.Listener) (*meta_schema.Servers, error) {
return nil, nil
}
},
GetInfoFn: func() (info *meta_schema.InfoObject) {
info = &meta_schema.InfoObject{}
title := "Lotus RPC API"
info.Title = (*meta_schema.InfoObjectProperties)(&title)
version := build.BuildVersion
info.Version = (*meta_schema.InfoObjectVersion)(&version)
return info
},
GetExternalDocsFn: func() (exdocs *meta_schema.ExternalDocumentationObject) {
return nil // FIXME
},
})
// Use a provided Ethereum default configuration as a base.
appReflector := &go_openrpc_reflect.EthereumReflectorT{}
// Install overrides for the json schema->type map fn used by the jsonschema reflect package.
appReflector.FnSchemaTypeMap = func() func(ty reflect.Type) *jsonschema.Type {
return OpenRPCSchemaTypeMapper
}
appReflector.FnIsMethodEligible = func(m reflect.Method) bool {
for i := 0; i < m.Func.Type().NumOut(); i++ {
if m.Func.Type().Out(i).Kind() == reflect.Chan {
return false
}
}
return go_openrpc_reflect.EthereumReflector.IsMethodEligible(m)
}
appReflector.FnGetMethodName = func(moduleName string, r reflect.Value, m reflect.Method, funcDecl *ast.FuncDecl) (string, error) {
if m.Name == "ID" {
return moduleName + "_ID", nil
}
if moduleName == "rpc" && m.Name == "Discover" {
return "rpc.discover", nil
}
return moduleName + "." + m.Name, nil
}
appReflector.FnGetMethodSummary = func(r reflect.Value, m reflect.Method, funcDecl *ast.FuncDecl) (string, error) {
if v, ok := Comments[m.Name]; ok {
return v, nil
}
return "", nil // noComment
}
appReflector.FnSchemaExamples = func(ty reflect.Type) (examples *meta_schema.Examples, err error) {
v := docgen.ExampleValue("unknown", ty, ty) // This isn't ideal, but seems to work well enough.
return &meta_schema.Examples{
meta_schema.AlwaysTrue(v),
}, nil
}
// Finally, register the configured reflector to the document.
d.WithReflector(appReflector)
return d
}

137
api/docgen/cmd/docgen.go Normal file
View File

@ -0,0 +1,137 @@
package main
import (
"encoding/json"
"fmt"
"os"
"reflect"
"sort"
"strings"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/api/docgen"
)
func main() {
comments, groupComments := docgen.ParseApiASTInfo(os.Args[1], os.Args[2])
groups := make(map[string]*docgen.MethodGroup)
var t reflect.Type
var permStruct, commonPermStruct reflect.Type
switch os.Args[2] {
case "FullNode":
t = reflect.TypeOf(new(struct{ api.FullNode })).Elem()
permStruct = reflect.TypeOf(apistruct.FullNodeStruct{}.Internal)
commonPermStruct = reflect.TypeOf(apistruct.CommonStruct{}.Internal)
case "StorageMiner":
t = reflect.TypeOf(new(struct{ api.StorageMiner })).Elem()
permStruct = reflect.TypeOf(apistruct.StorageMinerStruct{}.Internal)
commonPermStruct = reflect.TypeOf(apistruct.CommonStruct{}.Internal)
case "Worker":
t = reflect.TypeOf(new(struct{ api.Worker })).Elem()
permStruct = reflect.TypeOf(apistruct.WorkerStruct{}.Internal)
commonPermStruct = reflect.TypeOf(apistruct.WorkerStruct{}.Internal)
default:
panic("unknown type")
}
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
groupName := docgen.MethodGroupFromName(m.Name)
g, ok := groups[groupName]
if !ok {
g = new(docgen.MethodGroup)
g.Header = groupComments[groupName]
g.GroupName = groupName
groups[groupName] = g
}
var args []interface{}
ft := m.Func.Type()
for j := 2; j < ft.NumIn(); j++ {
inp := ft.In(j)
args = append(args, docgen.ExampleValue(m.Name, inp, nil))
}
v, err := json.MarshalIndent(args, "", " ")
if err != nil {
panic(err)
}
outv := docgen.ExampleValue(m.Name, ft.Out(0), nil)
ov, err := json.MarshalIndent(outv, "", " ")
if err != nil {
panic(err)
}
g.Methods = append(g.Methods, &docgen.Method{
Name: m.Name,
Comment: comments[m.Name],
InputExample: string(v),
ResponseExample: string(ov),
})
}
var groupslice []*docgen.MethodGroup
for _, g := range groups {
groupslice = append(groupslice, g)
}
sort.Slice(groupslice, func(i, j int) bool {
return groupslice[i].GroupName < groupslice[j].GroupName
})
fmt.Printf("# Groups\n")
for _, g := range groupslice {
fmt.Printf("* [%s](#%s)\n", g.GroupName, g.GroupName)
for _, method := range g.Methods {
fmt.Printf(" * [%s](#%s)\n", method.Name, method.Name)
}
}
for _, g := range groupslice {
g := g
fmt.Printf("## %s\n", g.GroupName)
fmt.Printf("%s\n\n", g.Header)
sort.Slice(g.Methods, func(i, j int) bool {
return g.Methods[i].Name < g.Methods[j].Name
})
for _, m := range g.Methods {
fmt.Printf("### %s\n", m.Name)
fmt.Printf("%s\n\n", m.Comment)
meth, ok := permStruct.FieldByName(m.Name)
if !ok {
meth, ok = commonPermStruct.FieldByName(m.Name)
if !ok {
panic("no perms for method: " + m.Name)
}
}
perms := meth.Tag.Get("perm")
fmt.Printf("Perms: %s\n\n", perms)
if strings.Count(m.InputExample, "\n") > 0 {
fmt.Printf("Inputs:\n```json\n%s\n```\n\n", m.InputExample)
} else {
fmt.Printf("Inputs: `%s`\n\n", m.InputExample)
}
if strings.Count(m.ResponseExample, "\n") > 0 {
fmt.Printf("Response:\n```json\n%s\n```\n\n", m.ResponseExample)
} else {
fmt.Printf("Response: `%s`\n\n", m.ResponseExample)
}
}
}
}

View File

@ -1,18 +1,18 @@
package main package docgen
import ( import (
"encoding/json"
"fmt" "fmt"
"go/ast" "go/ast"
"go/parser" "go/parser"
"go/token" "go/token"
"os" "path/filepath"
"reflect" "reflect"
"sort"
"strings" "strings"
"time" "time"
"unicode" "unicode"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/ipfs/go-filestore" "github.com/ipfs/go-filestore"
@ -23,8 +23,6 @@ import (
pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
datatransfer "github.com/filecoin-project/go-data-transfer" datatransfer "github.com/filecoin-project/go-data-transfer"
filestore2 "github.com/filecoin-project/go-fil-markets/filestore" filestore2 "github.com/filecoin-project/go-fil-markets/filestore"
"github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/retrievalmarket"
@ -36,7 +34,7 @@ import (
"github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apistruct" apitypes "github.com/filecoin-project/lotus/api/types"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks"
@ -89,6 +87,8 @@ func init() {
addExample(pid) addExample(pid)
addExample(&pid) addExample(&pid)
multistoreIDExample := multistore.StoreID(50)
addExample(bitfield.NewFromSet([]uint64{5})) addExample(bitfield.NewFromSet([]uint64{5}))
addExample(abi.RegisteredSealProof_StackedDrg32GiBV1_1) addExample(abi.RegisteredSealProof_StackedDrg32GiBV1_1)
addExample(abi.RegisteredPoStProof_StackedDrgWindow32GiBV1) addExample(abi.RegisteredPoStProof_StackedDrgWindow32GiBV1)
@ -118,7 +118,8 @@ func init() {
addExample(time.Minute) addExample(time.Minute)
addExample(datatransfer.TransferID(3)) addExample(datatransfer.TransferID(3))
addExample(datatransfer.Ongoing) addExample(datatransfer.Ongoing)
addExample(multistore.StoreID(50)) addExample(multistoreIDExample)
addExample(&multistoreIDExample)
addExample(retrievalmarket.ClientEventDealAccepted) addExample(retrievalmarket.ClientEventDealAccepted)
addExample(retrievalmarket.DealStatusNew) addExample(retrievalmarket.DealStatusNew)
addExample(network.ReachabilityPublic) addExample(network.ReachabilityPublic)
@ -126,17 +127,17 @@ func init() {
addExample(map[string]int{"name": 42}) addExample(map[string]int{"name": 42})
addExample(map[string]time.Time{"name": time.Unix(1615243938, 0).UTC()}) addExample(map[string]time.Time{"name": time.Unix(1615243938, 0).UTC()})
addExample(&types.ExecutionTrace{ addExample(&types.ExecutionTrace{
Msg: exampleValue("init", reflect.TypeOf(&types.Message{}), nil).(*types.Message), Msg: ExampleValue("init", reflect.TypeOf(&types.Message{}), nil).(*types.Message),
MsgRct: exampleValue("init", reflect.TypeOf(&types.MessageReceipt{}), nil).(*types.MessageReceipt), MsgRct: ExampleValue("init", reflect.TypeOf(&types.MessageReceipt{}), nil).(*types.MessageReceipt),
}) })
addExample(map[string]types.Actor{ addExample(map[string]types.Actor{
"t01236": exampleValue("init", reflect.TypeOf(types.Actor{}), nil).(types.Actor), "t01236": ExampleValue("init", reflect.TypeOf(types.Actor{}), nil).(types.Actor),
}) })
addExample(map[string]api.MarketDeal{ addExample(map[string]api.MarketDeal{
"t026363": exampleValue("init", reflect.TypeOf(api.MarketDeal{}), nil).(api.MarketDeal), "t026363": ExampleValue("init", reflect.TypeOf(api.MarketDeal{}), nil).(api.MarketDeal),
}) })
addExample(map[string]api.MarketBalance{ addExample(map[string]api.MarketBalance{
"t026363": exampleValue("init", reflect.TypeOf(api.MarketBalance{}), nil).(api.MarketBalance), "t026363": ExampleValue("init", reflect.TypeOf(api.MarketBalance{}), nil).(api.MarketBalance),
}) })
addExample(map[string]*pubsub.TopicScoreSnapshot{ addExample(map[string]*pubsub.TopicScoreSnapshot{
"/blocks": { "/blocks": {
@ -251,9 +252,17 @@ func init() {
sealtasks.TTPreCommit2: {}, sealtasks.TTPreCommit2: {},
}) })
addExample(sealtasks.TTCommit2) addExample(sealtasks.TTCommit2)
addExample(apitypes.OpenRPCDocument{
"openrpc": "1.2.6",
"info": map[string]interface{}{
"title": "Lotus RPC API",
"version": "1.2.1/generated=2020-11-22T08:22:42-06:00",
},
"methods": []interface{}{}},
)
} }
func exampleValue(method string, t, parent reflect.Type) interface{} { func ExampleValue(method string, t, parent reflect.Type) interface{} {
v, ok := ExampleValues[t] v, ok := ExampleValues[t]
if ok { if ok {
return v return v
@ -262,10 +271,10 @@ func exampleValue(method string, t, parent reflect.Type) interface{} {
switch t.Kind() { switch t.Kind() {
case reflect.Slice: case reflect.Slice:
out := reflect.New(t).Elem() out := reflect.New(t).Elem()
reflect.Append(out, reflect.ValueOf(exampleValue(method, t.Elem(), t))) reflect.Append(out, reflect.ValueOf(ExampleValue(method, t.Elem(), t)))
return out.Interface() return out.Interface()
case reflect.Chan: case reflect.Chan:
return exampleValue(method, t.Elem(), nil) return ExampleValue(method, t.Elem(), nil)
case reflect.Struct: case reflect.Struct:
es := exampleStruct(method, t, parent) es := exampleStruct(method, t, parent)
v := reflect.ValueOf(es).Elem().Interface() v := reflect.ValueOf(es).Elem().Interface()
@ -274,7 +283,7 @@ func exampleValue(method string, t, parent reflect.Type) interface{} {
case reflect.Array: case reflect.Array:
out := reflect.New(t).Elem() out := reflect.New(t).Elem()
for i := 0; i < t.Len(); i++ { for i := 0; i < t.Len(); i++ {
out.Index(i).Set(reflect.ValueOf(exampleValue(method, t.Elem(), t))) out.Index(i).Set(reflect.ValueOf(ExampleValue(method, t.Elem(), t)))
} }
return out.Interface() return out.Interface()
@ -299,7 +308,7 @@ func exampleStruct(method string, t, parent reflect.Type) interface{} {
continue continue
} }
if strings.Title(f.Name) == f.Name { if strings.Title(f.Name) == f.Name {
ns.Elem().Field(i).Set(reflect.ValueOf(exampleValue(method, f.Type, t))) ns.Elem().Field(i).Set(reflect.ValueOf(ExampleValue(method, f.Type, t)))
} }
} }
@ -331,13 +340,24 @@ func (v *Visitor) Visit(node ast.Node) ast.Visitor {
return v return v
} }
const noComment = "There are not yet any comments for this method." const NoComment = "There are not yet any comments for this method."
func parseApiASTInfo(apiFile, iface string) (map[string]string, map[string]string) { //nolint:golint func ParseApiASTInfo(apiFile, iface string) (comments map[string]string, groupDocs map[string]string) { //nolint:golint
fset := token.NewFileSet() fset := token.NewFileSet()
pkgs, err := parser.ParseDir(fset, "./api", nil, parser.AllErrors|parser.ParseComments) apiDir, err := filepath.Abs("./api")
if err != nil {
fmt.Println("./api filepath absolute error: ", err)
return
}
apiFile, err = filepath.Abs(apiFile)
if err != nil {
fmt.Println("filepath absolute error: ", err, "file:", apiFile)
return
}
pkgs, err := parser.ParseDir(fset, apiDir, nil, parser.AllErrors|parser.ParseComments)
if err != nil { if err != nil {
fmt.Println("parse error: ", err) fmt.Println("parse error: ", err)
return
} }
ap := pkgs["api"] ap := pkgs["api"]
@ -349,14 +369,14 @@ func parseApiASTInfo(apiFile, iface string) (map[string]string, map[string]strin
v := &Visitor{iface, make(map[string]ast.Node)} v := &Visitor{iface, make(map[string]ast.Node)}
ast.Walk(v, pkgs["api"]) ast.Walk(v, pkgs["api"])
groupDocs := make(map[string]string) comments = make(map[string]string)
out := make(map[string]string) groupDocs = make(map[string]string)
for mn, node := range v.Methods { for mn, node := range v.Methods {
cs := cmap.Filter(node).Comments() filteredComments := cmap.Filter(node).Comments()
if len(cs) == 0 { if len(filteredComments) == 0 {
out[mn] = noComment comments[mn] = NoComment
} else { } else {
for _, c := range cs { for _, c := range filteredComments {
if strings.HasPrefix(c.Text(), "MethodGroup:") { if strings.HasPrefix(c.Text(), "MethodGroup:") {
parts := strings.Split(c.Text(), "\n") parts := strings.Split(c.Text(), "\n")
groupName := strings.TrimSpace(parts[0][12:]) groupName := strings.TrimSpace(parts[0][12:])
@ -367,15 +387,19 @@ func parseApiASTInfo(apiFile, iface string) (map[string]string, map[string]strin
} }
} }
last := cs[len(cs)-1].Text() l := len(filteredComments) - 1
if len(filteredComments) > 1 {
l = len(filteredComments) - 2
}
last := filteredComments[l].Text()
if !strings.HasPrefix(last, "MethodGroup:") { if !strings.HasPrefix(last, "MethodGroup:") {
out[mn] = last comments[mn] = last
} else { } else {
out[mn] = noComment comments[mn] = NoComment
} }
} }
} }
return out, groupDocs return comments, groupDocs
} }
type MethodGroup struct { type MethodGroup struct {
@ -391,7 +415,7 @@ type Method struct {
ResponseExample string ResponseExample string
} }
func methodGroupFromName(mn string) string { func MethodGroupFromName(mn string) string {
i := strings.IndexFunc(mn[1:], func(r rune) bool { i := strings.IndexFunc(mn[1:], func(r rune) bool {
return unicode.IsUpper(r) return unicode.IsUpper(r)
}) })
@ -400,126 +424,3 @@ func methodGroupFromName(mn string) string {
} }
return mn[:i+1] return mn[:i+1]
} }
func main() {
comments, groupComments := parseApiASTInfo(os.Args[1], os.Args[2])
groups := make(map[string]*MethodGroup)
var t reflect.Type
var permStruct, commonPermStruct reflect.Type
switch os.Args[2] {
case "FullNode":
t = reflect.TypeOf(new(struct{ api.FullNode })).Elem()
permStruct = reflect.TypeOf(apistruct.FullNodeStruct{}.Internal)
commonPermStruct = reflect.TypeOf(apistruct.CommonStruct{}.Internal)
case "StorageMiner":
t = reflect.TypeOf(new(struct{ api.StorageMiner })).Elem()
permStruct = reflect.TypeOf(apistruct.StorageMinerStruct{}.Internal)
commonPermStruct = reflect.TypeOf(apistruct.CommonStruct{}.Internal)
case "WorkerAPI":
t = reflect.TypeOf(new(struct{ api.WorkerAPI })).Elem()
permStruct = reflect.TypeOf(apistruct.WorkerStruct{}.Internal)
commonPermStruct = reflect.TypeOf(apistruct.WorkerStruct{}.Internal)
default:
panic("unknown type")
}
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
groupName := methodGroupFromName(m.Name)
g, ok := groups[groupName]
if !ok {
g = new(MethodGroup)
g.Header = groupComments[groupName]
g.GroupName = groupName
groups[groupName] = g
}
var args []interface{}
ft := m.Func.Type()
for j := 2; j < ft.NumIn(); j++ {
inp := ft.In(j)
args = append(args, exampleValue(m.Name, inp, nil))
}
v, err := json.MarshalIndent(args, "", " ")
if err != nil {
panic(err)
}
outv := exampleValue(m.Name, ft.Out(0), nil)
ov, err := json.MarshalIndent(outv, "", " ")
if err != nil {
panic(err)
}
g.Methods = append(g.Methods, &Method{
Name: m.Name,
Comment: comments[m.Name],
InputExample: string(v),
ResponseExample: string(ov),
})
}
var groupslice []*MethodGroup
for _, g := range groups {
groupslice = append(groupslice, g)
}
sort.Slice(groupslice, func(i, j int) bool {
return groupslice[i].GroupName < groupslice[j].GroupName
})
fmt.Printf("# Groups\n")
for _, g := range groupslice {
fmt.Printf("* [%s](#%s)\n", g.GroupName, g.GroupName)
for _, method := range g.Methods {
fmt.Printf(" * [%s](#%s)\n", method.Name, method.Name)
}
}
for _, g := range groupslice {
g := g
fmt.Printf("## %s\n", g.GroupName)
fmt.Printf("%s\n\n", g.Header)
sort.Slice(g.Methods, func(i, j int) bool {
return g.Methods[i].Name < g.Methods[j].Name
})
for _, m := range g.Methods {
fmt.Printf("### %s\n", m.Name)
fmt.Printf("%s\n\n", m.Comment)
meth, ok := permStruct.FieldByName(m.Name)
if !ok {
meth, ok = commonPermStruct.FieldByName(m.Name)
if !ok {
panic("no perms for method: " + m.Name)
}
}
perms := meth.Tag.Get("perm")
fmt.Printf("Perms: %s\n\n", perms)
if strings.Count(m.InputExample, "\n") > 0 {
fmt.Printf("Inputs:\n```json\n%s\n```\n\n", m.InputExample)
} else {
fmt.Printf("Inputs: `%s`\n\n", m.InputExample)
}
if strings.Count(m.ResponseExample, "\n") > 0 {
fmt.Printf("Response:\n```json\n%s\n```\n\n", m.ResponseExample)
} else {
fmt.Printf("Response: `%s`\n\n", m.ResponseExample)
}
}
}
}

View File

@ -9,6 +9,7 @@ import (
address "github.com/filecoin-project/go-address" address "github.com/filecoin-project/go-address"
bitfield "github.com/filecoin-project/go-bitfield" bitfield "github.com/filecoin-project/go-bitfield"
datatransfer "github.com/filecoin-project/go-data-transfer" datatransfer "github.com/filecoin-project/go-data-transfer"
retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket"
storagemarket "github.com/filecoin-project/go-fil-markets/storagemarket" storagemarket "github.com/filecoin-project/go-fil-markets/storagemarket"
auth "github.com/filecoin-project/go-jsonrpc/auth" auth "github.com/filecoin-project/go-jsonrpc/auth"
multistore "github.com/filecoin-project/go-multistore" multistore "github.com/filecoin-project/go-multistore"
@ -18,6 +19,7 @@ import (
dline "github.com/filecoin-project/go-state-types/dline" dline "github.com/filecoin-project/go-state-types/dline"
network "github.com/filecoin-project/go-state-types/network" network "github.com/filecoin-project/go-state-types/network"
api "github.com/filecoin-project/lotus/api" api "github.com/filecoin-project/lotus/api"
apitypes "github.com/filecoin-project/lotus/api/types"
miner "github.com/filecoin-project/lotus/chain/actors/builtin/miner" miner "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
types "github.com/filecoin-project/lotus/chain/types" types "github.com/filecoin-project/lotus/chain/types"
marketevents "github.com/filecoin-project/lotus/markets/loggers" marketevents "github.com/filecoin-project/lotus/markets/loggers"
@ -444,6 +446,20 @@ func (mr *MockFullNodeMockRecorder) ClientCancelDataTransfer(arg0, arg1, arg2, a
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientCancelDataTransfer", reflect.TypeOf((*MockFullNode)(nil).ClientCancelDataTransfer), arg0, arg1, arg2, arg3) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientCancelDataTransfer", reflect.TypeOf((*MockFullNode)(nil).ClientCancelDataTransfer), arg0, arg1, arg2, arg3)
} }
// ClientCancelRetrievalDeal mocks base method
func (m *MockFullNode) ClientCancelRetrievalDeal(arg0 context.Context, arg1 retrievalmarket.DealID) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ClientCancelRetrievalDeal", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// ClientCancelRetrievalDeal indicates an expected call of ClientCancelRetrievalDeal
func (mr *MockFullNodeMockRecorder) ClientCancelRetrievalDeal(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientCancelRetrievalDeal", reflect.TypeOf((*MockFullNode)(nil).ClientCancelRetrievalDeal), arg0, arg1)
}
// ClientDataTransferUpdates mocks base method // ClientDataTransferUpdates mocks base method
func (m *MockFullNode) ClientDataTransferUpdates(arg0 context.Context) (<-chan api.DataTransferChannel, error) { func (m *MockFullNode) ClientDataTransferUpdates(arg0 context.Context) (<-chan api.DataTransferChannel, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@ -783,6 +799,21 @@ func (mr *MockFullNodeMockRecorder) CreateBackup(arg0, arg1 interface{}) *gomock
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateBackup", reflect.TypeOf((*MockFullNode)(nil).CreateBackup), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateBackup", reflect.TypeOf((*MockFullNode)(nil).CreateBackup), arg0, arg1)
} }
// Discover mocks base method
func (m *MockFullNode) Discover(arg0 context.Context) (apitypes.OpenRPCDocument, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Discover", arg0)
ret0, _ := ret[0].(apitypes.OpenRPCDocument)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Discover indicates an expected call of Discover
func (mr *MockFullNodeMockRecorder) Discover(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Discover", reflect.TypeOf((*MockFullNode)(nil).Discover), arg0)
}
// GasEstimateFeeCap mocks base method // GasEstimateFeeCap mocks base method
func (m *MockFullNode) GasEstimateFeeCap(arg0 context.Context, arg1 *types.Message, arg2 int64, arg3 types.TipSetKey) (big.Int, error) { func (m *MockFullNode) GasEstimateFeeCap(arg0 context.Context, arg1 *types.Message, arg2 int64, arg3 types.TipSetKey) (big.Int, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()

View File

@ -61,6 +61,7 @@ type DataTransferChannel struct {
Message string Message string
OtherPeer peer.ID OtherPeer peer.ID
Transferred uint64 Transferred uint64
Stages *datatransfer.ChannelStages
} }
// NewDataTransferChannel constructs an API DataTransferChannel type from full channel state snapshot and a host id // NewDataTransferChannel constructs an API DataTransferChannel type from full channel state snapshot and a host id

5
api/types/actors.go Normal file
View File

@ -0,0 +1,5 @@
package apitypes
import "github.com/filecoin-project/go-state-types/network"
type NetworkVersion = network.Version

3
api/types/openrpc.go Normal file
View File

@ -0,0 +1,3 @@
package apitypes
type OpenRPCDocument map[string]interface{}

View File

@ -85,11 +85,11 @@ const (
// operation calls after Close() has returned, but it may not happen for // operation calls after Close() has returned, but it may not happen for
// operations in progress. Those are likely to fail with a different error. // operations in progress. Those are likely to fail with a different error.
type Blockstore struct { type Blockstore struct {
DB *badger.DB // state is accessed atomically
// state is guarded by atomic.
state int64 state int64
DB *badger.DB
prefixing bool prefixing bool
prefix []byte prefix []byte
prefixLen int prefixLen int

43
build/openrpc.go Normal file
View File

@ -0,0 +1,43 @@
package build
import (
"bytes"
"compress/gzip"
"encoding/json"
rice "github.com/GeertJohan/go.rice"
apitypes "github.com/filecoin-project/lotus/api/types"
)
func mustReadGzippedOpenRPCDocument(data []byte) apitypes.OpenRPCDocument {
zr, err := gzip.NewReader(bytes.NewBuffer(data))
if err != nil {
log.Fatal(err)
}
m := apitypes.OpenRPCDocument{}
err = json.NewDecoder(zr).Decode(&m)
if err != nil {
log.Fatal(err)
}
err = zr.Close()
if err != nil {
log.Fatal(err)
}
return m
}
func OpenRPCDiscoverJSON_Full() apitypes.OpenRPCDocument {
data := rice.MustFindBox("openrpc").MustBytes("full.json.gz")
return mustReadGzippedOpenRPCDocument(data)
}
func OpenRPCDiscoverJSON_Miner() apitypes.OpenRPCDocument {
data := rice.MustFindBox("openrpc").MustBytes("miner.json.gz")
return mustReadGzippedOpenRPCDocument(data)
}
func OpenRPCDiscoverJSON_Worker() apitypes.OpenRPCDocument {
data := rice.MustFindBox("openrpc").MustBytes("worker.json.gz")
return mustReadGzippedOpenRPCDocument(data)
}

BIN
build/openrpc/full.json.gz Normal file

Binary file not shown.

BIN
build/openrpc/miner.json.gz Normal file

Binary file not shown.

Binary file not shown.

23
build/openrpc_test.go Normal file
View File

@ -0,0 +1,23 @@
package build
import (
"testing"
apitypes "github.com/filecoin-project/lotus/api/types"
)
func TestOpenRPCDiscoverJSON_Version(t *testing.T) {
// openRPCDocVersion is the current OpenRPC version of the API docs.
openRPCDocVersion := "1.2.6"
for i, docFn := range []func() apitypes.OpenRPCDocument{
OpenRPCDiscoverJSON_Full,
OpenRPCDiscoverJSON_Miner,
OpenRPCDiscoverJSON_Worker,
} {
doc := docFn()
if got, ok := doc["openrpc"]; !ok || got != openRPCDocVersion {
t.Fatalf("case: %d, want: %s, got: %v, doc: %v", i, openRPCDocVersion, got, doc)
}
}
}

View File

@ -37,6 +37,7 @@ func init() {
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1) policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048)) policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256)) policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
policy.SetPreCommitChallengeDelay(abi.ChainEpoch(10))
BuildType |= Build2k BuildType |= Build2k
} }

View File

@ -118,5 +118,5 @@ const PackingEfficiencyNum = 4
const PackingEfficiencyDenom = 5 const PackingEfficiencyDenom = 5
// Actor consts // Actor consts
// TODO: Pull from actors when its made not private // TODO: pieceSize unused from actors
var MinDealDuration = abi.ChainEpoch(180 * builtin2.EpochsInDay) var MinDealDuration, MaxDealDuration = policy.DealDurationBounds(0)

View File

@ -72,8 +72,8 @@ var (
}() }()
// Actor consts // Actor consts
// TODO: Pull from actors when its made not private // TODO: pieceSize unused from actors
MinDealDuration = abi.ChainEpoch(180 * builtin2.EpochsInDay) MinDealDuration, MaxDealDuration = policy.DealDurationBounds(0)
PackingEfficiencyNum int64 = 4 PackingEfficiencyNum int64 = 4
PackingEfficiencyDenom int64 = 5 PackingEfficiencyDenom int64 = 5

View File

@ -29,7 +29,7 @@ func buildType() string {
} }
// BuildVersion is the local build version, set by build system // BuildVersion is the local build version, set by build system
const BuildVersion = "1.5.2" const BuildVersion = "1.7.0-dev"
func UserVersion() string { func UserVersion() string {
return BuildVersion + buildType() + CurrentCommit return BuildVersion + buildType() + CurrentCommit

View File

@ -52,7 +52,7 @@ type PoStProof = proof0.PoStProof
type FilterEstimate = smoothing0.FilterEstimate type FilterEstimate = smoothing0.FilterEstimate
func FromV0FilterEstimate(v0 smoothing0.FilterEstimate) FilterEstimate { func FromV0FilterEstimate(v0 smoothing0.FilterEstimate) FilterEstimate {
return (FilterEstimate)(v0) return (FilterEstimate)(v0) //nolint:unconvert
} }
// Doesn't change between actors v0, v2, and v3. // Doesn't change between actors v0, v2, and v3.

View File

@ -61,6 +61,7 @@ type State interface {
VerifyDealsForActivation( VerifyDealsForActivation(
minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch, minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch,
) (weight, verifiedWeight abi.DealWeight, err error) ) (weight, verifiedWeight abi.DealWeight, err error)
NextID() (abi.DealID, error)
} }
type BalanceTable interface { type BalanceTable interface {

View File

@ -105,6 +105,10 @@ func (s *state0) VerifyDealsForActivation(
return market0.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch) return market0.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch)
} }
func (s *state0) NextID() (abi.DealID, error) {
return s.State.NextID, nil
}
type balanceTable0 struct { type balanceTable0 struct {
*adt0.BalanceTable *adt0.BalanceTable
} }

View File

@ -106,6 +106,10 @@ func (s *state2) VerifyDealsForActivation(
return w, vw, err return w, vw, err
} }
func (s *state2) NextID() (abi.DealID, error) {
return s.State.NextID, nil
}
type balanceTable2 struct { type balanceTable2 struct {
*adt2.BalanceTable *adt2.BalanceTable
} }

View File

@ -106,6 +106,10 @@ func (s *state3) VerifyDealsForActivation(
return w, vw, err return w, vw, err
} }
func (s *state3) NextID() (abi.DealID, error) {
return s.State.NextID, nil
}
type balanceTable3 struct { type balanceTable3 struct {
*adt3.BalanceTable *adt3.BalanceTable
} }

View File

@ -68,7 +68,7 @@ func (s *state0) ForEachPendingTxn(cb func(id int64, txn Transaction) error) err
if n <= 0 { if n <= 0 {
return xerrors.Errorf("invalid pending transaction key: %v", key) return xerrors.Errorf("invalid pending transaction key: %v", key)
} }
return cb(txid, (Transaction)(out)) return cb(txid, (Transaction)(out)) //nolint:unconvert
}) })
} }

View File

@ -67,7 +67,7 @@ func (s *state2) ForEachPendingTxn(cb func(id int64, txn Transaction) error) err
if n <= 0 { if n <= 0 {
return xerrors.Errorf("invalid pending transaction key: %v", key) return xerrors.Errorf("invalid pending transaction key: %v", key)
} }
return cb(txid, (Transaction)(out)) return cb(txid, (Transaction)(out)) //nolint:unconvert
}) })
} }

View File

@ -69,7 +69,7 @@ func (s *state3) ForEachPendingTxn(cb func(id int64, txn Transaction) error) err
if n <= 0 { if n <= 0 {
return xerrors.Errorf("invalid pending transaction key: %v", key) return xerrors.Errorf("invalid pending transaction key: %v", key)
} }
return cb(txid, (Transaction)(out)) return cb(txid, (Transaction)(out)) //nolint:unconvert
}) })
} }

View File

@ -25,9 +25,10 @@ import (
) )
const ( const (
ChainFinality = miner3.ChainFinality ChainFinality = miner3.ChainFinality
SealRandomnessLookback = ChainFinality SealRandomnessLookback = ChainFinality
PaychSettleDelay = paych3.SettleDelay PaychSettleDelay = paych3.SettleDelay
MaxPreCommitRandomnessLookback = builtin3.EpochsInDay + SealRandomnessLookback
) )
// SetSupportedProofTypes sets supported proof types, across all actor versions. // SetSupportedProofTypes sets supported proof types, across all actor versions.
@ -136,6 +137,10 @@ func DealProviderCollateralBounds(
} }
} }
func DealDurationBounds(pieceSize abi.PaddedPieceSize) (min, max abi.ChainEpoch) {
return market2.DealDurationBounds(pieceSize)
}
// Sets the challenge window and scales the proving period to match (such that // Sets the challenge window and scales the proving period to match (such that
// there are always 48 challenge windows in a proving period). // there are always 48 challenge windows in a proving period).
func SetWPoStChallengeWindow(period abi.ChainEpoch) { func SetWPoStChallengeWindow(period abi.ChainEpoch) {

View File

@ -55,11 +55,11 @@ type Events struct {
heightEvents heightEvents
*hcEvents *hcEvents
observers []TipSetObserver
} }
func NewEvents(ctx context.Context, api eventAPI) *Events { func NewEventsWithConfidence(ctx context.Context, api eventAPI, gcConfidence abi.ChainEpoch) *Events {
gcConfidence := 2 * build.ForkLengthThreshold
tsc := newTSCache(gcConfidence, api) tsc := newTSCache(gcConfidence, api)
e := &Events{ e := &Events{
@ -77,8 +77,9 @@ func NewEvents(ctx context.Context, api eventAPI) *Events {
htHeights: map[abi.ChainEpoch][]uint64{}, htHeights: map[abi.ChainEpoch][]uint64{},
}, },
hcEvents: newHCEvents(ctx, api, tsc, uint64(gcConfidence)), hcEvents: newHCEvents(ctx, api, tsc, uint64(gcConfidence)),
ready: make(chan struct{}), ready: make(chan struct{}),
observers: []TipSetObserver{},
} }
go e.listenHeadChanges(ctx) go e.listenHeadChanges(ctx)
@ -92,6 +93,11 @@ func NewEvents(ctx context.Context, api eventAPI) *Events {
return e return e
} }
func NewEvents(ctx context.Context, api eventAPI) *Events {
gcConfidence := 2 * build.ForkLengthThreshold
return NewEventsWithConfidence(ctx, api, gcConfidence)
}
func (e *Events) listenHeadChanges(ctx context.Context) { func (e *Events) listenHeadChanges(ctx context.Context) {
for { for {
if err := e.listenHeadChangesOnce(ctx); err != nil { if err := e.listenHeadChangesOnce(ctx); err != nil {
@ -164,7 +170,7 @@ func (e *Events) listenHeadChangesOnce(ctx context.Context) error {
} }
} }
if err := e.headChange(rev, app); err != nil { if err := e.headChange(ctx, rev, app); err != nil {
log.Warnf("headChange failed: %s", err) log.Warnf("headChange failed: %s", err)
} }
@ -177,7 +183,7 @@ func (e *Events) listenHeadChangesOnce(ctx context.Context) error {
return nil return nil
} }
func (e *Events) headChange(rev, app []*types.TipSet) error { func (e *Events) headChange(ctx context.Context, rev, app []*types.TipSet) error {
if len(app) == 0 { if len(app) == 0 {
return xerrors.New("events.headChange expected at least one applied tipset") return xerrors.New("events.headChange expected at least one applied tipset")
} }
@ -189,5 +195,39 @@ func (e *Events) headChange(rev, app []*types.TipSet) error {
return err return err
} }
if err := e.observeChanges(ctx, rev, app); err != nil {
return err
}
return e.processHeadChangeEvent(rev, app) return e.processHeadChangeEvent(rev, app)
} }
// A TipSetObserver receives notifications of tipsets
type TipSetObserver interface {
Apply(ctx context.Context, ts *types.TipSet) error
Revert(ctx context.Context, ts *types.TipSet) error
}
// TODO: add a confidence level so we can have observers with difference levels of confidence
func (e *Events) Observe(obs TipSetObserver) error {
e.lk.Lock()
defer e.lk.Unlock()
e.observers = append(e.observers, obs)
return nil
}
// observeChanges expects caller to hold e.lk
func (e *Events) observeChanges(ctx context.Context, rev, app []*types.TipSet) error {
for _, ts := range rev {
for _, o := range e.observers {
_ = o.Revert(ctx, ts)
}
}
for _, ts := range app {
for _, o := range e.observers {
_ = o.Apply(ctx, ts)
}
}
return nil
}

View File

@ -133,9 +133,22 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi
} }
} }
err := setupMsig(remainder.Meta) if remainder.Type == genesis.TAccount {
if err != nil { var ainfo genesis.AccountMeta
return 0, nil, nil, xerrors.Errorf("setting up remainder msig: %w", err) if err := json.Unmarshal(remainder.Meta, &ainfo); err != nil {
return 0, nil, nil, xerrors.Errorf("unmarshaling account meta: %w", err)
}
// TODO: Use builtin.ReserveAddress...
value := cbg.CborInt(90)
if err := amap.Put(abi.AddrKey(ainfo.Owner), &value); err != nil {
return 0, nil, nil, err
}
} else if remainder.Type == genesis.TMultisig {
err := setupMsig(remainder.Meta)
if err != nil {
return 0, nil, nil, xerrors.Errorf("setting up remainder msig: %w", err)
}
} }
amapaddr, err := amap.Root() amapaddr, err := amap.Root()

View File

@ -330,24 +330,18 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
if err := json.Unmarshal(template.RemainderAccount.Meta, &ainfo); err != nil { if err := json.Unmarshal(template.RemainderAccount.Meta, &ainfo); err != nil {
return nil, nil, xerrors.Errorf("unmarshaling account meta: %w", err) return nil, nil, xerrors.Errorf("unmarshaling account meta: %w", err)
} }
st, err := cst.Put(ctx, &account0.State{Address: ainfo.Owner})
if err != nil {
return nil, nil, err
}
_, ok := keyIDs[ainfo.Owner] _, ok := keyIDs[ainfo.Owner]
if ok { if ok {
return nil, nil, fmt.Errorf("remainder account has already been declared, cannot be assigned 90: %s", ainfo.Owner) return nil, nil, fmt.Errorf("remainder account has already been declared, cannot be assigned 90: %s", ainfo.Owner)
} }
err = state.SetActor(builtin.ReserveAddress, &types.Actor{ keyIDs[ainfo.Owner] = builtin.ReserveAddress
Code: builtin0.AccountActorCodeID, err = createAccountActor(ctx, cst, state, template.RemainderAccount, keyIDs)
Balance: template.RemainderAccount.Balance,
Head: st,
})
if err != nil { if err != nil {
return nil, nil, xerrors.Errorf("setting remainder account: %w", err) return nil, nil, xerrors.Errorf("creating remainder acct: %w", err)
} }
case genesis.TMultisig: case genesis.TMultisig:
if err = createMultisigAccount(ctx, bs, cst, state, builtin.ReserveAddress, template.RemainderAccount, keyIDs); err != nil { if err = createMultisigAccount(ctx, bs, cst, state, builtin.ReserveAddress, template.RemainderAccount, keyIDs); err != nil {
return nil, nil, xerrors.Errorf("failed to set up remainder: %w", err) return nil, nil, xerrors.Errorf("failed to set up remainder: %w", err)

View File

@ -15,7 +15,7 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w api.WalletAPI, bt *api.BlockTemplate) (*types.FullBlock, error) { func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w api.Wallet, bt *api.BlockTemplate) (*types.FullBlock, error) {
pts, err := sm.ChainStore().LoadTipSet(bt.Parents) pts, err := sm.ChainStore().LoadTipSet(bt.Parents)
if err != nil { if err != nil {

View File

@ -1333,7 +1333,7 @@ readLoop:
} }
actorMap := make(map[address.Address]address.Address) actorMap := make(map[address.Address]address.Address)
actorWallets := make(map[address.Address]api.WalletAPI) actorWallets := make(map[address.Address]api.Wallet)
for _, m := range msgs { for _, m := range msgs {
baseNonce := baseNonces[m.Message.From] baseNonce := baseNonces[m.Message.From]

View File

@ -29,13 +29,13 @@ type MpoolNonceAPI interface {
// MessageSigner keeps track of nonces per address, and increments the nonce // MessageSigner keeps track of nonces per address, and increments the nonce
// when signing a message // when signing a message
type MessageSigner struct { type MessageSigner struct {
wallet api.WalletAPI wallet api.Wallet
lk sync.Mutex lk sync.Mutex
mpool MpoolNonceAPI mpool MpoolNonceAPI
ds datastore.Batching ds datastore.Batching
} }
func NewMessageSigner(wallet api.WalletAPI, mpool MpoolNonceAPI, ds dtypes.MetadataDS) *MessageSigner { func NewMessageSigner(wallet api.Wallet, mpool MpoolNonceAPI, ds dtypes.MetadataDS) *MessageSigner {
ds = namespace.Wrap(ds, datastore.NewKey("/message-signer/")) ds = namespace.Wrap(ds, datastore.NewKey("/message-signer/"))
return &MessageSigner{ return &MessageSigner{
wallet: wallet, wallet: wallet,

View File

@ -255,7 +255,7 @@ func (sm *StateManager) Replay(ctx context.Context, ts *types.TipSet, mcid cid.C
} }
return nil return nil
}) })
if err != nil && err != errHaltExecution { if err != nil && !xerrors.Is(err, errHaltExecution) {
return nil, nil, xerrors.Errorf("unexpected error during execution: %w", err) return nil, nil, xerrors.Errorf("unexpected error during execution: %w", err)
} }

View File

@ -16,11 +16,11 @@ import (
) )
type RPCStateManager struct { type RPCStateManager struct {
gapi api.GatewayAPI gapi api.Gateway
cstore *cbor.BasicIpldStore cstore *cbor.BasicIpldStore
} }
func NewRPCStateManager(api api.GatewayAPI) *RPCStateManager { func NewRPCStateManager(api api.Gateway) *RPCStateManager {
cstore := cbor.NewCborStore(blockstore.NewAPIBlockstore(api)) cstore := cbor.NewCborStore(blockstore.NewAPIBlockstore(api))
return &RPCStateManager{gapi: api, cstore: cstore} return &RPCStateManager{gapi: api, cstore: cstore}
} }

View File

@ -36,7 +36,7 @@ type LedgerKeyInfo struct {
Path []uint32 Path []uint32
} }
var _ api.WalletAPI = (*LedgerWallet)(nil) var _ api.Wallet = (*LedgerWallet)(nil)
func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta api.MsgMeta) (*crypto.Signature, error) { func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta api.MsgMeta) (*crypto.Signature, error) {
ki, err := lw.getKeyInfo(signer) ki, err := lw.getKeyInfo(signer)
@ -227,7 +227,7 @@ func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address.
return lw.importKey(lki) return lw.importKey(lki)
} }
func (lw *LedgerWallet) Get() api.WalletAPI { func (lw *LedgerWallet) Get() api.Wallet {
if lw == nil { if lw == nil {
return nil return nil
} }

View File

@ -24,13 +24,13 @@ type MultiWallet struct {
} }
type getif interface { type getif interface {
api.WalletAPI api.Wallet
// workaround for the fact that iface(*struct(nil)) != nil // workaround for the fact that iface(*struct(nil)) != nil
Get() api.WalletAPI Get() api.Wallet
} }
func firstNonNil(wallets ...getif) api.WalletAPI { func firstNonNil(wallets ...getif) api.Wallet {
for _, w := range wallets { for _, w := range wallets {
if w.Get() != nil { if w.Get() != nil {
return w return w
@ -40,8 +40,8 @@ func firstNonNil(wallets ...getif) api.WalletAPI {
return nil return nil
} }
func nonNil(wallets ...getif) []api.WalletAPI { func nonNil(wallets ...getif) []api.Wallet {
var out []api.WalletAPI var out []api.Wallet
for _, w := range wallets { for _, w := range wallets {
if w.Get() == nil { if w.Get() == nil {
continue continue
@ -53,7 +53,7 @@ func nonNil(wallets ...getif) []api.WalletAPI {
return out return out
} }
func (m MultiWallet) find(ctx context.Context, address address.Address, wallets ...getif) (api.WalletAPI, error) { func (m MultiWallet) find(ctx context.Context, address address.Address, wallets ...getif) (api.Wallet, error) {
ws := nonNil(wallets...) ws := nonNil(wallets...)
for _, w := range ws { for _, w := range ws {
@ -167,4 +167,4 @@ func (m MultiWallet) WalletDelete(ctx context.Context, address address.Address)
} }
} }
var _ api.WalletAPI = MultiWallet{} var _ api.Wallet = MultiWallet{}

View File

@ -13,7 +13,7 @@ import (
) )
type RemoteWallet struct { type RemoteWallet struct {
api.WalletAPI api.Wallet
} }
func SetupRemoteWallet(info string) func(mctx helpers.MetricsCtx, lc fx.Lifecycle) (*RemoteWallet, error) { func SetupRemoteWallet(info string) func(mctx helpers.MetricsCtx, lc fx.Lifecycle) (*RemoteWallet, error) {
@ -41,7 +41,7 @@ func SetupRemoteWallet(info string) func(mctx helpers.MetricsCtx, lc fx.Lifecycl
} }
} }
func (w *RemoteWallet) Get() api.WalletAPI { func (w *RemoteWallet) Get() api.Wallet {
if w == nil { if w == nil {
return nil return nil
} }

View File

@ -329,7 +329,7 @@ func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) er
return nil return nil
} }
func (w *LocalWallet) Get() api.WalletAPI { func (w *LocalWallet) Get() api.Wallet {
if w == nil { if w == nil {
return nil return nil
} }
@ -337,7 +337,7 @@ func (w *LocalWallet) Get() api.WalletAPI {
return w return w
} }
var _ api.WalletAPI = &LocalWallet{} var _ api.Wallet = &LocalWallet{}
func swapMainnetForTestnetPrefix(addr string) (string, error) { func swapMainnetForTestnetPrefix(addr string) (string, error) {
aChars := []rune(addr) aChars := []rune(addr)

View File

@ -13,16 +13,16 @@ import (
"github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/node/repo"
) )
var authCmd = &cli.Command{ var AuthCmd = &cli.Command{
Name: "auth", Name: "auth",
Usage: "Manage RPC permissions", Usage: "Manage RPC permissions",
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
authCreateAdminToken, AuthCreateAdminToken,
authApiInfoToken, AuthApiInfoToken,
}, },
} }
var authCreateAdminToken = &cli.Command{ var AuthCreateAdminToken = &cli.Command{
Name: "create-token", Name: "create-token",
Usage: "Create token", Usage: "Create token",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -70,7 +70,7 @@ var authCreateAdminToken = &cli.Command{
}, },
} }
var authApiInfoToken = &cli.Command{ var AuthApiInfoToken = &cli.Command{
Name: "api-info", Name: "api-info",
Usage: "Get token with API info required to connect to this node", Usage: "Get token with API info required to connect to this node",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -90,7 +90,7 @@ var authApiInfoToken = &cli.Command{
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
if !cctx.IsSet("perm") { if !cctx.IsSet("perm") {
return xerrors.New("--perm flag not set") return xerrors.New("--perm flag not set, use with one of: read, write, sign, admin")
} }
perm := cctx.String("perm") perm := cctx.String("perm")

View File

@ -38,31 +38,31 @@ import (
types "github.com/filecoin-project/lotus/chain/types" types "github.com/filecoin-project/lotus/chain/types"
) )
var chainCmd = &cli.Command{ var ChainCmd = &cli.Command{
Name: "chain", Name: "chain",
Usage: "Interact with filecoin blockchain", Usage: "Interact with filecoin blockchain",
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
chainHeadCmd, ChainHeadCmd,
chainGetBlock, ChainGetBlock,
chainReadObjCmd, ChainReadObjCmd,
chainDeleteObjCmd, ChainDeleteObjCmd,
chainStatObjCmd, ChainStatObjCmd,
chainGetMsgCmd, ChainGetMsgCmd,
chainSetHeadCmd, ChainSetHeadCmd,
chainListCmd, ChainListCmd,
chainGetCmd, ChainGetCmd,
chainBisectCmd, ChainBisectCmd,
chainExportCmd, ChainExportCmd,
slashConsensusFault, SlashConsensusFault,
chainGasPriceCmd, ChainGasPriceCmd,
chainInspectUsage, ChainInspectUsage,
chainDecodeCmd, ChainDecodeCmd,
chainEncodeCmd, ChainEncodeCmd,
chainDisputeSetCmd, ChainDisputeSetCmd,
}, },
} }
var chainHeadCmd = &cli.Command{ var ChainHeadCmd = &cli.Command{
Name: "head", Name: "head",
Usage: "Print chain head", Usage: "Print chain head",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
@ -85,7 +85,7 @@ var chainHeadCmd = &cli.Command{
}, },
} }
var chainGetBlock = &cli.Command{ var ChainGetBlock = &cli.Command{
Name: "getblock", Name: "getblock",
Usage: "Get a block and print its details", Usage: "Get a block and print its details",
ArgsUsage: "[blockCid]", ArgsUsage: "[blockCid]",
@ -176,7 +176,7 @@ func apiMsgCids(in []lapi.Message) []cid.Cid {
return out return out
} }
var chainReadObjCmd = &cli.Command{ var ChainReadObjCmd = &cli.Command{
Name: "read-obj", Name: "read-obj",
Usage: "Read the raw bytes of an object", Usage: "Read the raw bytes of an object",
ArgsUsage: "[objectCid]", ArgsUsage: "[objectCid]",
@ -203,7 +203,7 @@ var chainReadObjCmd = &cli.Command{
}, },
} }
var chainDeleteObjCmd = &cli.Command{ var ChainDeleteObjCmd = &cli.Command{
Name: "delete-obj", Name: "delete-obj",
Usage: "Delete an object from the chain blockstore", Usage: "Delete an object from the chain blockstore",
Description: "WARNING: Removing wrong objects from the chain blockstore may lead to sync issues", Description: "WARNING: Removing wrong objects from the chain blockstore may lead to sync issues",
@ -240,7 +240,7 @@ var chainDeleteObjCmd = &cli.Command{
}, },
} }
var chainStatObjCmd = &cli.Command{ var ChainStatObjCmd = &cli.Command{
Name: "stat-obj", Name: "stat-obj",
Usage: "Collect size and ipld link counts for objs", Usage: "Collect size and ipld link counts for objs",
ArgsUsage: "[cid]", ArgsUsage: "[cid]",
@ -287,7 +287,7 @@ var chainStatObjCmd = &cli.Command{
}, },
} }
var chainGetMsgCmd = &cli.Command{ var ChainGetMsgCmd = &cli.Command{
Name: "getmessage", Name: "getmessage",
Usage: "Get and print a message by its cid", Usage: "Get and print a message by its cid",
ArgsUsage: "[messageCid]", ArgsUsage: "[messageCid]",
@ -335,7 +335,7 @@ var chainGetMsgCmd = &cli.Command{
}, },
} }
var chainSetHeadCmd = &cli.Command{ var ChainSetHeadCmd = &cli.Command{
Name: "sethead", Name: "sethead",
Usage: "manually set the local nodes head tipset (Caution: normally only used for recovery)", Usage: "manually set the local nodes head tipset (Caution: normally only used for recovery)",
ArgsUsage: "[tipsetkey]", ArgsUsage: "[tipsetkey]",
@ -384,7 +384,7 @@ var chainSetHeadCmd = &cli.Command{
}, },
} }
var chainInspectUsage = &cli.Command{ var ChainInspectUsage = &cli.Command{
Name: "inspect-usage", Name: "inspect-usage",
Usage: "Inspect block space usage of a given tipset", Usage: "Inspect block space usage of a given tipset",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -529,7 +529,7 @@ var chainInspectUsage = &cli.Command{
}, },
} }
var chainListCmd = &cli.Command{ var ChainListCmd = &cli.Command{
Name: "list", Name: "list",
Aliases: []string{"love"}, Aliases: []string{"love"},
Usage: "View a segment of the chain", Usage: "View a segment of the chain",
@ -658,7 +658,7 @@ var chainListCmd = &cli.Command{
}, },
} }
var chainGetCmd = &cli.Command{ var ChainGetCmd = &cli.Command{
Name: "get", Name: "get",
Usage: "Get chain DAG node by path", Usage: "Get chain DAG node by path",
ArgsUsage: "[path]", ArgsUsage: "[path]",
@ -905,7 +905,7 @@ func printTipSet(format string, ts *types.TipSet) {
fmt.Println(format) fmt.Println(format)
} }
var chainBisectCmd = &cli.Command{ var ChainBisectCmd = &cli.Command{
Name: "bisect", Name: "bisect",
Usage: "bisect chain for an event", Usage: "bisect chain for an event",
ArgsUsage: "[minHeight maxHeight path shellCommand <shellCommandArgs (if any)>]", ArgsUsage: "[minHeight maxHeight path shellCommand <shellCommandArgs (if any)>]",
@ -1028,7 +1028,7 @@ var chainBisectCmd = &cli.Command{
}, },
} }
var chainExportCmd = &cli.Command{ var ChainExportCmd = &cli.Command{
Name: "export", Name: "export",
Usage: "export chain to a car file", Usage: "export chain to a car file",
ArgsUsage: "[outputPath]", ArgsUsage: "[outputPath]",
@ -1106,7 +1106,7 @@ var chainExportCmd = &cli.Command{
}, },
} }
var slashConsensusFault = &cli.Command{ var SlashConsensusFault = &cli.Command{
Name: "slash-consensus", Name: "slash-consensus",
Usage: "Report consensus fault", Usage: "Report consensus fault",
ArgsUsage: "[blockCid1 blockCid2]", ArgsUsage: "[blockCid1 blockCid2]",
@ -1227,7 +1227,7 @@ var slashConsensusFault = &cli.Command{
}, },
} }
var chainGasPriceCmd = &cli.Command{ var ChainGasPriceCmd = &cli.Command{
Name: "gas-price", Name: "gas-price",
Usage: "Estimate gas prices", Usage: "Estimate gas prices",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
@ -1254,7 +1254,7 @@ var chainGasPriceCmd = &cli.Command{
}, },
} }
var chainDecodeCmd = &cli.Command{ var ChainDecodeCmd = &cli.Command{
Name: "decode", Name: "decode",
Usage: "decode various types", Usage: "decode various types",
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
@ -1334,7 +1334,7 @@ var chainDecodeParamsCmd = &cli.Command{
}, },
} }
var chainEncodeCmd = &cli.Command{ var ChainEncodeCmd = &cli.Command{
Name: "encode", Name: "encode",
Usage: "encode various types", Usage: "encode various types",
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{

View File

@ -83,12 +83,14 @@ var clientCmd = &cli.Command{
WithCategory("storage", clientGetDealCmd), WithCategory("storage", clientGetDealCmd),
WithCategory("storage", clientListAsksCmd), WithCategory("storage", clientListAsksCmd),
WithCategory("storage", clientDealStatsCmd), WithCategory("storage", clientDealStatsCmd),
WithCategory("storage", clientInspectDealCmd),
WithCategory("data", clientImportCmd), WithCategory("data", clientImportCmd),
WithCategory("data", clientDropCmd), WithCategory("data", clientDropCmd),
WithCategory("data", clientLocalCmd), WithCategory("data", clientLocalCmd),
WithCategory("data", clientStat), WithCategory("data", clientStat),
WithCategory("retrieval", clientFindCmd), WithCategory("retrieval", clientFindCmd),
WithCategory("retrieval", clientRetrieveCmd), WithCategory("retrieval", clientRetrieveCmd),
WithCategory("retrieval", clientCancelRetrievalDealCmd),
WithCategory("util", clientCommPCmd), WithCategory("util", clientCommPCmd),
WithCategory("util", clientCarGenCmd), WithCategory("util", clientCarGenCmd),
WithCategory("util", clientBalancesCmd), WithCategory("util", clientBalancesCmd),
@ -387,6 +389,9 @@ var clientDealCmd = &cli.Command{
if abi.ChainEpoch(dur) < build.MinDealDuration { if abi.ChainEpoch(dur) < build.MinDealDuration {
return xerrors.Errorf("minimum deal duration is %d blocks", build.MinDealDuration) return xerrors.Errorf("minimum deal duration is %d blocks", build.MinDealDuration)
} }
if abi.ChainEpoch(dur) > build.MaxDealDuration {
return xerrors.Errorf("maximum deal duration is %d blocks", build.MaxDealDuration)
}
var a address.Address var a address.Address
if from := cctx.String("from"); from != "" { if from := cctx.String("from"); from != "" {
@ -498,9 +503,10 @@ func interactiveDeal(cctx *cli.Context) error {
var ds lapi.DataCIDSize var ds lapi.DataCIDSize
// find // find
var candidateAsks []*storagemarket.StorageAsk var candidateAsks []QueriedAsk
var budget types.FIL var budget types.FIL
var dealCount int64 var dealCount int64
var medianPing, maxAcceptablePing time.Duration
var a address.Address var a address.Address
if from := cctx.String("from"); from != "" { if from := cctx.String("from"); from != "" {
@ -660,6 +666,18 @@ uiLoop:
return err return err
} }
if len(asks) == 0 {
printErr(xerrors.Errorf("no asks found"))
continue uiLoop
}
medianPing = asks[len(asks)/2].Ping
var avgPing time.Duration
for _, ask := range asks {
avgPing += ask.Ping
}
avgPing /= time.Duration(len(asks))
for _, ask := range asks { for _, ask := range asks {
if ask.Ask.MinPieceSize > ds.PieceSize { if ask.Ask.MinPieceSize > ds.PieceSize {
continue continue
@ -667,10 +685,48 @@ uiLoop:
if ask.Ask.MaxPieceSize < ds.PieceSize { if ask.Ask.MaxPieceSize < ds.PieceSize {
continue continue
} }
candidateAsks = append(candidateAsks, ask.Ask) candidateAsks = append(candidateAsks, ask)
} }
afmt.Printf("Found %d candidate asks\n", len(candidateAsks)) afmt.Printf("Found %d candidate asks\n", len(candidateAsks))
afmt.Printf("Average network latency: %s; Median latency: %s\n", avgPing.Truncate(time.Millisecond), medianPing.Truncate(time.Millisecond))
state = "max-ping"
case "max-ping":
maxAcceptablePing = medianPing
afmt.Printf("Maximum network latency (default: %s) (ms): ", maxAcceptablePing.Truncate(time.Millisecond))
_latStr, _, err := rl.ReadLine()
latStr := string(_latStr)
if err != nil {
printErr(xerrors.Errorf("reading maximum latency: %w", err))
continue
}
if latStr != "" {
maxMs, err := strconv.ParseInt(latStr, 10, 64)
if err != nil {
printErr(xerrors.Errorf("parsing FIL: %w", err))
continue uiLoop
}
maxAcceptablePing = time.Millisecond * time.Duration(maxMs)
}
var goodAsks []QueriedAsk
for _, candidateAsk := range candidateAsks {
if candidateAsk.Ping < maxAcceptablePing {
goodAsks = append(goodAsks, candidateAsk)
}
}
if len(goodAsks) == 0 {
afmt.Printf("no asks left after filtering for network latency\n")
continue uiLoop
}
afmt.Printf("%d asks left after filtering for network latency\n", len(goodAsks))
candidateAsks = goodAsks
state = "find-budget" state = "find-budget"
case "find-budget": case "find-budget":
afmt.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))
@ -689,11 +745,11 @@ uiLoop:
continue uiLoop continue uiLoop
} }
var goodAsks []*storagemarket.StorageAsk var goodAsks []QueriedAsk
for _, ask := range candidateAsks { for _, ask := range candidateAsks {
p := ask.Price p := ask.Ask.Price
if verified { if verified {
p = ask.VerifiedPrice p = ask.Ask.VerifiedPrice
} }
epochPrice := types.BigDiv(types.BigMul(p, types.NewInt(uint64(ds.PieceSize))), gib) epochPrice := types.BigDiv(types.BigMul(p, types.NewInt(uint64(ds.PieceSize))), gib)
@ -733,9 +789,9 @@ uiLoop:
pickedAsks = []*storagemarket.StorageAsk{} pickedAsks = []*storagemarket.StorageAsk{}
for _, ask := range candidateAsks { for _, ask := range candidateAsks {
p := ask.Price p := ask.Ask.Price
if verified { if verified {
p = ask.VerifiedPrice p = ask.Ask.VerifiedPrice
} }
epochPrice := types.BigDiv(types.BigMul(p, types.NewInt(uint64(ds.PieceSize))), gib) epochPrice := types.BigDiv(types.BigMul(p, types.NewInt(uint64(ds.PieceSize))), gib)
@ -745,7 +801,7 @@ uiLoop:
continue continue
} }
pickedAsks = append(pickedAsks, ask) pickedAsks = append(pickedAsks, ask.Ask)
remainingBudget = big.Sub(remainingBudget, totalPrice) remainingBudget = big.Sub(remainingBudget, totalPrice)
if len(pickedAsks) == int(dealCount) { if len(pickedAsks) == int(dealCount) {
@ -1114,6 +1170,29 @@ var clientRetrieveCmd = &cli.Command{
}, },
} }
var clientInspectDealCmd = &cli.Command{
Name: "inspect-deal",
Usage: "Inspect detailed information about deal's lifecycle and the various stages it goes through",
Flags: []cli.Flag{
&cli.IntFlag{
Name: "deal-id",
},
&cli.StringFlag{
Name: "proposal-cid",
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
return inspectDealCmd(ctx, api, cctx.String("proposal-cid"), cctx.Int("deal-id"))
},
}
var clientDealStatsCmd = &cli.Command{ var clientDealStatsCmd = &cli.Command{
Name: "deal-stats", Name: "deal-stats",
Usage: "Print statistics about local storage deals", Usage: "Print statistics about local storage deals",
@ -1975,6 +2054,33 @@ var clientCancelTransfer = &cli.Command{
}, },
} }
var clientCancelRetrievalDealCmd = &cli.Command{
Name: "cancel-retrieval",
Usage: "Cancel a retrieval deal by deal ID; this also cancels the associated transfer",
Flags: []cli.Flag{
&cli.Int64Flag{
Name: "deal-id",
Usage: "specify retrieval deal by deal ID",
Required: true,
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
id := cctx.Int64("deal-id")
if id < 0 {
return errors.New("deal id cannot be negative")
}
return api.ClientCancelRetrievalDeal(ctx, retrievalmarket.DealID(id))
},
}
var clientListTransfers = &cli.Command{ var clientListTransfers = &cli.Command{
Name: "list-transfers", Name: "list-transfers",
Usage: "List ongoing data transfers for deals", Usage: "List ongoing data transfers for deals",
@ -2163,3 +2269,77 @@ func ellipsis(s string, length int) string {
} }
return s return s
} }
func inspectDealCmd(ctx context.Context, api lapi.FullNode, proposalCid string, dealId int) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
deals, err := api.ClientListDeals(ctx)
if err != nil {
return err
}
var di *lapi.DealInfo
for i, cdi := range deals {
if proposalCid != "" && cdi.ProposalCid.String() == proposalCid {
di = &deals[i]
break
}
if dealId != 0 && int(cdi.DealID) == dealId {
di = &deals[i]
break
}
}
if di == nil {
if proposalCid != "" {
return fmt.Errorf("cannot find deal with proposal cid: %s", proposalCid)
}
if dealId != 0 {
return fmt.Errorf("cannot find deal with deal id: %v", dealId)
}
return errors.New("you must specify proposal cid or deal id in order to inspect a deal")
}
// populate DealInfo.DealStages and DataTransfer.Stages
di, err = api.ClientGetDealInfo(ctx, di.ProposalCid)
if err != nil {
return fmt.Errorf("cannot get deal info for proposal cid: %v", di.ProposalCid)
}
renderDeal(di)
return nil
}
func renderDeal(di *lapi.DealInfo) {
color.Blue("Deal ID: %d\n", int(di.DealID))
color.Blue("Proposal CID: %s\n\n", di.ProposalCid.String())
if di.DealStages == nil {
color.Yellow("Deal was made with an older version of Lotus and Lotus did not collect detailed information about its stages")
return
}
for _, stg := range di.DealStages.Stages {
msg := fmt.Sprintf("%s %s: %s (%s)", color.BlueString("Stage:"), color.BlueString(strings.TrimPrefix(stg.Name, "StorageDeal")), stg.Description, color.GreenString(stg.ExpectedDuration))
if stg.UpdatedTime.Time().IsZero() {
msg = color.YellowString(msg)
}
fmt.Println(msg)
for _, l := range stg.Logs {
fmt.Printf(" %s %s\n", color.YellowString(l.UpdatedTime.Time().UTC().Round(time.Second).Format(time.Stamp)), l.Log)
}
if stg.Name == "StorageDealStartDataTransfer" {
for _, dtStg := range di.DataTransfer.Stages.Stages {
fmt.Printf(" %s %s %s\n", color.YellowString(dtStg.CreatedTime.Time().UTC().Round(time.Second).Format(time.Stamp)), color.BlueString("Data transfer stage:"), color.BlueString(dtStg.Name))
for _, l := range dtStg.Logs {
fmt.Printf(" %s %s\n", color.YellowString(l.UpdatedTime.Time().UTC().Round(time.Second).Format(time.Stamp)), l.Log)
}
}
}
}
}

View File

@ -56,12 +56,12 @@ var GetStorageMinerAPI = cliutil.GetStorageMinerAPI
var GetWorkerAPI = cliutil.GetWorkerAPI var GetWorkerAPI = cliutil.GetWorkerAPI
var CommonCommands = []*cli.Command{ var CommonCommands = []*cli.Command{
netCmd, NetCmd,
authCmd, AuthCmd,
logCmd, LogCmd,
waitApiCmd, WaitApiCmd,
fetchParamCmd, FetchParamCmd,
pprofCmd, PprofCmd,
VersionCmd, VersionCmd,
} }
@ -71,16 +71,16 @@ var Commands = []*cli.Command{
WithCategory("basic", clientCmd), WithCategory("basic", clientCmd),
WithCategory("basic", multisigCmd), WithCategory("basic", multisigCmd),
WithCategory("basic", paychCmd), WithCategory("basic", paychCmd),
WithCategory("developer", authCmd), WithCategory("developer", AuthCmd),
WithCategory("developer", mpoolCmd), WithCategory("developer", MpoolCmd),
WithCategory("developer", stateCmd), WithCategory("developer", StateCmd),
WithCategory("developer", chainCmd), WithCategory("developer", ChainCmd),
WithCategory("developer", logCmd), WithCategory("developer", LogCmd),
WithCategory("developer", waitApiCmd), WithCategory("developer", WaitApiCmd),
WithCategory("developer", fetchParamCmd), WithCategory("developer", FetchParamCmd),
WithCategory("network", netCmd), WithCategory("network", NetCmd),
WithCategory("network", syncCmd), WithCategory("network", SyncCmd),
pprofCmd, PprofCmd,
VersionCmd, VersionCmd,
} }

View File

@ -35,7 +35,7 @@ type minerDeadline struct {
index uint64 index uint64
} }
var chainDisputeSetCmd = &cli.Command{ var ChainDisputeSetCmd = &cli.Command{
Name: "disputer", Name: "disputer",
Usage: "interact with the window post disputer", Usage: "interact with the window post disputer",
Flags: []cli.Flag{ Flags: []cli.Flag{

View File

@ -7,16 +7,16 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
) )
var logCmd = &cli.Command{ var LogCmd = &cli.Command{
Name: "log", Name: "log",
Usage: "Manage logging", Usage: "Manage logging",
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
logList, LogList,
logSetLevel, LogSetLevel,
}, },
} }
var logList = &cli.Command{ var LogList = &cli.Command{
Name: "list", Name: "list",
Usage: "List log systems", Usage: "List log systems",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
@ -41,7 +41,7 @@ var logList = &cli.Command{
}, },
} }
var logSetLevel = &cli.Command{ var LogSetLevel = &cli.Command{
Name: "set-level", Name: "set-level",
Usage: "Set log level", Usage: "Set log level",
ArgsUsage: "[level]", ArgsUsage: "[level]",

View File

@ -22,22 +22,22 @@ import (
"github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/config"
) )
var mpoolCmd = &cli.Command{ var MpoolCmd = &cli.Command{
Name: "mpool", Name: "mpool",
Usage: "Manage message pool", Usage: "Manage message pool",
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
mpoolPending, MpoolPending,
mpoolClear, MpoolClear,
mpoolSub, MpoolSub,
mpoolStat, MpoolStat,
mpoolReplaceCmd, MpoolReplaceCmd,
mpoolFindCmd, MpoolFindCmd,
mpoolConfig, MpoolConfig,
mpoolGasPerfCmd, MpoolGasPerfCmd,
}, },
} }
var mpoolPending = &cli.Command{ var MpoolPending = &cli.Command{
Name: "pending", Name: "pending",
Usage: "Get pending messages", Usage: "Get pending messages",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -132,7 +132,7 @@ var mpoolPending = &cli.Command{
}, },
} }
var mpoolClear = &cli.Command{ var MpoolClear = &cli.Command{
Name: "clear", Name: "clear",
Usage: "Clear all pending messages from the mpool (USE WITH CARE)", Usage: "Clear all pending messages from the mpool (USE WITH CARE)",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -165,7 +165,7 @@ var mpoolClear = &cli.Command{
}, },
} }
var mpoolSub = &cli.Command{ var MpoolSub = &cli.Command{
Name: "sub", Name: "sub",
Usage: "Subscribe to mpool changes", Usage: "Subscribe to mpool changes",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
@ -197,7 +197,7 @@ var mpoolSub = &cli.Command{
}, },
} }
var mpoolStat = &cli.Command{ var MpoolStat = &cli.Command{
Name: "stat", Name: "stat",
Usage: "print mempool stats", Usage: "print mempool stats",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -356,7 +356,7 @@ var mpoolStat = &cli.Command{
}, },
} }
var mpoolReplaceCmd = &cli.Command{ var MpoolReplaceCmd = &cli.Command{
Name: "replace", Name: "replace",
Usage: "replace a message in the mempool", Usage: "replace a message in the mempool",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -509,7 +509,7 @@ var mpoolReplaceCmd = &cli.Command{
}, },
} }
var mpoolFindCmd = &cli.Command{ var MpoolFindCmd = &cli.Command{
Name: "find", Name: "find",
Usage: "find a message in the mempool", Usage: "find a message in the mempool",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -592,7 +592,7 @@ var mpoolFindCmd = &cli.Command{
}, },
} }
var mpoolConfig = &cli.Command{ var MpoolConfig = &cli.Command{
Name: "config", Name: "config",
Usage: "get or set current mpool configuration", Usage: "get or set current mpool configuration",
ArgsUsage: "[new-config]", ArgsUsage: "[new-config]",
@ -637,7 +637,7 @@ var mpoolConfig = &cli.Command{
}, },
} }
var mpoolGasPerfCmd = &cli.Command{ var MpoolGasPerfCmd = &cli.Command{
Name: "gas-perf", Name: "gas-perf",
Usage: "Check gas performance of messages in mempool", Usage: "Check gas performance of messages in mempool",
Flags: []cli.Flag{ Flags: []cli.Flag{

View File

@ -23,16 +23,16 @@ import (
"github.com/filecoin-project/lotus/lib/addrutil" "github.com/filecoin-project/lotus/lib/addrutil"
) )
var netCmd = &cli.Command{ var NetCmd = &cli.Command{
Name: "net", Name: "net",
Usage: "Manage P2P Network", Usage: "Manage P2P Network",
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
NetPeers, NetPeers,
netConnect, NetConnect,
NetListen, NetListen,
NetId, NetId,
netFindPeer, NetFindPeer,
netScores, NetScores,
NetReachability, NetReachability,
NetBandwidthCmd, NetBandwidthCmd,
NetBlockCmd, NetBlockCmd,
@ -112,7 +112,7 @@ var NetPeers = &cli.Command{
}, },
} }
var netScores = &cli.Command{ var NetScores = &cli.Command{
Name: "scores", Name: "scores",
Usage: "Print peers' pubsub scores", Usage: "Print peers' pubsub scores",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -175,7 +175,7 @@ var NetListen = &cli.Command{
}, },
} }
var netConnect = &cli.Command{ var NetConnect = &cli.Command{
Name: "connect", Name: "connect",
Usage: "Connect to a peer", Usage: "Connect to a peer",
ArgsUsage: "[peerMultiaddr|minerActorAddress]", ArgsUsage: "[peerMultiaddr|minerActorAddress]",
@ -264,7 +264,7 @@ var NetId = &cli.Command{
}, },
} }
var netFindPeer = &cli.Command{ var NetFindPeer = &cli.Command{
Name: "findpeer", Name: "findpeer",
Usage: "Find the addresses of a given peerID", Usage: "Find the addresses of a given peerID",
ArgsUsage: "[peerId]", ArgsUsage: "[peerId]",

View File

@ -9,7 +9,7 @@ import (
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
) )
var fetchParamCmd = &cli.Command{ var FetchParamCmd = &cli.Command{
Name: "fetch-params", Name: "fetch-params",
Usage: "Fetch proving parameters", Usage: "Fetch proving parameters",
ArgsUsage: "[sectorSize]", ArgsUsage: "[sectorSize]",

View File

@ -11,7 +11,7 @@ import (
"github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/node/repo"
) )
var pprofCmd = &cli.Command{ var PprofCmd = &cli.Command{
Name: "pprof", Name: "pprof",
Hidden: true, Hidden: true,
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{

View File

@ -41,7 +41,7 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
var stateCmd = &cli.Command{ var StateCmd = &cli.Command{
Name: "state", Name: "state",
Usage: "Interact with and query filecoin chain state", Usage: "Interact with and query filecoin chain state",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -51,32 +51,32 @@ var stateCmd = &cli.Command{
}, },
}, },
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
statePowerCmd, StatePowerCmd,
stateSectorsCmd, StateSectorsCmd,
stateActiveSectorsCmd, StateActiveSectorsCmd,
stateListActorsCmd, StateListActorsCmd,
stateListMinersCmd, StateListMinersCmd,
stateCircSupplyCmd, StateCircSupplyCmd,
stateSectorCmd, StateSectorCmd,
stateGetActorCmd, StateGetActorCmd,
stateLookupIDCmd, StateLookupIDCmd,
stateReplayCmd, StateReplayCmd,
stateSectorSizeCmd, StateSectorSizeCmd,
stateReadStateCmd, StateReadStateCmd,
stateListMessagesCmd, StateListMessagesCmd,
stateComputeStateCmd, StateComputeStateCmd,
stateCallCmd, StateCallCmd,
stateGetDealSetCmd, StateGetDealSetCmd,
stateWaitMsgCmd, StateWaitMsgCmd,
stateSearchMsgCmd, StateSearchMsgCmd,
stateMinerInfo, StateMinerInfo,
stateMarketCmd, StateMarketCmd,
stateExecTraceCmd, StateExecTraceCmd,
stateNtwkVersionCmd, StateNtwkVersionCmd,
}, },
} }
var stateMinerInfo = &cli.Command{ var StateMinerInfo = &cli.Command{
Name: "miner-info", Name: "miner-info",
Usage: "Retrieve miner information", Usage: "Retrieve miner information",
ArgsUsage: "[minerAddress]", ArgsUsage: "[minerAddress]",
@ -219,7 +219,7 @@ func ParseTipSetRef(ctx context.Context, api api.FullNode, tss string) (*types.T
return ts, nil return ts, nil
} }
var statePowerCmd = &cli.Command{ var StatePowerCmd = &cli.Command{
Name: "power", Name: "power",
Usage: "Query network or miner power", Usage: "Query network or miner power",
ArgsUsage: "[<minerAddress> (optional)]", ArgsUsage: "[<minerAddress> (optional)]",
@ -263,7 +263,7 @@ var statePowerCmd = &cli.Command{
}, },
} }
var stateSectorsCmd = &cli.Command{ var StateSectorsCmd = &cli.Command{
Name: "sectors", Name: "sectors",
Usage: "Query the sector set of a miner", Usage: "Query the sector set of a miner",
ArgsUsage: "[minerAddress]", ArgsUsage: "[minerAddress]",
@ -303,7 +303,7 @@ var stateSectorsCmd = &cli.Command{
}, },
} }
var stateActiveSectorsCmd = &cli.Command{ var StateActiveSectorsCmd = &cli.Command{
Name: "active-sectors", Name: "active-sectors",
Usage: "Query the active sector set of a miner", Usage: "Query the active sector set of a miner",
ArgsUsage: "[minerAddress]", ArgsUsage: "[minerAddress]",
@ -343,7 +343,7 @@ var stateActiveSectorsCmd = &cli.Command{
}, },
} }
var stateExecTraceCmd = &cli.Command{ var StateExecTraceCmd = &cli.Command{
Name: "exec-trace", Name: "exec-trace",
Usage: "Get the execution trace of a given message", Usage: "Get the execution trace of a given message",
ArgsUsage: "<messageCid>", ArgsUsage: "<messageCid>",
@ -411,7 +411,7 @@ var stateExecTraceCmd = &cli.Command{
}, },
} }
var stateReplayCmd = &cli.Command{ var StateReplayCmd = &cli.Command{
Name: "replay", Name: "replay",
Usage: "Replay a particular message", Usage: "Replay a particular message",
ArgsUsage: "<messageCid>", ArgsUsage: "<messageCid>",
@ -476,7 +476,7 @@ var stateReplayCmd = &cli.Command{
}, },
} }
var stateGetDealSetCmd = &cli.Command{ var StateGetDealSetCmd = &cli.Command{
Name: "get-deal", Name: "get-deal",
Usage: "View on-chain deal info", Usage: "View on-chain deal info",
ArgsUsage: "[dealId]", ArgsUsage: "[dealId]",
@ -518,7 +518,7 @@ var stateGetDealSetCmd = &cli.Command{
}, },
} }
var stateListMinersCmd = &cli.Command{ var StateListMinersCmd = &cli.Command{
Name: "list-miners", Name: "list-miners",
Usage: "list all miners in the network", Usage: "list all miners in the network",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -590,7 +590,7 @@ func getDealsCounts(ctx context.Context, lapi api.FullNode) (map[address.Address
return out, nil return out, nil
} }
var stateListActorsCmd = &cli.Command{ var StateListActorsCmd = &cli.Command{
Name: "list-actors", Name: "list-actors",
Usage: "list all actors in the network", Usage: "list all actors in the network",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
@ -620,7 +620,7 @@ var stateListActorsCmd = &cli.Command{
}, },
} }
var stateGetActorCmd = &cli.Command{ var StateGetActorCmd = &cli.Command{
Name: "get-actor", Name: "get-actor",
Usage: "Print actor information", Usage: "Print actor information",
ArgsUsage: "[actorrAddress]", ArgsUsage: "[actorrAddress]",
@ -664,7 +664,7 @@ var stateGetActorCmd = &cli.Command{
}, },
} }
var stateLookupIDCmd = &cli.Command{ var StateLookupIDCmd = &cli.Command{
Name: "lookup", Name: "lookup",
Usage: "Find corresponding ID address", Usage: "Find corresponding ID address",
ArgsUsage: "[address]", ArgsUsage: "[address]",
@ -715,7 +715,7 @@ var stateLookupIDCmd = &cli.Command{
}, },
} }
var stateSectorSizeCmd = &cli.Command{ var StateSectorSizeCmd = &cli.Command{
Name: "sector-size", Name: "sector-size",
Usage: "Look up miners sector size", Usage: "Look up miners sector size",
ArgsUsage: "[minerAddress]", ArgsUsage: "[minerAddress]",
@ -752,7 +752,7 @@ var stateSectorSizeCmd = &cli.Command{
}, },
} }
var stateReadStateCmd = &cli.Command{ var StateReadStateCmd = &cli.Command{
Name: "read-state", Name: "read-state",
Usage: "View a json representation of an actors state", Usage: "View a json representation of an actors state",
ArgsUsage: "[actorAddress]", ArgsUsage: "[actorAddress]",
@ -794,7 +794,7 @@ var stateReadStateCmd = &cli.Command{
}, },
} }
var stateListMessagesCmd = &cli.Command{ var StateListMessagesCmd = &cli.Command{
Name: "list-messages", Name: "list-messages",
Usage: "list messages on chain matching given criteria", Usage: "list messages on chain matching given criteria",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -907,7 +907,7 @@ var stateListMessagesCmd = &cli.Command{
}, },
} }
var stateComputeStateCmd = &cli.Command{ var StateComputeStateCmd = &cli.Command{
Name: "compute-state", Name: "compute-state",
Usage: "Perform state computations", Usage: "Perform state computations",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -1365,7 +1365,7 @@ func jsonReturn(code cid.Cid, method abi.MethodNum, ret []byte) (string, error)
return string(b), err return string(b), err
} }
var stateWaitMsgCmd = &cli.Command{ var StateWaitMsgCmd = &cli.Command{
Name: "wait-msg", Name: "wait-msg",
Usage: "Wait for a message to appear on chain", Usage: "Wait for a message to appear on chain",
ArgsUsage: "[messageCid]", ArgsUsage: "[messageCid]",
@ -1407,7 +1407,7 @@ var stateWaitMsgCmd = &cli.Command{
}, },
} }
var stateSearchMsgCmd = &cli.Command{ var StateSearchMsgCmd = &cli.Command{
Name: "search-msg", Name: "search-msg",
Usage: "Search to see whether a message has appeared on chain", Usage: "Search to see whether a message has appeared on chain",
ArgsUsage: "[messageCid]", ArgsUsage: "[messageCid]",
@ -1484,7 +1484,7 @@ func printMsg(ctx context.Context, api api.FullNode, msg cid.Cid, mw *lapi.MsgLo
return nil return nil
} }
var stateCallCmd = &cli.Command{ var StateCallCmd = &cli.Command{
Name: "call", Name: "call",
Usage: "Invoke a method on an actor locally", Usage: "Invoke a method on an actor locally",
ArgsUsage: "[toAddress methodId <param1 param2 ...> (optional)]", ArgsUsage: "[toAddress methodId <param1 param2 ...> (optional)]",
@ -1692,7 +1692,7 @@ func parseParamsForMethod(act cid.Cid, method uint64, args []string) ([]byte, er
return buf.Bytes(), nil return buf.Bytes(), nil
} }
var stateCircSupplyCmd = &cli.Command{ var StateCircSupplyCmd = &cli.Command{
Name: "circulating-supply", Name: "circulating-supply",
Usage: "Get the exact current circulating supply of Filecoin", Usage: "Get the exact current circulating supply of Filecoin",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -1741,7 +1741,7 @@ var stateCircSupplyCmd = &cli.Command{
}, },
} }
var stateSectorCmd = &cli.Command{ var StateSectorCmd = &cli.Command{
Name: "sector", Name: "sector",
Usage: "Get miner sector info", Usage: "Get miner sector info",
ArgsUsage: "[miner address] [sector number]", ArgsUsage: "[miner address] [sector number]",
@ -1815,7 +1815,7 @@ var stateSectorCmd = &cli.Command{
}, },
} }
var stateMarketCmd = &cli.Command{ var StateMarketCmd = &cli.Command{
Name: "market", Name: "market",
Usage: "Inspect the storage market actor", Usage: "Inspect the storage market actor",
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
@ -1861,7 +1861,7 @@ var stateMarketBalanceCmd = &cli.Command{
}, },
} }
var stateNtwkVersionCmd = &cli.Command{ var StateNtwkVersionCmd = &cli.Command{
Name: "network-version", Name: "network-version",
Usage: "Returns the network version", Usage: "Returns the network version",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {

View File

@ -15,20 +15,20 @@ import (
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
) )
var syncCmd = &cli.Command{ var SyncCmd = &cli.Command{
Name: "sync", Name: "sync",
Usage: "Inspect or interact with the chain syncer", Usage: "Inspect or interact with the chain syncer",
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
syncStatusCmd, SyncStatusCmd,
syncWaitCmd, SyncWaitCmd,
syncMarkBadCmd, SyncMarkBadCmd,
syncUnmarkBadCmd, SyncUnmarkBadCmd,
syncCheckBadCmd, SyncCheckBadCmd,
syncCheckpointCmd, SyncCheckpointCmd,
}, },
} }
var syncStatusCmd = &cli.Command{ var SyncStatusCmd = &cli.Command{
Name: "status", Name: "status",
Usage: "check sync status", Usage: "check sync status",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
@ -81,7 +81,7 @@ var syncStatusCmd = &cli.Command{
}, },
} }
var syncWaitCmd = &cli.Command{ var SyncWaitCmd = &cli.Command{
Name: "wait", Name: "wait",
Usage: "Wait for sync to be complete", Usage: "Wait for sync to be complete",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -102,7 +102,7 @@ var syncWaitCmd = &cli.Command{
}, },
} }
var syncMarkBadCmd = &cli.Command{ var SyncMarkBadCmd = &cli.Command{
Name: "mark-bad", Name: "mark-bad",
Usage: "Mark the given block as bad, will prevent syncing to a chain that contains it", Usage: "Mark the given block as bad, will prevent syncing to a chain that contains it",
ArgsUsage: "[blockCid]", ArgsUsage: "[blockCid]",
@ -127,7 +127,7 @@ var syncMarkBadCmd = &cli.Command{
}, },
} }
var syncUnmarkBadCmd = &cli.Command{ var SyncUnmarkBadCmd = &cli.Command{
Name: "unmark-bad", Name: "unmark-bad",
Usage: "Unmark the given block as bad, makes it possible to sync to a chain containing it", Usage: "Unmark the given block as bad, makes it possible to sync to a chain containing it",
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -162,7 +162,7 @@ var syncUnmarkBadCmd = &cli.Command{
}, },
} }
var syncCheckBadCmd = &cli.Command{ var SyncCheckBadCmd = &cli.Command{
Name: "check-bad", Name: "check-bad",
Usage: "check if the given block was marked bad, and for what reason", Usage: "check if the given block was marked bad, and for what reason",
ArgsUsage: "[blockCid]", ArgsUsage: "[blockCid]",
@ -198,7 +198,7 @@ var syncCheckBadCmd = &cli.Command{
}, },
} }
var syncCheckpointCmd = &cli.Command{ var SyncCheckpointCmd = &cli.Command{
Name: "checkpoint", Name: "checkpoint",
Usage: "mark a certain tipset as checkpointed; the node will never fork away from this tipset", Usage: "mark a certain tipset as checkpointed; the node will never fork away from this tipset",
ArgsUsage: "[tipsetKey]", ArgsUsage: "[tipsetKey]",

View File

@ -230,7 +230,7 @@ func GetStorageMinerAPI(ctx *cli.Context, opts ...GetStorageMinerOption) (api.St
return client.NewStorageMinerRPC(ctx.Context, addr, headers) return client.NewStorageMinerRPC(ctx.Context, addr, headers)
} }
func GetWorkerAPI(ctx *cli.Context) (api.WorkerAPI, jsonrpc.ClientCloser, error) { func GetWorkerAPI(ctx *cli.Context) (api.Worker, jsonrpc.ClientCloser, error) {
addr, headers, err := GetRawAPI(ctx, repo.Worker) addr, headers, err := GetRawAPI(ctx, repo.Worker)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -239,7 +239,7 @@ func GetWorkerAPI(ctx *cli.Context) (api.WorkerAPI, jsonrpc.ClientCloser, error)
return client.NewWorkerRPC(ctx.Context, addr, headers) return client.NewWorkerRPC(ctx.Context, addr, headers)
} }
func GetGatewayAPI(ctx *cli.Context) (api.GatewayAPI, jsonrpc.ClientCloser, error) { func GetGatewayAPI(ctx *cli.Context) (api.Gateway, jsonrpc.ClientCloser, error) {
addr, headers, err := GetRawAPI(ctx, repo.FullNode) addr, headers, err := GetRawAPI(ctx, repo.FullNode)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err

View File

@ -7,7 +7,7 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
var waitApiCmd = &cli.Command{ var WaitApiCmd = &cli.Command{
Name: "wait-api", Name: "wait-api",
Usage: "Wait for lotus api to come online", Usage: "Wait for lotus api to come online",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {

View File

@ -404,7 +404,7 @@ func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg []
return sigs.Verify(sig, k, msg) == nil, nil return sigs.Verify(sig, k, msg) == nil, nil
} }
var _ api.GatewayAPI = (*GatewayAPI)(nil) var _ api.Gateway = (*GatewayAPI)(nil)
var _ full.ChainModuleAPI = (*GatewayAPI)(nil) var _ full.ChainModuleAPI = (*GatewayAPI)(nil)
var _ full.GasModuleAPI = (*GatewayAPI)(nil) var _ full.GasModuleAPI = (*GatewayAPI)(nil)
var _ full.MpoolModuleAPI = (*GatewayAPI)(nil) var _ full.MpoolModuleAPI = (*GatewayAPI)(nil)

View File

@ -249,12 +249,12 @@ func startNodes(
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
var gapi api.GatewayAPI var gapi api.Gateway
gapi, closer, err = client.NewGatewayRPC(ctx, addr, nil) gapi, closer, err = client.NewGatewayRPC(ctx, addr, nil)
require.NoError(t, err) require.NoError(t, err)
// Provide the gateway API to dependency injection // Provide the gateway API to dependency injection
return node.Override(new(api.GatewayAPI), gapi) return node.Override(new(api.Gateway), gapi)
}, },
}, },
) )

View File

@ -9,6 +9,8 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
apitypes "github.com/filecoin-project/lotus/api/types"
"github.com/filecoin-project/lotus/build"
sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage"
"github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/extern/sector-storage/stores"
"github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/lotus/extern/sector-storage/storiface"
@ -76,4 +78,8 @@ func (w *worker) Session(ctx context.Context) (uuid.UUID, error) {
return w.LocalWorker.Session(ctx) return w.LocalWorker.Session(ctx)
} }
func (w *worker) Discover(ctx context.Context) (apitypes.OpenRPCDocument, error) {
return build.OpenRPCDiscoverJSON_Worker(), nil
}
var _ storiface.WorkerCalls = &worker{} var _ storiface.WorkerCalls = &worker{}

View File

@ -41,17 +41,17 @@ var tasksEnableCmd = &cli.Command{
Name: "enable", Name: "enable",
Usage: "Enable a task type", Usage: "Enable a task type",
ArgsUsage: "[" + settableStr + "]", ArgsUsage: "[" + settableStr + "]",
Action: taskAction(api.WorkerAPI.TaskEnable), Action: taskAction(api.Worker.TaskEnable),
} }
var tasksDisableCmd = &cli.Command{ var tasksDisableCmd = &cli.Command{
Name: "disable", Name: "disable",
Usage: "Disable a task type", Usage: "Disable a task type",
ArgsUsage: "[" + settableStr + "]", ArgsUsage: "[" + settableStr + "]",
Action: taskAction(api.WorkerAPI.TaskDisable), Action: taskAction(api.Worker.TaskDisable),
} }
func taskAction(tf func(a api.WorkerAPI, ctx context.Context, tt sealtasks.TaskType) error) func(cctx *cli.Context) error { func taskAction(tf func(a api.Worker, ctx context.Context, tt sealtasks.TaskType) error) func(cctx *cli.Context) error {
return func(cctx *cli.Context) error { return func(cctx *cli.Context) error {
if cctx.NArg() != 1 { if cctx.NArg() != 1 {
return xerrors.Errorf("expected 1 argument") return xerrors.Errorf("expected 1 argument")

75
cmd/lotus-shed/base64.go Normal file
View File

@ -0,0 +1,75 @@
package main
import (
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"os"
"strings"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-address"
"github.com/urfave/cli/v2"
)
var base64Cmd = &cli.Command{
Name: "base64",
Description: "multiformats base64",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "decodeAddr",
Value: false,
Usage: "Decode a base64 addr",
},
&cli.BoolFlag{
Name: "decodeBig",
Value: false,
Usage: "Decode a base64 big",
},
},
Action: func(cctx *cli.Context) error {
var input io.Reader
if cctx.Args().Len() == 0 {
input = os.Stdin
} else {
input = strings.NewReader(cctx.Args().First())
}
bytes, err := ioutil.ReadAll(input)
if err != nil {
return nil
}
decoded, err := base64.RawStdEncoding.DecodeString(strings.TrimSpace(string(bytes)))
if err != nil {
return err
}
if cctx.Bool("decodeAddr") {
addr, err := address.NewFromBytes(decoded)
if err != nil {
return err
}
fmt.Println(addr)
return nil
}
if cctx.Bool("decodeBig") {
var val abi.TokenAmount
err = val.UnmarshalBinary(decoded)
if err != nil {
return err
}
fmt.Println(val)
}
return nil
},
}

View File

@ -180,8 +180,11 @@ var datastoreBackupStatCmd = &cli.Command{
} }
defer f.Close() // nolint:errcheck defer f.Close() // nolint:errcheck
var keys, kbytes, vbytes uint64 var keys, logs, kbytes, vbytes uint64
err = backupds.ReadBackup(f, func(key datastore.Key, value []byte) error { err = backupds.ReadBackup(f, func(key datastore.Key, value []byte, log bool) error {
if log {
logs++
}
keys++ keys++
kbytes += uint64(len(key.String())) kbytes += uint64(len(key.String()))
vbytes += uint64(len(value)) vbytes += uint64(len(value))
@ -192,6 +195,7 @@ var datastoreBackupStatCmd = &cli.Command{
} }
fmt.Println("Keys: ", keys) fmt.Println("Keys: ", keys)
fmt.Println("Log values: ", log)
fmt.Println("Key bytes: ", units.BytesSize(float64(kbytes))) fmt.Println("Key bytes: ", units.BytesSize(float64(kbytes)))
fmt.Println("Value bytes: ", units.BytesSize(float64(vbytes))) fmt.Println("Value bytes: ", units.BytesSize(float64(vbytes)))
@ -225,7 +229,7 @@ var datastoreBackupListCmd = &cli.Command{
defer f.Close() // nolint:errcheck defer f.Close() // nolint:errcheck
printKv := kvPrinter(cctx.Bool("top-level"), cctx.String("get-enc")) printKv := kvPrinter(cctx.Bool("top-level"), cctx.String("get-enc"))
err = backupds.ReadBackup(f, func(key datastore.Key, value []byte) error { err = backupds.ReadBackup(f, func(key datastore.Key, value []byte, _ bool) error {
return printKv(key.String(), value) return printKv(key.String(), value)
}) })
if err != nil { if err != nil {

View File

@ -7,30 +7,35 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli" lcli "github.com/filecoin-project/lotus/cli"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
) )
var electionCmd = &cli.Command{ var electionCmd = &cli.Command{
Name: "election", Name: "election",
Usage: "commands related to leader election", Usage: "Commands related to leader election",
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
electionRunDummy, electionRunDummy,
electionEstimate,
}, },
} }
var electionRunDummy = &cli.Command{ var electionRunDummy = &cli.Command{
Name: "run-dummy", Name: "run-dummy",
Usage: "runs dummy elections with given power", Usage: "Runs dummy elections with given power",
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: "network-power", Name: "network-power",
Usage: "network storage power",
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "miner-power", Name: "miner-power",
Usage: "miner storage power",
}, },
&cli.Uint64Flag{ &cli.Uint64Flag{
Name: "seed", Name: "seed",
Usage: "rand number",
Value: 0, Value: 0,
}, },
}, },
@ -42,7 +47,7 @@ var electionRunDummy = &cli.Command{
} }
networkPow, err := types.BigFromString(cctx.String("network-power")) networkPow, err := types.BigFromString(cctx.String("network-power"))
if err != nil { if err != nil {
return xerrors.Errorf("decoding miner-power: %w", err) return xerrors.Errorf("decoding network-power: %w", err)
} }
ep := &types.ElectionProof{} ep := &types.ElectionProof{}
@ -68,3 +73,54 @@ var electionRunDummy = &cli.Command{
} }
}, },
} }
var electionEstimate = &cli.Command{
Name: "estimate",
Usage: "Estimate elections with given power",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "network-power",
Usage: "network storage power",
},
&cli.StringFlag{
Name: "miner-power",
Usage: "miner storage power",
},
&cli.Uint64Flag{
Name: "seed",
Usage: "rand number",
Value: 0,
},
},
Action: func(cctx *cli.Context) error {
minerPow, err := types.BigFromString(cctx.String("miner-power"))
if err != nil {
return xerrors.Errorf("decoding miner-power: %w", err)
}
networkPow, err := types.BigFromString(cctx.String("network-power"))
if err != nil {
return xerrors.Errorf("decoding network-power: %w", err)
}
ep := &types.ElectionProof{}
ep.VRFProof = make([]byte, 32)
seed := cctx.Uint64("seed")
if seed == 0 {
seed = rand.Uint64()
}
binary.BigEndian.PutUint64(ep.VRFProof, seed)
winYear := int64(0)
for i := 0; i < builtin2.EpochsInYear; i++ {
binary.BigEndian.PutUint64(ep.VRFProof[8:], uint64(i))
j := ep.ComputeWinCount(minerPow, networkPow)
winYear += j
}
winHour := winYear * builtin2.EpochsInHour / builtin2.EpochsInYear
winDay := winYear * builtin2.EpochsInDay / builtin2.EpochsInYear
winMonth := winYear * builtin2.EpochsInDay * 30 / builtin2.EpochsInYear
fmt.Println("winInHour, winInDay, winInMonth, winInYear")
fmt.Printf("%d, %d, %d, %d\n", winHour, winDay, winMonth, winYear)
return nil
},
}

View File

@ -16,6 +16,7 @@ func main() {
logging.SetLogLevel("*", "INFO") logging.SetLogLevel("*", "INFO")
local := []*cli.Command{ local := []*cli.Command{
base64Cmd,
base32Cmd, base32Cmd,
base16Cmd, base16Cmd,
bitFieldCmd, bitFieldCmd,
@ -52,6 +53,7 @@ func main() {
rpcCmd, rpcCmd,
cidCmd, cidCmd,
blockmsgidCmd, blockmsgidCmd,
signaturesCmd,
} }
app := &cli.App{ app := &cli.App{

View File

@ -6,6 +6,7 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/big"
@ -34,6 +35,10 @@ var terminateSectorCmd = &cli.Command{
Usage: "Forcefully terminate a sector (WARNING: This means losing power and pay a one-time termination penalty(including collateral) for the terminated sector)", Usage: "Forcefully terminate a sector (WARNING: This means losing power and pay a one-time termination penalty(including collateral) for the terminated sector)",
ArgsUsage: "[sectorNum1 sectorNum2 ...]", ArgsUsage: "[sectorNum1 sectorNum2 ...]",
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{
Name: "actor",
Usage: "specify the address of miner actor",
},
&cli.BoolFlag{ &cli.BoolFlag{
Name: "really-do-it", Name: "really-do-it",
Usage: "pass this flag if you know what you are doing", Usage: "pass this flag if you know what you are doing",
@ -44,6 +49,15 @@ var terminateSectorCmd = &cli.Command{
return fmt.Errorf("at least one sector must be specified") return fmt.Errorf("at least one sector must be specified")
} }
var maddr address.Address
if act := cctx.String("actor"); act != "" {
var err error
maddr, err = address.NewFromString(act)
if err != nil {
return fmt.Errorf("parsing address %s: %w", act, err)
}
}
if !cctx.Bool("really-do-it") { if !cctx.Bool("really-do-it") {
return fmt.Errorf("this is a command for advanced users, only use it if you are sure of what you are doing") return fmt.Errorf("this is a command for advanced users, only use it if you are sure of what you are doing")
} }
@ -54,17 +68,19 @@ var terminateSectorCmd = &cli.Command{
} }
defer closer() defer closer()
api, acloser, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
return err
}
defer acloser()
ctx := lcli.ReqContext(cctx) ctx := lcli.ReqContext(cctx)
maddr, err := api.ActorAddress(ctx) if maddr.Empty() {
if err != nil { api, acloser, err := lcli.GetStorageMinerAPI(cctx)
return err if err != nil {
return err
}
defer acloser()
maddr, err = api.ActorAddress(ctx)
if err != nil {
return err
}
} }
mi, err := nodeApi.StateMinerInfo(ctx, maddr, types.EmptyTSK) mi, err := nodeApi.StateMinerInfo(ctx, maddr, types.EmptyTSK)
@ -147,28 +163,45 @@ var terminateSectorPenaltyEstimationCmd = &cli.Command{
Name: "termination-estimate", Name: "termination-estimate",
Usage: "Estimate the termination penalty", Usage: "Estimate the termination penalty",
ArgsUsage: "[sectorNum1 sectorNum2 ...]", ArgsUsage: "[sectorNum1 sectorNum2 ...]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "actor",
Usage: "specify the address of miner actor",
},
},
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() < 1 { if cctx.Args().Len() < 1 {
return fmt.Errorf("at least one sector must be specified") return fmt.Errorf("at least one sector must be specified")
} }
var maddr address.Address
if act := cctx.String("actor"); act != "" {
var err error
maddr, err = address.NewFromString(act)
if err != nil {
return fmt.Errorf("parsing address %s: %w", act, err)
}
}
nodeApi, closer, err := lcli.GetFullNodeAPI(cctx) nodeApi, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
} }
defer closer() defer closer()
api, acloser, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
return err
}
defer acloser()
ctx := lcli.ReqContext(cctx) ctx := lcli.ReqContext(cctx)
maddr, err := api.ActorAddress(ctx) if maddr.Empty() {
if err != nil { api, acloser, err := lcli.GetStorageMinerAPI(cctx)
return err if err != nil {
return err
}
defer acloser()
maddr, err = api.ActorAddress(ctx)
if err != nil {
return err
}
} }
mi, err := nodeApi.StateMinerInfo(ctx, maddr, types.EmptyTSK) mi, err := nodeApi.StateMinerInfo(ctx, maddr, types.EmptyTSK)

View File

@ -0,0 +1,74 @@
package main
import (
"encoding/hex"
"fmt"
"strconv"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/go-address"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
)
var signaturesCmd = &cli.Command{
Name: "signatures",
Usage: "tools involving signatures",
Subcommands: []*cli.Command{
sigsVerifyVoteCmd,
},
}
var sigsVerifyVoteCmd = &cli.Command{
Name: "verify-vote",
Description: "can be used to verify signed votes being submitted for FILPolls",
Usage: "<FIPnumber> <signingAddress> <signature>",
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 3 {
return xerrors.Errorf("usage: verify-vote <FIPnumber> <signingAddress> <signature>")
}
fip, err := strconv.ParseInt(cctx.Args().First(), 10, 64)
if err != nil {
return xerrors.Errorf("couldn't parse FIP number: %w", err)
}
addr, err := address.NewFromString(cctx.Args().Get(1))
if err != nil {
return xerrors.Errorf("couldn't parse signing address: %w", err)
}
sigBytes, err := hex.DecodeString(cctx.Args().Get(2))
if err != nil {
return xerrors.Errorf("couldn't parse sig: %w", err)
}
var sig crypto.Signature
if err := sig.UnmarshalBinary(sigBytes); err != nil {
return xerrors.Errorf("couldn't unmarshal sig: %w", err)
}
switch fip {
case 14:
approve := []byte("7 - Approve")
if sigs.Verify(&sig, addr, approve) == nil {
fmt.Println("valid vote for approving FIP-0014")
return nil
}
reject := []byte("7 - Reject")
if sigs.Verify(&sig, addr, reject) == nil {
fmt.Println("valid vote for rejecting FIP-0014")
return nil
}
return xerrors.Errorf("invalid vote for FIP-0014!")
default:
return xerrors.Errorf("unrecognized FIP number")
}
},
}

View File

@ -31,7 +31,7 @@ type InteractiveWallet struct {
lk sync.Mutex lk sync.Mutex
apiGetter func() (api.FullNode, jsonrpc.ClientCloser, error) apiGetter func() (api.FullNode, jsonrpc.ClientCloser, error)
under api.WalletAPI under api.Wallet
} }
func (c *InteractiveWallet) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) { func (c *InteractiveWallet) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) {

View File

@ -16,7 +16,7 @@ import (
) )
type LoggedWallet struct { type LoggedWallet struct {
under api.WalletAPI under api.Wallet
} }
func (c *LoggedWallet) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) { func (c *LoggedWallet) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) {

View File

@ -130,7 +130,7 @@ var runCmd = &cli.Command{
return err return err
} }
var w api.WalletAPI = lw var w api.Wallet = lw
if cctx.Bool("ledger") { if cctx.Bool("ledger") {
ds, err := lr.Datastore(context.Background(), "/metadata") ds, err := lr.Datastore(context.Background(), "/metadata")
if err != nil { if err != nil {

View File

@ -289,7 +289,7 @@ var DaemonCmd = &cli.Command{
shutdownChan := make(chan struct{}) shutdownChan := make(chan struct{})
// If the daemon is started in "lite mode", provide a GatewayAPI // If the daemon is started in "lite mode", provide a Gateway
// for RPC calls // for RPC calls
liteModeDeps := node.Options() liteModeDeps := node.Options()
if isLite { if isLite {
@ -299,7 +299,7 @@ var DaemonCmd = &cli.Command{
} }
defer closer() defer closer()
liteModeDeps = node.Override(new(api.GatewayAPI), gapi) liteModeDeps = node.Override(new(api.Gateway), gapi)
} }
// some libraries like ipfs/go-ds-measure and ipfs/go-ipfs-blockstore // some libraries like ipfs/go-ds-measure and ipfs/go-ipfs-blockstore

View File

@ -37,6 +37,7 @@ func serveRPC(a api.FullNode, stop node.StopFunc, addr multiaddr.Multiaddr, shut
} }
rpcServer := jsonrpc.NewServer(serverOptions...) rpcServer := jsonrpc.NewServer(serverOptions...)
rpcServer.Register("Filecoin", apistruct.PermissionedFullAPI(metrics.MetricedFullAPI(a))) rpcServer.Register("Filecoin", apistruct.PermissionedFullAPI(metrics.MetricedFullAPI(a)))
rpcServer.AliasMethod("rpc.discover", "Filecoin.Discover")
ah := &auth.Handler{ ah := &auth.Handler{
Verify: a.AuthVerify, Verify: a.AuthVerify,

View File

@ -1,6 +1,7 @@
# Groups # Groups
* [](#) * [](#)
* [Closing](#Closing) * [Closing](#Closing)
* [Discover](#Discover)
* [Session](#Session) * [Session](#Session)
* [Shutdown](#Shutdown) * [Shutdown](#Shutdown)
* [Version](#Version) * [Version](#Version)
@ -13,6 +14,8 @@
* [AuthVerify](#AuthVerify) * [AuthVerify](#AuthVerify)
* [Check](#Check) * [Check](#Check)
* [CheckProvable](#CheckProvable) * [CheckProvable](#CheckProvable)
* [Compute](#Compute)
* [ComputeProof](#ComputeProof)
* [Create](#Create) * [Create](#Create)
* [CreateBackup](#CreateBackup) * [CreateBackup](#CreateBackup)
* [Deals](#Deals) * [Deals](#Deals)
@ -142,6 +145,25 @@ Inputs: `null`
Response: `{}` Response: `{}`
### Discover
Perms: read
Inputs: `null`
Response:
```json
{
"info": {
"title": "Lotus RPC API",
"version": "1.2.1/generated=2020-11-22T08:22:42-06:00"
},
"methods": [],
"openrpc": "1.2.6"
}
```
### Session ### Session
@ -180,7 +202,7 @@ Response:
### ActorAddress ### ActorAddress
There are not yet any comments for this method.
Perms: read Perms: read
@ -189,7 +211,7 @@ Inputs: `null`
Response: `"f01234"` Response: `"f01234"`
### ActorAddressConfig ### ActorAddressConfig
There are not yet any comments for this method.
Perms: read Perms: read
@ -207,7 +229,7 @@ Response:
``` ```
### ActorSectorSize ### ActorSectorSize
There are not yet any comments for this method.
Perms: read Perms: read
@ -255,7 +277,7 @@ Response: `null`
### CheckProvable ### CheckProvable
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -275,6 +297,24 @@ Response:
} }
``` ```
## Compute
### ComputeProof
Perms: read
Inputs:
```json
[
null,
null
]
```
Response: `null`
## Create ## Create
@ -300,63 +340,63 @@ Response: `{}`
### DealsConsiderOfflineRetrievalDeals ### DealsConsiderOfflineRetrievalDeals
There are not yet any comments for this method.
Perms: read
Perms: admin
Inputs: `null` Inputs: `null`
Response: `true` Response: `true`
### DealsConsiderOfflineStorageDeals ### DealsConsiderOfflineStorageDeals
There are not yet any comments for this method.
Perms: read
Perms: admin
Inputs: `null` Inputs: `null`
Response: `true` Response: `true`
### DealsConsiderOnlineRetrievalDeals ### DealsConsiderOnlineRetrievalDeals
There are not yet any comments for this method.
Perms: read
Perms: admin
Inputs: `null` Inputs: `null`
Response: `true` Response: `true`
### DealsConsiderOnlineStorageDeals ### DealsConsiderOnlineStorageDeals
There are not yet any comments for this method.
Perms: read
Perms: admin
Inputs: `null` Inputs: `null`
Response: `true` Response: `true`
### DealsConsiderUnverifiedStorageDeals ### DealsConsiderUnverifiedStorageDeals
There are not yet any comments for this method.
Perms: read
Perms: admin
Inputs: `null` Inputs: `null`
Response: `true` Response: `true`
### DealsConsiderVerifiedStorageDeals ### DealsConsiderVerifiedStorageDeals
There are not yet any comments for this method.
Perms: read
Perms: admin
Inputs: `null` Inputs: `null`
Response: `true` Response: `true`
### DealsImportData ### DealsImportData
There are not yet any comments for this method.
Perms: write
Perms: admin
Inputs: Inputs:
```json ```json
@ -371,25 +411,25 @@ Inputs:
Response: `{}` Response: `{}`
### DealsList ### DealsList
There are not yet any comments for this method.
Perms: read
Perms: admin
Inputs: `null` Inputs: `null`
Response: `null` Response: `null`
### DealsPieceCidBlocklist ### DealsPieceCidBlocklist
There are not yet any comments for this method.
Perms: read
Perms: admin
Inputs: `null` Inputs: `null`
Response: `null` Response: `null`
### DealsSetConsiderOfflineRetrievalDeals ### DealsSetConsiderOfflineRetrievalDeals
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -403,7 +443,7 @@ Inputs:
Response: `{}` Response: `{}`
### DealsSetConsiderOfflineStorageDeals ### DealsSetConsiderOfflineStorageDeals
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -417,7 +457,7 @@ Inputs:
Response: `{}` Response: `{}`
### DealsSetConsiderOnlineRetrievalDeals ### DealsSetConsiderOnlineRetrievalDeals
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -431,7 +471,7 @@ Inputs:
Response: `{}` Response: `{}`
### DealsSetConsiderOnlineStorageDeals ### DealsSetConsiderOnlineStorageDeals
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -445,7 +485,7 @@ Inputs:
Response: `{}` Response: `{}`
### DealsSetConsiderUnverifiedStorageDeals ### DealsSetConsiderUnverifiedStorageDeals
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -459,7 +499,7 @@ Inputs:
Response: `{}` Response: `{}`
### DealsSetConsiderVerifiedStorageDeals ### DealsSetConsiderVerifiedStorageDeals
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -473,7 +513,7 @@ Inputs:
Response: `{}` Response: `{}`
### DealsSetPieceCidBlocklist ### DealsSetPieceCidBlocklist
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -546,7 +586,7 @@ Inputs:
Response: `{}` Response: `{}`
### MarketDataTransferUpdates ### MarketDataTransferUpdates
There are not yet any comments for this method.
Perms: write Perms: write
@ -565,12 +605,15 @@ Response:
"Voucher": "string value", "Voucher": "string value",
"Message": "string value", "Message": "string value",
"OtherPeer": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", "OtherPeer": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
"Transferred": 42 "Transferred": 42,
"Stages": {
"Stages": null
}
} }
``` ```
### MarketGetAsk ### MarketGetAsk
There are not yet any comments for this method.
Perms: read Perms: read
@ -597,7 +640,7 @@ Response:
``` ```
### MarketGetDealUpdates ### MarketGetDealUpdates
There are not yet any comments for this method.
Perms: read Perms: read
@ -662,7 +705,7 @@ Response:
``` ```
### MarketGetRetrievalAsk ### MarketGetRetrievalAsk
There are not yet any comments for this method.
Perms: read Perms: read
@ -679,7 +722,7 @@ Response:
``` ```
### MarketImportDealData ### MarketImportDealData
There are not yet any comments for this method.
Perms: write Perms: write
@ -696,7 +739,7 @@ Inputs:
Response: `{}` Response: `{}`
### MarketListDataTransfers ### MarketListDataTransfers
There are not yet any comments for this method.
Perms: write Perms: write
@ -705,7 +748,7 @@ Inputs: `null`
Response: `null` Response: `null`
### MarketListDeals ### MarketListDeals
There are not yet any comments for this method.
Perms: read Perms: read
@ -714,7 +757,7 @@ Inputs: `null`
Response: `null` Response: `null`
### MarketListIncompleteDeals ### MarketListIncompleteDeals
There are not yet any comments for this method.
Perms: read Perms: read
@ -723,7 +766,7 @@ Inputs: `null`
Response: `null` Response: `null`
### MarketListRetrievalDeals ### MarketListRetrievalDeals
There are not yet any comments for this method.
Perms: read Perms: read
@ -732,7 +775,7 @@ Inputs: `null`
Response: `null` Response: `null`
### MarketPendingDeals ### MarketPendingDeals
There are not yet any comments for this method.
Perms: write Perms: write
@ -748,7 +791,7 @@ Response:
``` ```
### MarketPublishPendingDeals ### MarketPublishPendingDeals
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -774,7 +817,7 @@ Inputs:
Response: `{}` Response: `{}`
### MarketSetAsk ### MarketSetAsk
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -792,7 +835,7 @@ Inputs:
Response: `{}` Response: `{}`
### MarketSetRetrievalAsk ### MarketSetRetrievalAsk
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -814,7 +857,7 @@ Response: `{}`
### MiningBase ### MiningBase
There are not yet any comments for this method.
Perms: read Perms: read
@ -1102,7 +1145,7 @@ Response: `null`
### PiecesGetCIDInfo ### PiecesGetCIDInfo
There are not yet any comments for this method.
Perms: read Perms: read
@ -1126,7 +1169,7 @@ Response:
``` ```
### PiecesGetPieceInfo ### PiecesGetPieceInfo
There are not yet any comments for this method.
Perms: read Perms: read
@ -1150,7 +1193,7 @@ Response:
``` ```
### PiecesListCidInfos ### PiecesListCidInfos
There are not yet any comments for this method.
Perms: read Perms: read
@ -1159,7 +1202,7 @@ Inputs: `null`
Response: `null` Response: `null`
### PiecesListPieces ### PiecesListPieces
There are not yet any comments for this method.
Perms: read Perms: read
@ -1190,6 +1233,7 @@ Response:
### ReturnAddPiece ### ReturnAddPiece
storiface.WorkerReturn
Perms: admin Perms: admin
@ -1475,7 +1519,7 @@ Response: `{}`
### SealingAbort ### SealingAbort
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -1534,7 +1578,7 @@ Inputs: `null`
Response: `60000000000` Response: `60000000000`
### SectorMarkForUpgrade ### SectorMarkForUpgrade
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -1688,7 +1732,7 @@ Response:
``` ```
### SectorsRefs ### SectorsRefs
There are not yet any comments for this method.
Perms: read Perms: read
@ -1771,7 +1815,7 @@ Response:
``` ```
### SectorsUpdate ### SectorsUpdate
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -1789,7 +1833,7 @@ Response: `{}`
### StorageAddLocal ### StorageAddLocal
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -1803,6 +1847,7 @@ Inputs:
Response: `{}` Response: `{}`
### StorageAttach ### StorageAttach
stores.SectorIndex
Perms: admin Perms: admin
@ -1931,7 +1976,7 @@ Response:
``` ```
### StorageList ### StorageList
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -1951,7 +1996,7 @@ Response:
``` ```
### StorageLocal ### StorageLocal
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -2009,7 +2054,7 @@ Inputs:
Response: `{}` Response: `{}`
### StorageStat ### StorageStat
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -2070,7 +2115,7 @@ Inputs:
Response: `{}` Response: `{}`
### WorkerJobs ### WorkerJobs
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -2102,7 +2147,7 @@ Response:
``` ```
### WorkerStats ### WorkerStats
There are not yet any comments for this method.
Perms: admin Perms: admin

View File

@ -40,7 +40,7 @@
### Enabled ### Enabled
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -81,7 +81,7 @@ Response:
``` ```
### Info ### Info
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -102,7 +102,7 @@ Response:
``` ```
### Paths ### Paths
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -139,7 +139,6 @@ Inputs: `null`
Response: `"07070707-0707-0707-0707-070707070707"` Response: `"07070707-0707-0707-0707-070707070707"`
### Version ### Version
TODO: Info() (name, ...) ?
Perms: admin Perms: admin
@ -152,6 +151,7 @@ Response: `65792`
### AddPiece ### AddPiece
storiface.WorkerCalls
Perms: admin Perms: admin
@ -488,7 +488,7 @@ Response: `{}`
### StorageAddLocal ### StorageAddLocal
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -505,7 +505,7 @@ Response: `{}`
### TaskDisable ### TaskDisable
There are not yet any comments for this method.
Perms: admin Perms: admin
@ -519,7 +519,7 @@ Inputs:
Response: `{}` Response: `{}`
### TaskEnable ### TaskEnable
There are not yet any comments for this method.
Perms: admin Perms: admin

View File

@ -1,6 +1,7 @@
# Groups # Groups
* [](#) * [](#)
* [Closing](#Closing) * [Closing](#Closing)
* [Discover](#Discover)
* [Session](#Session) * [Session](#Session)
* [Shutdown](#Shutdown) * [Shutdown](#Shutdown)
* [Version](#Version) * [Version](#Version)
@ -34,6 +35,7 @@
* [Client](#Client) * [Client](#Client)
* [ClientCalcCommP](#ClientCalcCommP) * [ClientCalcCommP](#ClientCalcCommP)
* [ClientCancelDataTransfer](#ClientCancelDataTransfer) * [ClientCancelDataTransfer](#ClientCancelDataTransfer)
* [ClientCancelRetrievalDeal](#ClientCancelRetrievalDeal)
* [ClientDataTransferUpdates](#ClientDataTransferUpdates) * [ClientDataTransferUpdates](#ClientDataTransferUpdates)
* [ClientDealPieceCID](#ClientDealPieceCID) * [ClientDealPieceCID](#ClientDealPieceCID)
* [ClientDealSize](#ClientDealSize) * [ClientDealSize](#ClientDealSize)
@ -226,6 +228,25 @@ Inputs: `null`
Response: `{}` Response: `{}`
### Discover
Perms: read
Inputs: `null`
Response:
```json
{
"info": {
"title": "Lotus RPC API",
"version": "1.2.1/generated=2020-11-22T08:22:42-06:00"
},
"methods": [],
"openrpc": "1.2.6"
}
```
### Session ### Session
@ -425,6 +446,17 @@ Response:
### ChainGetBlockMessages ### ChainGetBlockMessages
ChainGetBlockMessages returns messages stored in the specified block. ChainGetBlockMessages returns messages stored in the specified block.
Note: If there are multiple blocks in a tipset, it's likely that some
messages will be duplicated. It's also possible for blocks in a tipset to have
different messages from the same sender at the same nonce. When that happens,
only the first message (in a block with lowest ticket) will be considered
for execution
NOTE: THIS METHOD SHOULD ONLY BE USED FOR GETTING MESSAGES IN A SPECIFIC BLOCK
DO NOT USE THIS METHOD TO GET MESSAGES INCLUDED IN A TIPSET
Use ChainGetParentMessages, which will perform correct message deduplication
Perms: read Perms: read
@ -499,7 +531,7 @@ Response:
``` ```
### ChainGetNode ### ChainGetNode
There are not yet any comments for this method.
Perms: read Perms: read
@ -854,7 +886,7 @@ retrieval markets as a client
ClientCalcCommP calculates the CommP for a specified file ClientCalcCommP calculates the CommP for a specified file
Perms: read Perms: write
Inputs: Inputs:
```json ```json
@ -890,8 +922,23 @@ Inputs:
Response: `{}` Response: `{}`
### ClientCancelRetrievalDeal
ClientCancelRetrievalDeal cancels an ongoing retrieval deal based on DealID
Perms: write
Inputs:
```json
[
5
]
```
Response: `{}`
### ClientDataTransferUpdates ### ClientDataTransferUpdates
There are not yet any comments for this method.
Perms: write Perms: write
@ -910,7 +957,10 @@ Response:
"Voucher": "string value", "Voucher": "string value",
"Message": "string value", "Message": "string value",
"OtherPeer": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", "OtherPeer": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
"Transferred": 42 "Transferred": 42,
"Stages": {
"Stages": null
}
} }
``` ```
@ -1023,6 +1073,9 @@ Response:
}, },
"State": 42, "State": 42,
"Message": "string value", "Message": "string value",
"DealStages": {
"Stages": null
},
"Provider": "f01234", "Provider": "f01234",
"DataRef": { "DataRef": {
"TransferType": "string value", "TransferType": "string value",
@ -1058,7 +1111,10 @@ Response:
"Voucher": "string value", "Voucher": "string value",
"Message": "string value", "Message": "string value",
"OtherPeer": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", "OtherPeer": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
"Transferred": 42 "Transferred": 42,
"Stages": {
"Stages": null
}
} }
} }
``` ```
@ -1082,7 +1138,7 @@ Response: `"string value"`
ClientGetDealUpdates returns the status of updated deals ClientGetDealUpdates returns the status of updated deals
Perms: read Perms: write
Inputs: `null` Inputs: `null`
@ -1094,6 +1150,9 @@ Response:
}, },
"State": 42, "State": 42,
"Message": "string value", "Message": "string value",
"DealStages": {
"Stages": null
},
"Provider": "f01234", "Provider": "f01234",
"DataRef": { "DataRef": {
"TransferType": "string value", "TransferType": "string value",
@ -1129,7 +1188,10 @@ Response:
"Voucher": "string value", "Voucher": "string value",
"Message": "string value", "Message": "string value",
"OtherPeer": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", "OtherPeer": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
"Transferred": 42 "Transferred": 42,
"Stages": {
"Stages": null
}
} }
} }
``` ```
@ -1763,7 +1825,7 @@ Response:
### MinerCreateBlock ### MinerCreateBlock
There are not yet any comments for this method.
Perms: write Perms: write
@ -2179,7 +2241,7 @@ Response: `null`
MpoolSetConfig sets the mpool config to (a copy of) the supplied config MpoolSetConfig sets the mpool config to (a copy of) the supplied config
Perms: write Perms: admin
Inputs: Inputs:
```json ```json
@ -2198,7 +2260,7 @@ Inputs:
Response: `{}` Response: `{}`
### MpoolSub ### MpoolSub
There are not yet any comments for this method.
Perms: read Perms: read
@ -2944,7 +3006,7 @@ The Paych methods are for interacting with and managing payment channels
### PaychAllocateLane ### PaychAllocateLane
There are not yet any comments for this method.
Perms: sign Perms: sign
@ -2958,7 +3020,7 @@ Inputs:
Response: `42` Response: `42`
### PaychAvailableFunds ### PaychAvailableFunds
There are not yet any comments for this method.
Perms: sign Perms: sign
@ -2984,7 +3046,7 @@ Response:
``` ```
### PaychAvailableFundsByFromTo ### PaychAvailableFundsByFromTo
There are not yet any comments for this method.
Perms: sign Perms: sign
@ -3011,7 +3073,7 @@ Response:
``` ```
### PaychCollect ### PaychCollect
There are not yet any comments for this method.
Perms: sign Perms: sign
@ -3054,7 +3116,7 @@ Response:
``` ```
### PaychGetWaitReady ### PaychGetWaitReady
There are not yet any comments for this method.
Perms: sign Perms: sign
@ -3070,7 +3132,7 @@ Inputs:
Response: `"f01234"` Response: `"f01234"`
### PaychList ### PaychList
There are not yet any comments for this method.
Perms: read Perms: read
@ -3079,7 +3141,7 @@ Inputs: `null`
Response: `null` Response: `null`
### PaychNewPayment ### PaychNewPayment
There are not yet any comments for this method.
Perms: sign Perms: sign
@ -3104,7 +3166,7 @@ Response:
``` ```
### PaychSettle ### PaychSettle
There are not yet any comments for this method.
Perms: sign Perms: sign
@ -3123,7 +3185,7 @@ Response:
``` ```
### PaychStatus ### PaychStatus
There are not yet any comments for this method.
Perms: read Perms: read
@ -3143,7 +3205,7 @@ Response:
``` ```
### PaychVoucherAdd ### PaychVoucherAdd
There are not yet any comments for this method.
Perms: write Perms: write
@ -3179,7 +3241,7 @@ Inputs:
Response: `"0"` Response: `"0"`
### PaychVoucherCheckSpendable ### PaychVoucherCheckSpendable
There are not yet any comments for this method.
Perms: read Perms: read
@ -3215,7 +3277,7 @@ Inputs:
Response: `true` Response: `true`
### PaychVoucherCheckValid ### PaychVoucherCheckValid
There are not yet any comments for this method.
Perms: read Perms: read
@ -3249,7 +3311,7 @@ Inputs:
Response: `{}` Response: `{}`
### PaychVoucherCreate ### PaychVoucherCreate
There are not yet any comments for this method.
Perms: sign Perms: sign
@ -3290,7 +3352,7 @@ Response:
``` ```
### PaychVoucherList ### PaychVoucherList
There are not yet any comments for this method.
Perms: write Perms: write
@ -3304,7 +3366,7 @@ Inputs:
Response: `null` Response: `null`
### PaychVoucherSubmit ### PaychVoucherSubmit
There are not yet any comments for this method.
Perms: sign Perms: sign
@ -3566,6 +3628,36 @@ Response: `"0"`
StateCompute is a flexible command that applies the given messages on the given tipset. StateCompute is a flexible command that applies the given messages on the given tipset.
The messages are run as though the VM were at the provided height. The messages are run as though the VM were at the provided height.
When called, StateCompute will:
- Load the provided tipset, or use the current chain head if not provided
- Compute the tipset state of the provided tipset on top of the parent state
- (note that this step runs before vmheight is applied to the execution)
- Execute state upgrade if any were scheduled at the epoch, or in null
blocks preceding the tipset
- Call the cron actor on null blocks preceding the tipset
- For each block in the tipset
- Apply messages in blocks in the specified
- Award block reward by calling the reward actor
- Call the cron actor for the current epoch
- If the specified vmheight is higher than the current epoch, apply any
needed state upgrades to the state
- Apply the specified messages to the state
The vmheight parameter sets VM execution epoch, and can be used to simulate
message execution in different network versions. If the specified vmheight
epoch is higher than the epoch of the specified tipset, any state upgrades
until the vmheight will be executed on the state before applying messages
specified by the user.
Note that the initial tipset state computation is not affected by the
vmheight parameter - only the messages in the `apply` set are
If the caller wants to simply compute the state, vmheight should be set to
the epoch of the specified tipset.
Messages in the `apply` parameter must have the correct nonces, and gas
values set.
Perms: read Perms: read
@ -3693,7 +3785,7 @@ matching gas-repriced replacing message
NOTE: If the requested message was replaced, this method will return the receipt NOTE: If the requested message was replaced, this method will return the receipt
for the replacing message - if the caller needs the receipt for exactly the for the replacing message - if the caller needs the receipt for exactly the
requested message, use StateSearchMsg().Receipt, and check that MsgLookup.Message requested message, use StateSearchMsg().Receipt, and check that MsgLookup.Message
is matching the requseted CID is matching the requested CID
DEPRECATED: Use StateSearchMsg, this method won't be supported in v1 API DEPRECATED: Use StateSearchMsg, this method won't be supported in v1 API
@ -4459,7 +4551,22 @@ Response:
### StateReplay ### StateReplay
StateReplay replays a given message, assuming it was included in a block in the specified tipset. StateReplay replays a given message, assuming it was included in a block in the specified tipset.
If no tipset key is provided, the appropriate tipset is looked up.
If a tipset key is provided, and a replacing message is found on chain,
the method will return an error saying that the message wasn't found
If no tipset key is provided, the appropriate tipset is looked up, and if
the message was gas-repriced, the on-chain message will be replayed - in
that case the returned InvocResult.MsgCid will not match the Cid param
If the caller wants to ensure that exactly the requested message was executed,
they MUST check that InvocResult.MsgCid is equal to the provided Cid.
Without this check both the requested and original message may appear as
successfully executed on-chain, which may look like a double-spend.
A replacing message is a message with a different CID, any of Gas values, and
different signature, but with all other parameters matching (source/destination,
nonce, params, etc.)
Perms: read Perms: read
@ -5284,7 +5391,7 @@ Response: `"f01234"`
WalletDelete deletes an address from the wallet. WalletDelete deletes an address from the wallet.
Perms: write Perms: admin
Inputs: Inputs:
```json ```json
@ -5380,7 +5487,7 @@ Response: `"f01234"`
WalletSetDefault marks the given address as as the default one. WalletSetDefault marks the given address as as the default one.
Perms: admin Perms: write
Inputs: Inputs:
```json ```json

View File

@ -392,8 +392,10 @@ func (st *Local) Reserve(ctx context.Context, sid storage.SectorRef, ft storifac
} }
p.reserved += overhead p.reserved += overhead
p.reservations[sid.ID] |= fileType
prevDone := done prevDone := done
saveFileType := fileType
done = func() { done = func() {
prevDone() prevDone()
@ -401,6 +403,10 @@ func (st *Local) Reserve(ctx context.Context, sid storage.SectorRef, ft storifac
defer st.localLk.Unlock() defer st.localLk.Unlock()
p.reserved -= overhead p.reserved -= overhead
p.reservations[sid.ID] ^= saveFileType
if p.reservations[sid.ID] == storiface.FTNone {
delete(p.reservations, sid.ID)
}
} }
} }

View File

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"context" "context"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/actors/policy"
proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof"
@ -94,14 +93,9 @@ func checkPrecommit(ctx context.Context, maddr address.Address, si SectorInfo, t
return &ErrBadCommD{xerrors.Errorf("on chain CommD differs from sector: %s != %s", commD, si.CommD)} return &ErrBadCommD{xerrors.Errorf("on chain CommD differs from sector: %s != %s", commD, si.CommD)}
} }
nv, err := api.StateNetworkVersion(ctx, tok) ticketEarliest := height - policy.MaxPreCommitRandomnessLookback
if err != nil {
return &ErrApi{xerrors.Errorf("calling StateNetworkVersion: %w", err)}
}
msd := policy.GetMaxProveCommitDuration(actors.VersionForNetwork(nv), si.SectorType) if si.TicketEpoch < ticketEarliest {
if height-(si.TicketEpoch+policy.SealRandomnessLookback) > msd {
return &ErrExpiredTicket{xerrors.Errorf("ticket expired: seal height: %d, head: %d", si.TicketEpoch+policy.SealRandomnessLookback, height)} return &ErrExpiredTicket{xerrors.Errorf("ticket expired: seal height: %d, head: %d", si.TicketEpoch+policy.SealRandomnessLookback, height)}
} }

View File

@ -12,7 +12,6 @@ import (
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-statemachine" "github.com/filecoin-project/go-statemachine"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-storage/storage" "github.com/filecoin-project/specs-storage/storage"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
@ -22,7 +21,7 @@ import (
) )
var DealSectorPriority = 1024 var DealSectorPriority = 1024
var MaxTicketAge = abi.ChainEpoch(builtin0.EpochsInDay * 2) var MaxTicketAge = policy.MaxPreCommitRandomnessLookback
func (m *Sealing) handlePacking(ctx statemachine.Context, sector SectorInfo) error { func (m *Sealing) handlePacking(ctx statemachine.Context, sector SectorInfo) error {
m.inputLk.Lock() m.inputLk.Lock()

297
gen/api/proxygen.go Normal file
View File

@ -0,0 +1,297 @@
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"io"
"os"
"path/filepath"
"strings"
"text/template"
"unicode"
"golang.org/x/xerrors"
)
type methodMeta struct {
node ast.Node
ftype *ast.FuncType
}
type Visitor struct {
Methods map[string]map[string]*methodMeta
Include map[string][]string
}
func (v *Visitor) Visit(node ast.Node) ast.Visitor {
st, ok := node.(*ast.TypeSpec)
if !ok {
return v
}
iface, ok := st.Type.(*ast.InterfaceType)
if !ok {
return v
}
if v.Methods[st.Name.Name] == nil {
v.Methods[st.Name.Name] = map[string]*methodMeta{}
}
for _, m := range iface.Methods.List {
switch ft := m.Type.(type) {
case *ast.Ident:
v.Include[st.Name.Name] = append(v.Include[st.Name.Name], ft.Name)
case *ast.FuncType:
v.Methods[st.Name.Name][m.Names[0].Name] = &methodMeta{
node: m,
ftype: ft,
}
}
}
return v
}
func main() {
if err := runMain(); err != nil {
fmt.Println("error: ", err)
}
}
func typeName(e ast.Expr) (string, error) {
switch t := e.(type) {
case *ast.SelectorExpr:
return t.X.(*ast.Ident).Name + "." + t.Sel.Name, nil
case *ast.Ident:
pstr := t.Name
if !unicode.IsLower(rune(pstr[0])) {
pstr = "api." + pstr // todo src pkg name
}
return pstr, nil
case *ast.ArrayType:
subt, err := typeName(t.Elt)
if err != nil {
return "", err
}
return "[]" + subt, nil
case *ast.StarExpr:
subt, err := typeName(t.X)
if err != nil {
return "", err
}
return "*" + subt, nil
case *ast.MapType:
k, err := typeName(t.Key)
if err != nil {
return "", err
}
v, err := typeName(t.Value)
if err != nil {
return "", err
}
return "map[" + k + "]" + v, nil
case *ast.StructType:
if len(t.Fields.List) != 0 {
return "", xerrors.Errorf("can't struct")
}
return "struct{}", nil
case *ast.InterfaceType:
if len(t.Methods.List) != 0 {
return "", xerrors.Errorf("can't interface")
}
return "interface{}", nil
case *ast.ChanType:
subt, err := typeName(t.Value)
if err != nil {
return "", err
}
if t.Dir == ast.SEND {
subt = "->chan " + subt
} else {
subt = "<-chan " + subt
}
return subt, nil
default:
return "", xerrors.Errorf("unknown type")
}
}
func runMain() error {
fset := token.NewFileSet()
apiDir, err := filepath.Abs("./api")
if err != nil {
return err
}
pkgs, err := parser.ParseDir(fset, apiDir, nil, parser.AllErrors|parser.ParseComments)
if err != nil {
return err
}
ap := pkgs["api"]
v := &Visitor{make(map[string]map[string]*methodMeta), map[string][]string{}}
ast.Walk(v, ap)
type methodInfo struct {
Name string
node ast.Node
Tags map[string][]string
NamedParams, ParamNames, Results string
}
type strinfo struct {
Name string
Methods map[string]*methodInfo
Include []string
}
type meta struct {
Infos map[string]*strinfo
Imports map[string]string
}
m := &meta{
Infos: map[string]*strinfo{},
Imports: map[string]string{},
}
for fn, f := range ap.Files {
if strings.HasSuffix(fn, "gen.go") {
continue
}
//fmt.Println("F:", fn)
cmap := ast.NewCommentMap(fset, f, f.Comments)
for _, im := range f.Imports {
m.Imports[im.Path.Value] = im.Path.Value
}
for ifname, methods := range v.Methods {
if _, ok := m.Infos[ifname]; !ok {
m.Infos[ifname] = &strinfo{
Name: ifname,
Methods: map[string]*methodInfo{},
Include: v.Include[ifname],
}
}
info := m.Infos[ifname]
for mname, node := range methods {
filteredComments := cmap.Filter(node.node).Comments()
if _, ok := info.Methods[mname]; !ok {
var params, pnames []string
for _, param := range node.ftype.Params.List {
pstr, err := typeName(param.Type)
if err != nil {
return err
}
c := len(param.Names)
if c == 0 {
c = 1
}
for i := 0; i < c; i++ {
pname := fmt.Sprintf("p%d", len(params))
pnames = append(pnames, pname)
params = append(params, pname+" "+pstr)
}
}
var results []string
for _, result := range node.ftype.Results.List {
rs, err := typeName(result.Type)
if err != nil {
return err
}
results = append(results, rs)
}
info.Methods[mname] = &methodInfo{
Name: mname,
node: node.node,
Tags: map[string][]string{},
NamedParams: strings.Join(params, ", "),
ParamNames: strings.Join(pnames, ", "),
Results: strings.Join(results, ", "),
}
}
// try to parse tag info
if len(filteredComments) > 0 {
tagstr := filteredComments[len(filteredComments)-1].List[0].Text
tagstr = strings.TrimPrefix(tagstr, "//")
tl := strings.Split(strings.TrimSpace(tagstr), " ")
for _, ts := range tl {
tf := strings.Split(ts, ":")
if len(tf) != 2 {
continue
}
if tf[0] != "perm" { // todo: allow more tag types
continue
}
info.Methods[mname].Tags[tf[0]] = tf
}
}
}
}
}
/*jb, err := json.MarshalIndent(Infos, "", " ")
if err != nil {
return err
}
fmt.Println(string(jb))*/
w := os.Stdout
err = doTemplate(w, m, `// Code generated by github.com/filecoin-project/lotus/gen/api. DO NOT EDIT.
package apistruct
import (
{{range .Imports}}{{.}}
{{end}}
)
`)
if err != nil {
return err
}
err = doTemplate(w, m, `
{{range .Infos}}
type {{.Name}}Struct struct {
{{range .Include}}
{{.}}Struct
{{end}}
Internal struct {
{{range .Methods}}
{{.Name}} func({{.NamedParams}}) ({{.Results}}) `+"`"+`{{range .Tags}}{{index . 0}}:"{{index . 1}}"{{end}}`+"`"+`
{{end}}
}
}
{{end}}
{{range .Infos}}
{{$name := .Name}}
{{range .Methods}}
func (s *{{$name}}Struct) {{.Name}}({{.NamedParams}}) ({{.Results}}) {
return s.Internal.{{.Name}}({{.ParamNames}})
}
{{end}}
{{end}}
{{range .Infos}}var _ api.{{.Name}} = new({{.Name}}Struct)
{{end}}
`)
return err
}
func doTemplate(w io.Writer, info interface{}, templ string) error {
t := template.Must(template.New("").
Funcs(template.FuncMap{}).Parse(templ))
return t.Execute(w, info)
}

15
go.mod
View File

@ -10,6 +10,7 @@ require (
github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921
github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
github.com/cockroachdb/pebble v0.0.0-20201001221639-879f3bfeef07 github.com/cockroachdb/pebble v0.0.0-20201001221639-879f3bfeef07
@ -22,24 +23,25 @@ require (
github.com/dustin/go-humanize v1.0.0 github.com/dustin/go-humanize v1.0.0
github.com/elastic/go-sysinfo v1.3.0 github.com/elastic/go-sysinfo v1.3.0
github.com/elastic/gosigar v0.12.0 github.com/elastic/gosigar v0.12.0
github.com/etclabscore/go-openrpc-reflect v0.0.36
github.com/fatih/color v1.9.0 github.com/fatih/color v1.9.0
github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f
github.com/filecoin-project/go-address v0.0.5 github.com/filecoin-project/go-address v0.0.5
github.com/filecoin-project/go-amt-ipld/v2 v2.1.1-0.20201006184820-924ee87a1349 // indirect github.com/filecoin-project/go-amt-ipld/v2 v2.1.1-0.20201006184820-924ee87a1349 // indirect
github.com/filecoin-project/go-bitfield v0.2.4 github.com/filecoin-project/go-bitfield v0.2.4
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2
github.com/filecoin-project/go-commp-utils v0.0.0-20201119054358-b88f7a96a434 github.com/filecoin-project/go-commp-utils v0.1.0
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
github.com/filecoin-project/go-data-transfer v1.2.7 github.com/filecoin-project/go-data-transfer v1.4.1
github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a
github.com/filecoin-project/go-fil-markets v1.1.9 github.com/filecoin-project/go-fil-markets v1.2.4
github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec
github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-multistore v0.0.3
github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261 github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261
github.com/filecoin-project/go-state-types v0.1.0 github.com/filecoin-project/go-state-types v0.1.0
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe
github.com/filecoin-project/go-statestore v0.1.1-0.20210311122610-6c7a5aedbdea github.com/filecoin-project/go-statestore v0.1.1
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b
github.com/filecoin-project/specs-actors v0.9.13 github.com/filecoin-project/specs-actors v0.9.13
github.com/filecoin-project/specs-actors/v2 v2.3.4 github.com/filecoin-project/specs-actors/v2 v2.3.4
@ -122,11 +124,13 @@ require (
github.com/multiformats/go-multibase v0.0.3 github.com/multiformats/go-multibase v0.0.3
github.com/multiformats/go-multihash v0.0.14 github.com/multiformats/go-multihash v0.0.14
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/open-rpc/meta-schema v0.0.0-20201029221707-1b72ef2ea333
github.com/opentracing/opentracing-go v1.2.0 github.com/opentracing/opentracing-go v1.2.0
github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a
github.com/prometheus/client_golang v1.6.0 github.com/prometheus/client_golang v1.6.0
github.com/raulk/clock v1.1.0 github.com/raulk/clock v1.1.0
github.com/raulk/go-watchdog v1.0.1 github.com/raulk/go-watchdog v1.0.1
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
github.com/syndtr/goleveldb v1.0.0 github.com/syndtr/goleveldb v1.0.0
github.com/urfave/cli/v2 v2.2.0 github.com/urfave/cli/v2 v2.2.0
@ -142,7 +146,7 @@ require (
go.uber.org/fx v1.9.0 go.uber.org/fx v1.9.0
go.uber.org/multierr v1.6.0 go.uber.org/multierr v1.6.0
go.uber.org/zap v1.16.0 go.uber.org/zap v1.16.0
golang.org/x/net v0.0.0-20201021035429-f5854403a974 golang.org/x/net v0.0.0-20201022231255-08b38378de70
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 golang.org/x/time v0.0.0-20191024005414-555d28b269f0
@ -150,6 +154,7 @@ require (
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/cheggaaa/pb.v1 v1.0.28 gopkg.in/cheggaaa/pb.v1 v1.0.28
gotest.tools v2.2.0+incompatible gotest.tools v2.2.0+incompatible
honnef.co/go/tools v0.0.1-2020.1.3 // indirect
) )
replace github.com/filecoin-project/lotus => ./ replace github.com/filecoin-project/lotus => ./

81
go.sum
View File

@ -42,8 +42,15 @@ github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee h1:8doiS7ib3zi6/K1
github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee/go.mod h1:W0GbEAA4uFNYOGG2cJpmFJ04E6SD1NLELPYZB57/7AY= github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee/go.mod h1:W0GbEAA4uFNYOGG2cJpmFJ04E6SD1NLELPYZB57/7AY=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
github.com/Masterminds/glide v0.13.2/go.mod h1:STyF5vcenH/rUqTEv+/hBXlSTo7KYwg2oc2f4tzPWic=
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/vcs v1.13.0/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
@ -58,6 +65,8 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBA
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw=
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921 h1:T3+cD5fYvuH36h7EZq+TDpm+d8a6FSD4pQsbmuGGQ8o=
github.com/alecthomas/jsonschema v0.0.0-20200530073317-71f438968921/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@ -140,6 +149,7 @@ github.com/cockroachdb/redact v0.0.0-20200622112456-cd282804bbd3 h1:2+dpIJzYMSbL
github.com/cockroachdb/redact v0.0.0-20200622112456-cd282804bbd3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/redact v0.0.0-20200622112456-cd282804bbd3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/codegangsta/cli v1.20.0/go.mod h1:/qJNoX69yVSKu5o4jLyXAENLRyk1uhi7zkbQ3slBdOA=
github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 h1:7grrpcfCtbZLsjtB0DgMuzs1umsJmpzaHMZ6cO6iAWw= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327 h1:7grrpcfCtbZLsjtB0DgMuzs1umsJmpzaHMZ6cO6iAWw=
github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@ -155,6 +165,7 @@ github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7
github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg= github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg=
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/corpix/uarand v0.1.1/go.mod h1:SFKZvkcRoLqVRFZ4u25xPmp6m9ktANfbpXZ7SJ0/FNU=
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@ -223,6 +234,10 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/etclabscore/go-jsonschema-walk v0.0.6 h1:DrNzoKWKd8f8XB5nFGBY00IcjakRE22OTI12k+2LkyY=
github.com/etclabscore/go-jsonschema-walk v0.0.6/go.mod h1:VdfDY72AFAiUhy0ZXEaWSpveGjMT5JcDIm903NGqFwQ=
github.com/etclabscore/go-openrpc-reflect v0.0.36 h1:kSqNB2U8RVoW4si+4fsv13NGNkRAQ5j78zTUx1qiehk=
github.com/etclabscore/go-openrpc-reflect v0.0.36/go.mod h1:0404Ky3igAasAOpyj1eESjstTyneBAIk5PgJFbK4s5E=
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A=
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
@ -240,26 +255,26 @@ github.com/filecoin-project/go-amt-ipld/v3 v3.0.0 h1:Ou/q82QeHGOhpkedvaxxzpBYuqT
github.com/filecoin-project/go-amt-ipld/v3 v3.0.0/go.mod h1:Qa95YNAbtoVCTSVtX38aAC1ptBnJfPma1R/zZsKmx4o= github.com/filecoin-project/go-amt-ipld/v3 v3.0.0/go.mod h1:Qa95YNAbtoVCTSVtX38aAC1ptBnJfPma1R/zZsKmx4o=
github.com/filecoin-project/go-bitfield v0.2.0/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM= github.com/filecoin-project/go-bitfield v0.2.0/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM=
github.com/filecoin-project/go-bitfield v0.2.3/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM= github.com/filecoin-project/go-bitfield v0.2.3/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM=
github.com/filecoin-project/go-bitfield v0.2.3/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM=
github.com/filecoin-project/go-bitfield v0.2.4 h1:uZ7MeE+XfM5lqrHJZ93OnhQKc/rveW8p9au0C68JPgk= github.com/filecoin-project/go-bitfield v0.2.4 h1:uZ7MeE+XfM5lqrHJZ93OnhQKc/rveW8p9au0C68JPgk=
github.com/filecoin-project/go-bitfield v0.2.4/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM= github.com/filecoin-project/go-bitfield v0.2.4/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM=
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:av5fw6wmm58FYMgJeoB/lK9XXrgdugYiTqkdxjTy9k8= github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:av5fw6wmm58FYMgJeoB/lK9XXrgdugYiTqkdxjTy9k8=
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg= github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg=
github.com/filecoin-project/go-commp-utils v0.0.0-20201119054358-b88f7a96a434 h1:0kHszkYP3hgApcjl5x4rpwONhN9+j7XDobf6at5XfHs=
github.com/filecoin-project/go-commp-utils v0.0.0-20201119054358-b88f7a96a434/go.mod h1:6s95K91mCyHY51RPWECZieD3SGWTqIFLf1mPOes9l5U= github.com/filecoin-project/go-commp-utils v0.0.0-20201119054358-b88f7a96a434/go.mod h1:6s95K91mCyHY51RPWECZieD3SGWTqIFLf1mPOes9l5U=
github.com/filecoin-project/go-commp-utils v0.1.0 h1:PaDxoXYh1TXnnz5kA/xSObpAQwcJSUs4Szb72nuaNdk=
github.com/filecoin-project/go-commp-utils v0.1.0/go.mod h1:6s95K91mCyHY51RPWECZieD3SGWTqIFLf1mPOes9l5U=
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus=
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ=
github.com/filecoin-project/go-data-transfer v1.0.1/go.mod h1:UxvfUAY9v3ub0a21BSK9u3pB2aq30Y0KMsG+w9/ysyo= github.com/filecoin-project/go-data-transfer v1.0.1/go.mod h1:UxvfUAY9v3ub0a21BSK9u3pB2aq30Y0KMsG+w9/ysyo=
github.com/filecoin-project/go-data-transfer v1.2.7 h1:WE5Cpp9eMt5BDoWOVR64QegSn6bwHQaDzyyjVU377Y0= github.com/filecoin-project/go-data-transfer v1.4.1 h1:4GoMGEdMeDLqbKR74Q5ceZTN35nv+66JZERqQ+SjxWU=
github.com/filecoin-project/go-data-transfer v1.2.7/go.mod h1:mvjZ+C3NkBX10JP4JMu27DCjUouHFjHwUGh+Xc4yvDA= github.com/filecoin-project/go-data-transfer v1.4.1/go.mod h1:n8kbDQXWrY1c4UgfMa9KERxNCWbOTDwdNhf2MpN9dpo=
github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ=
github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s=
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ=
github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a h1:hyJ+pUm/4U4RdEZBlg6k8Ma4rDiuvqyGpoICXAxwsTg= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a h1:hyJ+pUm/4U4RdEZBlg6k8Ma4rDiuvqyGpoICXAxwsTg=
github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ=
github.com/filecoin-project/go-fil-markets v1.0.5-0.20201113164554-c5eba40d5335/go.mod h1:AJySOJC00JRWEZzRG2KsfUnqEf5ITXxeX09BE9N4f9c= github.com/filecoin-project/go-fil-markets v1.0.5-0.20201113164554-c5eba40d5335/go.mod h1:AJySOJC00JRWEZzRG2KsfUnqEf5ITXxeX09BE9N4f9c=
github.com/filecoin-project/go-fil-markets v1.1.9 h1:sA0NIEOpy7brZaeXeNgdXg5pvHaBtD5OTRlraOUbI0w= github.com/filecoin-project/go-fil-markets v1.2.4 h1:AcNMy/XGvSdv4GjuVoeqe67Q7OvppkSx1zWEGqVHixg=
github.com/filecoin-project/go-fil-markets v1.1.9/go.mod h1:0yQu5gvrjFoAIyzPSSJ+xUdCG83vjInAFbTswIB5/hk= github.com/filecoin-project/go-fil-markets v1.2.4/go.mod h1:8WEpiMkwdvtHb5dXmRIWX4vz4XjkVlhxRdHJdouV1b0=
github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM=
github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24=
github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM=
@ -283,8 +298,8 @@ github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psS
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw=
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI=
github.com/filecoin-project/go-statestore v0.1.1-0.20210311122610-6c7a5aedbdea h1:EvmiCrHRrPF2mxVMIRdtsxZGByqwT24aJLw7mdzEFxE= github.com/filecoin-project/go-statestore v0.1.1 h1:ufMFq00VqnT2CAuDpcGnwLnCX1I/c3OROw/kXVNSTZk=
github.com/filecoin-project/go-statestore v0.1.1-0.20210311122610-6c7a5aedbdea/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= github.com/filecoin-project/go-statestore v0.1.1/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI=
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b h1:fkRZSPrYpk42PV3/lIXiL0LHetxde7vyYYvSsttQtfg= github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b h1:fkRZSPrYpk42PV3/lIXiL0LHetxde7vyYYvSsttQtfg=
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/go.mod h1:Q0GQOBtKf1oE10eSXSlhN45kDBdGvEcVOqMiffqX+N8= github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/go.mod h1:Q0GQOBtKf1oE10eSXSlhN45kDBdGvEcVOqMiffqX+N8=
github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07U6cPKol6fd3w9KjMPZ6Z4= github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07U6cPKol6fd3w9KjMPZ6Z4=
@ -333,6 +348,21 @@ github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg=
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/spec v0.19.7/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
github.com/go-openapi/spec v0.19.11 h1:ogU5q8dtp3MMPn59a9VRrPKVxvJHEs5P7yNMR5sNnis=
github.com/go-openapi/spec v0.19.11/go.mod h1:vqK/dIdLGCosfvYsQV3WfC7N3TiZSnGY2RZKoFK7X28=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.8/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
github.com/go-openapi/swag v0.19.11 h1:RFTu/dlFySpyVvJDfp/7674JY4SDglYWKztbiIGFpmc=
github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
@ -366,6 +396,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -484,7 +515,11 @@ github.com/huin/goupnp v0.0.0-20180415215157-1395d1447324/go.mod h1:MZ2ZmwcBpvOo
github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
github.com/iancoleman/orderedmap v0.1.0 h1:2orAxZBJsvimgEBmMWfXaFlzSG2fbQil5qzP3F6cCkg=
github.com/iancoleman/orderedmap v0.1.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428/go.mod h1:uhpZMVGznybq1itEKXj6RYw9I71qK4kH+OGMjRC4KEo=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
@ -560,7 +595,6 @@ github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28
github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE=
github.com/ipfs/go-graphsync v0.4.2/go.mod h1:/VmbZTUdUMTbNkgzAiCEucIIAU3BkLE2cZrDCVUhyi0= github.com/ipfs/go-graphsync v0.4.2/go.mod h1:/VmbZTUdUMTbNkgzAiCEucIIAU3BkLE2cZrDCVUhyi0=
github.com/ipfs/go-graphsync v0.4.3/go.mod h1:mPOwDYv128gf8gxPFgXnz4fNrSYPsWyqisJ7ych+XDY= github.com/ipfs/go-graphsync v0.4.3/go.mod h1:mPOwDYv128gf8gxPFgXnz4fNrSYPsWyqisJ7ych+XDY=
github.com/ipfs/go-graphsync v0.5.2/go.mod h1:e2ZxnClqBBYAtd901g9vXMJzS47labjAtOzsWtOzKNk=
github.com/ipfs/go-graphsync v0.6.0 h1:x6UvDUGA7wjaKNqx5Vbo7FGT8aJ5ryYA0dMQ5jN3dF0= github.com/ipfs/go-graphsync v0.6.0 h1:x6UvDUGA7wjaKNqx5Vbo7FGT8aJ5ryYA0dMQ5jN3dF0=
github.com/ipfs/go-graphsync v0.6.0/go.mod h1:e2ZxnClqBBYAtd901g9vXMJzS47labjAtOzsWtOzKNk= github.com/ipfs/go-graphsync v0.6.0/go.mod h1:e2ZxnClqBBYAtd901g9vXMJzS47labjAtOzsWtOzKNk=
github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk= github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk=
@ -710,6 +744,8 @@ github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jonboulle/clockwork v0.1.1-0.20190114141812-62fb9bc030d1 h1:qBCV/RLV02TSfQa7tFmxTihnG+u+7JXByOkhlkR5rmQ= github.com/jonboulle/clockwork v0.1.1-0.20190114141812-62fb9bc030d1 h1:qBCV/RLV02TSfQa7tFmxTihnG+u+7JXByOkhlkR5rmQ=
github.com/jonboulle/clockwork v0.1.1-0.20190114141812-62fb9bc030d1/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.1.1-0.20190114141812-62fb9bc030d1/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
@ -1078,6 +1114,11 @@ github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0Q
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI=
github.com/marten-seemann/qpack v0.2.0/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= github.com/marten-seemann/qpack v0.2.0/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk=
@ -1212,6 +1253,7 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/ngdinhtoan/glide-cleanup v0.2.0/go.mod h1:UQzsmiDOb8YV3nOsCxK/c9zPpCZVNoHScRE3EO9pVMM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nikkolasg/hexjson v0.0.0-20181101101858-78e39397e00c h1:5bFTChQxSKNwy8ALwOebjekYExl9HTT9urdawqC95tA= github.com/nikkolasg/hexjson v0.0.0-20181101101858-78e39397e00c h1:5bFTChQxSKNwy8ALwOebjekYExl9HTT9urdawqC95tA=
@ -1239,6 +1281,8 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/open-rpc/meta-schema v0.0.0-20201029221707-1b72ef2ea333 h1:CznVS40zms0Dj5he4ERo+fRPtO0qxUk8lA8Xu3ddet0=
github.com/open-rpc/meta-schema v0.0.0-20201029221707-1b72ef2ea333/go.mod h1:Ag6rSXkHIckQmjFBCweJEEt1mrTPBv8b9W4aU/NQWfI=
github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opentracing-contrib/go-grpc v0.0.0-20180928155321-4b5a12d3ff02/go.mod h1:JNdpVEzCpXBgIiv4ds+TzhN1hrtxq6ClLrTlT9OQRSc= github.com/opentracing-contrib/go-grpc v0.0.0-20180928155321-4b5a12d3ff02/go.mod h1:JNdpVEzCpXBgIiv4ds+TzhN1hrtxq6ClLrTlT9OQRSc=
@ -1406,10 +1450,12 @@ github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@ -1420,6 +1466,12 @@ github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFd
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g=
github.com/tidwall/gjson v1.6.0 h1:9VEQWz6LLMUsUl6PueE49ir4Ka6CzLymOAZDxpFsTDc=
github.com/tidwall/gjson v1.6.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tj/go-spin v1.1.0 h1:lhdWZsvImxvZ3q1C5OIB7d72DuOwP4O2NdBg9PyzNds= github.com/tj/go-spin v1.1.0 h1:lhdWZsvImxvZ3q1C5OIB7d72DuOwP4O2NdBg9PyzNds=
github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@ -1664,13 +1716,15 @@ golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200519113804-d87ec0cfa476/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200519113804-d87ec0cfa476/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201022231255-08b38378de70 h1:Z6x4N9mAi4oF0TbHweCsH618MO6OI6UFgV0FP5n0wBY=
golang.org/x/net v0.0.0-20201022231255-08b38378de70/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1798,6 +1852,7 @@ golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
@ -1928,15 +1983,15 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M= howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M=
howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
modernc.org/cc v1.0.0 h1:nPibNuDEx6tvYrUAtvDTTw98rx5juGsa5zuDnKwEEQQ= modernc.org/cc v1.0.0 h1:nPibNuDEx6tvYrUAtvDTTw98rx5juGsa5zuDnKwEEQQ=
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8=
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/golex v1.0.1 h1:EYKY1a3wStt0RzHaH8mdSRNg78Ub0OHxYfCRWw35YtM= modernc.org/golex v1.0.1 h1:EYKY1a3wStt0RzHaH8mdSRNg78Ub0OHxYfCRWw35YtM=
modernc.org/golex v1.0.1/go.mod h1:QCA53QtsT1NdGkaZZkF5ezFwk4IXh4BGNafAARTC254= modernc.org/golex v1.0.1/go.mod h1:QCA53QtsT1NdGkaZZkF5ezFwk4IXh4BGNafAARTC254=
modernc.org/lex v1.0.0/go.mod h1:G6rxMTy3cH2iA0iXL/HRRv4Znu8MK4higxph/lE7ypk= modernc.org/lex v1.0.0/go.mod h1:G6rxMTy3cH2iA0iXL/HRRv4Znu8MK4higxph/lE7ypk=

View File

@ -55,7 +55,7 @@ func (d *Datastore) startLog(logdir string) error {
return xerrors.Errorf("creating log: %w", err) return xerrors.Errorf("creating log: %w", err)
} }
} else { } else {
l, err = d.openLog(filepath.Join(logdir, latest)) l, latest, err = d.openLog(filepath.Join(logdir, latest))
if err != nil { if err != nil {
return xerrors.Errorf("opening log: %w", err) return xerrors.Errorf("opening log: %w", err)
} }
@ -97,6 +97,8 @@ type logfile struct {
file *os.File file *os.File
} }
var compactThresh = 2
func (d *Datastore) createLog(logdir string) (*logfile, string, error) { func (d *Datastore) createLog(logdir string) (*logfile, string, error) {
p := filepath.Join(logdir, strconv.FormatInt(time.Now().Unix(), 10)+".log.cbor") p := filepath.Join(logdir, strconv.FormatInt(time.Now().Unix(), 10)+".log.cbor")
log.Infow("creating log", "file", p) log.Infow("creating log", "file", p)
@ -119,32 +121,36 @@ func (d *Datastore) createLog(logdir string) (*logfile, string, error) {
}, filepath.Base(p), nil }, filepath.Base(p), nil
} }
func (d *Datastore) openLog(p string) (*logfile, error) { func (d *Datastore) openLog(p string) (*logfile, string, error) {
log.Infow("opening log", "file", p) log.Infow("opening log", "file", p)
lh, err := d.child.Get(loghead) lh, err := d.child.Get(loghead)
if err != nil { if err != nil {
return nil, xerrors.Errorf("checking log head (logfile '%s'): %w", p, err) return nil, "", xerrors.Errorf("checking log head (logfile '%s'): %w", p, err)
} }
lhp := strings.Split(string(lh), ";") lhp := strings.Split(string(lh), ";")
if len(lhp) != 3 { if len(lhp) != 3 {
return nil, xerrors.Errorf("expected loghead to have 3 parts") return nil, "", xerrors.Errorf("expected loghead to have 3 parts")
} }
if lhp[0] != filepath.Base(p) { if lhp[0] != filepath.Base(p) {
return nil, xerrors.Errorf("loghead log file doesn't match, opening %s, expected %s", p, lhp[0]) return nil, "", xerrors.Errorf("loghead log file doesn't match, opening %s, expected %s", p, lhp[0])
} }
f, err := os.OpenFile(p, os.O_RDWR, 0644) f, err := os.OpenFile(p, os.O_RDWR, 0644)
if err != nil { if err != nil {
return nil, err return nil, "", err
} }
var lastLogHead string var lastLogHead string
var openCount, logvals int64 var openCount, vals, logvals int64
// check file integrity // check file integrity
err = ReadBackup(f, func(k datastore.Key, v []byte) error { err = ReadBackup(f, func(k datastore.Key, v []byte, log bool) error {
logvals++ if log {
logvals++
} else {
vals++
}
if k == loghead { if k == loghead {
lastLogHead = string(v) lastLogHead = string(v)
openCount++ openCount++
@ -152,32 +158,53 @@ func (d *Datastore) openLog(p string) (*logfile, error) {
return nil return nil
}) })
if err != nil { if err != nil {
return nil, xerrors.Errorf("reading backup part of the logfile: %w", err) return nil, "", xerrors.Errorf("reading backup part of the logfile: %w", err)
} }
if string(lh) != lastLogHead { if string(lh) != lastLogHead {
return nil, xerrors.Errorf("loghead didn't match, expected '%s', last in logfile '%s'", string(lh), lastLogHead) return nil, "", xerrors.Errorf("loghead didn't match, expected '%s', last in logfile '%s'", string(lh), lastLogHead)
} }
// make sure we're at the end of the file // make sure we're at the end of the file
at, err := f.Seek(0, io.SeekCurrent) at, err := f.Seek(0, io.SeekCurrent)
if err != nil { if err != nil {
return nil, xerrors.Errorf("get current logfile offset: %w", err) return nil, "", xerrors.Errorf("get current logfile offset: %w", err)
} }
end, err := f.Seek(0, io.SeekEnd) end, err := f.Seek(0, io.SeekEnd)
if err != nil { if err != nil {
return nil, xerrors.Errorf("get current logfile offset: %w", err) return nil, "", xerrors.Errorf("get current logfile offset: %w", err)
} }
if at != end { if at != end {
return nil, xerrors.Errorf("logfile %s validated %d bytes, but the file has %d bytes (%d more)", p, at, end, end-at) return nil, "", xerrors.Errorf("logfile %s validated %d bytes, but the file has %d bytes (%d more)", p, at, end, end-at)
} }
log.Infow("log opened", "file", p, "openCount", openCount, "logValues", logvals) compact := logvals > vals*int64(compactThresh)
if compact {
log.Infow("compacting log", "current", p, "openCount", openCount, "baseValues", vals, "logValues", logvals)
if err := f.Close(); err != nil {
return nil, "", xerrors.Errorf("closing current log: %w", err)
}
l, latest, err := d.createLog(filepath.Dir(p))
if err != nil {
return nil, "", xerrors.Errorf("creating compacted log: %w", err)
}
log.Infow("compacted log created, cleaning up old", "old", p, "new", latest)
if err := os.Remove(p); err != nil {
l.Close() // nolint
return nil, "", xerrors.Errorf("cleaning up old logfile: %w", err)
}
return l, latest, nil
}
log.Infow("log opened", "file", p, "openCount", openCount, "baseValues", vals, "logValues", logvals)
// todo: maybe write a magic 'opened at' entry; pad the log to filesystem page to prevent more exotic types of corruption // todo: maybe write a magic 'opened at' entry; pad the log to filesystem page to prevent more exotic types of corruption
return &logfile{ return &logfile{
file: f, file: f,
}, nil }, filepath.Base(p), nil
} }
func (l *logfile) writeLogHead(logname string, ds datastore.Batching) error { func (l *logfile) writeLogHead(logname string, ds datastore.Batching) error {

View File

@ -11,7 +11,7 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
) )
func ReadBackup(r io.Reader, cb func(key datastore.Key, value []byte) error) error { func ReadBackup(r io.Reader, cb func(key datastore.Key, value []byte, log bool) error) error {
scratch := make([]byte, 9) scratch := make([]byte, 9)
// read array[2]( // read array[2](
@ -61,7 +61,7 @@ func ReadBackup(r io.Reader, cb func(key datastore.Key, value []byte) error) err
return xerrors.Errorf("reading value: %w", err) return xerrors.Errorf("reading value: %w", err)
} }
if err := cb(key, value); err != nil { if err := cb(key, value, false); err != nil {
return err return err
} }
} }
@ -110,7 +110,7 @@ func ReadBackup(r io.Reader, cb func(key datastore.Key, value []byte) error) err
key := datastore.NewKey(string(ent.Key)) key := datastore.NewKey(string(ent.Key))
if err := cb(key, ent.Value); err != nil { if err := cb(key, ent.Value, true); err != nil {
return err return err
} }
} }
@ -122,7 +122,7 @@ func RestoreInto(r io.Reader, dest datastore.Batching) error {
return xerrors.Errorf("creating batch: %w", err) return xerrors.Errorf("creating batch: %w", err)
} }
err = ReadBackup(r, func(key datastore.Key, value []byte) error { err = ReadBackup(r, func(key datastore.Key, value []byte, _ bool) error {
if err := batch.Put(key, value); err != nil { if err := batch.Put(key, value); err != nil {
return xerrors.Errorf("put key: %w", err) return xerrors.Errorf("put key: %w", err)
} }

View File

@ -4,6 +4,9 @@ import (
"context" "context"
"io" "io"
"github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log/v2"
"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"
@ -16,10 +19,10 @@ import (
"github.com/filecoin-project/go-fil-markets/shared" "github.com/filecoin-project/go-fil-markets/shared"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
specstorage "github.com/filecoin-project/specs-storage/storage" specstorage "github.com/filecoin-project/specs-storage/storage"
"github.com/ipfs/go-cid"
) )
var log = logging.Logger("retrievaladapter")
type retrievalProviderNode struct { type retrievalProviderNode struct {
miner *storage.Miner miner *storage.Miner
sealer sectorstorage.SectorManager sealer sectorstorage.SectorManager
@ -61,13 +64,20 @@ func (rpn *retrievalProviderNode) UnsealSector(ctx context.Context, sectorID abi
ProofType: si.SectorType, ProofType: si.SectorType,
} }
// Set up a pipe so that data can be written from the unsealing process
// into the reader returned by this function
r, w := io.Pipe() r, w := io.Pipe()
go func() { go func() {
var commD cid.Cid var commD cid.Cid
if si.CommD != nil { if si.CommD != nil {
commD = *si.CommD commD = *si.CommD
} }
// Read the piece into the pipe's writer, unsealing the piece if necessary
err := rpn.sealer.ReadPiece(ctx, w, ref, storiface.UnpaddedByteIndex(offset), length, si.TicketValue, commD) err := rpn.sealer.ReadPiece(ctx, w, ref, storiface.UnpaddedByteIndex(offset), length, si.TicketValue, commD)
if err != nil {
log.Errorf("failed to unseal piece from sector %d: %s", sectorID, err)
}
// Close the reader with any error that was returned while reading the piece
_ = w.CloseWithError(err) _ = w.CloseWithError(err)
}() }()

View File

@ -24,19 +24,19 @@ func MetricedFullAPI(a api.FullNode) api.FullNode {
return &out return &out
} }
func MetricedWorkerAPI(a api.WorkerAPI) api.WorkerAPI { func MetricedWorkerAPI(a api.Worker) api.Worker {
var out apistruct.WorkerStruct var out apistruct.WorkerStruct
proxy(a, &out.Internal) proxy(a, &out.Internal)
return &out return &out
} }
func MetricedWalletAPI(a api.WalletAPI) api.WalletAPI { func MetricedWalletAPI(a api.Wallet) api.Wallet {
var out apistruct.WalletStruct var out apistruct.WalletStruct
proxy(a, &out.Internal) proxy(a, &out.Internal)
return &out return &out
} }
func MetricedGatewayAPI(a api.GatewayAPI) api.GatewayAPI { func MetricedGatewayAPI(a api.Gateway) api.Gateway {
var out apistruct.GatewayStruct var out apistruct.GatewayStruct
proxy(a, &out.Internal) proxy(a, &out.Internal)
return &out return &out

View File

@ -37,7 +37,13 @@ const (
evtTypeBlockMined = iota evtTypeBlockMined = iota
) )
// returns a callback reporting whether we mined a blocks in this round // waitFunc is expected to pace block mining at the configured network rate.
//
// baseTime is the timestamp of the mining base, i.e. the timestamp
// of the tipset we're planning to construct upon.
//
// Upon each mining loop iteration, the returned callback is called reporting
// whether we mined a block in this round or not.
type waitFunc func(ctx context.Context, baseTime uint64) (func(bool, abi.ChainEpoch, error), abi.ChainEpoch, error) type waitFunc func(ctx context.Context, baseTime uint64) (func(bool, abi.ChainEpoch, error), abi.ChainEpoch, error)
func randTimeOffset(width time.Duration) time.Duration { func randTimeOffset(width time.Duration) time.Duration {
@ -48,6 +54,8 @@ func randTimeOffset(width time.Duration) time.Duration {
return val - (width / 2) return val - (width / 2)
} }
// NewMiner instantiates a miner with a concrete WinningPoStProver and a miner
// address (which can be different from the worker's address).
func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf *slashfilter.SlashFilter, j journal.Journal) *Miner { func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf *slashfilter.SlashFilter, j journal.Journal) *Miner {
arc, err := lru.NewARC(10000) arc, err := lru.NewARC(10000)
if err != nil { if err != nil {
@ -59,7 +67,16 @@ func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address,
epp: epp, epp: epp,
address: addr, address: addr,
waitFunc: func(ctx context.Context, baseTime uint64) (func(bool, abi.ChainEpoch, error), abi.ChainEpoch, error) { waitFunc: func(ctx context.Context, baseTime uint64) (func(bool, abi.ChainEpoch, error), abi.ChainEpoch, error) {
// Wait around for half the block time in case other parents come in // wait around for half the block time in case other parents come in
//
// if we're mining a block in the past via catch-up/rush mining,
// such as when recovering from a network halt, this sleep will be
// for a negative duration, and therefore **will return
// immediately**.
//
// the result is that we WILL NOT wait, therefore fast-forwarding
// and thus healing the chain by backfilling it with null rounds
// rapidly.
deadline := baseTime + build.PropagationDelaySecs deadline := baseTime + build.PropagationDelaySecs
baseT := time.Unix(int64(deadline), 0) baseT := time.Unix(int64(deadline), 0)
@ -79,6 +96,9 @@ func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address,
} }
} }
// Miner encapsulates the mining processes of the system.
//
// Refer to the godocs on mineOne and mine methods for more detail.
type Miner struct { type Miner struct {
api api.FullNode api api.FullNode
@ -91,15 +111,20 @@ type Miner struct {
waitFunc waitFunc waitFunc waitFunc
// lastWork holds the last MiningBase we built upon.
lastWork *MiningBase lastWork *MiningBase
sf *slashfilter.SlashFilter sf *slashfilter.SlashFilter
// minedBlockHeights is a safeguard that caches the last heights we mined.
// It is consulted before publishing a newly mined block, for a sanity check
// intended to avoid slashings in case of a bug.
minedBlockHeights *lru.ARCCache minedBlockHeights *lru.ARCCache
evtTypes [1]journal.EventType evtTypes [1]journal.EventType
journal journal.Journal journal journal.Journal
} }
// Address returns the address of the miner.
func (m *Miner) Address() address.Address { func (m *Miner) Address() address.Address {
m.lk.Lock() m.lk.Lock()
defer m.lk.Unlock() defer m.lk.Unlock()
@ -107,7 +132,9 @@ func (m *Miner) Address() address.Address {
return m.address return m.address
} }
func (m *Miner) Start(ctx context.Context) error { // Start starts the mining operation. It spawns a goroutine and returns
// immediately. Start is not idempotent.
func (m *Miner) Start(_ context.Context) error {
m.lk.Lock() m.lk.Lock()
defer m.lk.Unlock() defer m.lk.Unlock()
if m.stop != nil { if m.stop != nil {
@ -118,6 +145,8 @@ func (m *Miner) Start(ctx context.Context) error {
return nil return nil
} }
// Stop stops the mining operation. It is not idempotent, and multiple adjacent
// calls to Stop will fail.
func (m *Miner) Stop(ctx context.Context) error { func (m *Miner) Stop(ctx context.Context) error {
m.lk.Lock() m.lk.Lock()
@ -145,6 +174,28 @@ func (m *Miner) niceSleep(d time.Duration) bool {
} }
} }
// mine runs the mining loop. It performs the following:
//
// 1. Queries our current best currently-known mining candidate (tipset to
// build upon).
// 2. Waits until the propagation delay of the network has elapsed (currently
// 6 seconds). The waiting is done relative to the timestamp of the best
// candidate, which means that if it's way in the past, we won't wait at
// all (e.g. in catch-up or rush mining).
// 3. After the wait, we query our best mining candidate. This will be the one
// we'll work with.
// 4. Sanity check that we _actually_ have a new mining base to mine on. If
// not, wait one epoch + propagation delay, and go back to the top.
// 5. We attempt to mine a block, by calling mineOne (refer to godocs). This
// method will either return a block if we were eligible to mine, or nil
// if we weren't.
// 6a. If we mined a block, we update our state and push it out to the network
// via gossipsub.
// 6b. If we didn't mine a block, we consider this to be a nil round on top of
// the mining base we selected. If other miner or miners on the network
// were eligible to mine, we will receive their blocks via gossipsub and
// we will select that tipset on the next iteration of the loop, thus
// discarding our null round.
func (m *Miner) mine(ctx context.Context) { func (m *Miner) mine(ctx context.Context) {
ctx, span := trace.StartSpan(ctx, "/mine") ctx, span := trace.StartSpan(ctx, "/mine")
defer span.End() defer span.End()
@ -305,11 +356,19 @@ minerLoop:
} }
} }
// MiningBase is the tipset on top of which we plan to construct our next block.
// Refer to godocs on GetBestMiningCandidate.
type MiningBase struct { type MiningBase struct {
TipSet *types.TipSet TipSet *types.TipSet
NullRounds abi.ChainEpoch NullRounds abi.ChainEpoch
} }
// GetBestMiningCandidate implements the fork choice rule from a miner's
// perspective.
//
// It obtains the current chain head (HEAD), and compares it to the last tipset
// we selected as our mining base (LAST). If HEAD's weight is larger than
// LAST's weight, it selects HEAD to build on. Else, it selects LAST.
func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) { func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) {
m.lk.Lock() m.lk.Lock()
defer m.lk.Unlock() defer m.lk.Unlock()

View File

@ -305,7 +305,7 @@ var ChainNode = Options(
Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner), Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner),
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.Wallet), From(new(wallet.MultiWallet))),
// Service: Payment channels // Service: Payment channels
Override(new(paychmgr.PaychAPI), From(new(modules.PaychAPI))), Override(new(paychmgr.PaychAPI), From(new(modules.PaychAPI))),
@ -329,13 +329,15 @@ var ChainNode = Options(
Override(new(storagemarket.StorageClientNode), storageadapter.NewClientNodeAdapter), Override(new(storagemarket.StorageClientNode), storageadapter.NewClientNodeAdapter),
Override(HandleMigrateClientFundsKey, modules.HandleMigrateClientFunds), Override(HandleMigrateClientFundsKey, modules.HandleMigrateClientFunds),
Override(new(*full.GasPriceCache), full.NewGasPriceCache),
// Lite node API // Lite node API
ApplyIf(isLiteNode, ApplyIf(isLiteNode,
Override(new(messagesigner.MpoolNonceAPI), From(new(modules.MpoolNonceAPI))), Override(new(messagesigner.MpoolNonceAPI), From(new(modules.MpoolNonceAPI))),
Override(new(full.ChainModuleAPI), From(new(api.GatewayAPI))), Override(new(full.ChainModuleAPI), From(new(api.Gateway))),
Override(new(full.GasModuleAPI), From(new(api.GatewayAPI))), Override(new(full.GasModuleAPI), From(new(api.Gateway))),
Override(new(full.MpoolModuleAPI), From(new(api.GatewayAPI))), Override(new(full.MpoolModuleAPI), From(new(api.Gateway))),
Override(new(full.StateModuleAPI), From(new(api.GatewayAPI))), Override(new(full.StateModuleAPI), From(new(api.Gateway))),
Override(new(stmgr.StateManagerAPI), rpcstmgr.NewRPCStateManager), Override(new(stmgr.StateManagerAPI), rpcstmgr.NewRPCStateManager),
), ),
@ -727,3 +729,19 @@ func Test() Option {
Override(new(*storageadapter.DealPublisher), storageadapter.NewDealPublisher(nil, storageadapter.PublishMsgConfig{})), Override(new(*storageadapter.DealPublisher), storageadapter.NewDealPublisher(nil, storageadapter.PublishMsgConfig{})),
) )
} }
// For 3rd party dep injection.
func WithRepoType(repoType repo.RepoType) func(s *Settings) error {
return func(s *Settings) error {
s.nodeType = repoType
return nil
}
}
func WithInvokesKey(i invoke, resApi interface{}) func(s *Settings) error {
return func(s *Settings) error {
s.invokes[i] = fx.Populate(resApi)
return nil
}
}

View File

@ -267,10 +267,14 @@ func (a *API) newDealInfo(ctx context.Context, v storagemarket.ClientDeal) api.D
// be not found if it's no longer active // be not found if it's no longer active
if err == nil { if err == nil {
ch := api.NewDataTransferChannel(a.Host.ID(), state) ch := api.NewDataTransferChannel(a.Host.ID(), state)
ch.Stages = state.Stages()
transferCh = &ch transferCh = &ch
} }
} }
return a.newDealInfoWithTransfer(transferCh, v)
di := a.newDealInfoWithTransfer(transferCh, v)
di.DealStages = v.DealStages
return di
} }
func (a *API) newDealInfoWithTransfer(transferCh *api.DataTransferChannel, v storagemarket.ClientDeal) api.DealInfo { func (a *API) newDealInfoWithTransfer(transferCh *api.DataTransferChannel, v storagemarket.ClientDeal) api.DealInfo {
@ -475,6 +479,29 @@ func (a *API) ClientListImports(ctx context.Context) ([]api.Import, error) {
return out, nil return out, nil
} }
func (a *API) ClientCancelRetrievalDeal(ctx context.Context, dealID retrievalmarket.DealID) error {
cerr := make(chan error)
go func() {
err := a.Retrieval.CancelDeal(dealID)
select {
case cerr <- err:
case <-ctx.Done():
}
}()
select {
case err := <-cerr:
if err != nil {
return xerrors.Errorf("failed to cancel retrieval deal: %w", err)
}
return nil
case <-ctx.Done():
return xerrors.Errorf("context timeout while canceling retrieval deal: %w", ctx.Err())
}
}
func (a *API) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error { func (a *API) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error {
events := make(chan marketevents.RetrievalEvent) events := make(chan marketevents.RetrievalEvent)
go a.clientRetrieve(ctx, order, ref, events) go a.clientRetrieve(ctx, order, ref, events)

View File

@ -24,6 +24,7 @@ import (
"github.com/filecoin-project/go-jsonrpc/auth" "github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
apitypes "github.com/filecoin-project/lotus/api/types"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/modules/lp2p" "github.com/filecoin-project/lotus/node/modules/lp2p"
@ -207,6 +208,10 @@ func (a *CommonAPI) NetBandwidthStatsByProtocol(ctx context.Context) (map[protoc
return a.Reporter.GetBandwidthByProtocol(), nil return a.Reporter.GetBandwidthByProtocol(), nil
} }
func (a *CommonAPI) Discover(ctx context.Context) (apitypes.OpenRPCDocument, error) {
return build.OpenRPCDiscoverJSON_Full(), nil
}
func (a *CommonAPI) ID(context.Context) (peer.ID, error) { func (a *CommonAPI) ID(context.Context) (peer.ID, error) {
return a.Host.ID(), nil return a.Host.ID(), nil
} }

Some files were not shown because too many files have changed in this diff Show More