Merge branch 'releases' into release/v1.10.0

This commit is contained in:
Aayush Rajasekaran 2021-06-15 17:33:04 -04:00
commit 520a0091f5
145 changed files with 15121 additions and 1644 deletions

View File

@ -444,7 +444,7 @@ jobs:
- run: make deps
- run: go install golang.org/x/tools/cmd/goimports
- run: go install github.com/hannahhoward/cbor-gen-for
- run: go generate ./...
- run: make type-gen
- run: git --no-pager diff
- run: git --no-pager diff --quiet
@ -453,6 +453,7 @@ jobs:
steps:
- install-deps
- prepare
- run: go install golang.org/x/tools/cmd/goimports
- 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

8
.github/CODEOWNERS vendored
View File

@ -8,9 +8,9 @@
## the PR before merging.
### Global owners.
* @magik6k @whyrusleeping @Kubuxu
* @magik6k @arajasek
### Conformance testing.
conformance/ @raulk
extern/test-vectors @raulk
cmd/tvx @raulk
conformance/ @ZenGround0
extern/test-vectors @ZenGround0
cmd/tvx @ZenGround0

65
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@ -0,0 +1,65 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@ -233,6 +233,13 @@ testground:
.PHONY: testground
BINS+=testground
tvx:
rm -f tvx
go build -o tvx ./cmd/tvx
.PHONY: tvx
BINS+=tvx
install-chainwatch: lotus-chainwatch
install -C ./lotus-chainwatch /usr/local/bin/lotus-chainwatch
@ -318,11 +325,12 @@ dist-clean:
git submodule deinit --all -f
.PHONY: dist-clean
type-gen:
type-gen: api-gen
go run ./gen/main.go
go generate ./...
go generate -x ./...
goimports -w api/
method-gen:
method-gen: api-gen
(cd ./lotuspond/front/src/chain && go run ./methodgen.go)
actors-gen:
@ -330,35 +338,36 @@ actors-gen:
go fmt ./...
api-gen:
go run ./gen/api > api/apistruct/struct.go
goimports -w api/apistruct
goimports -w api/apistruct
go run ./gen/api
goimports -w api
goimports -w api
.PHONY: api-gen
docsgen: docsgen-md docsgen-openrpc
docsgen-md-bin: actors-gen
docsgen-md-bin: api-gen actors-gen
go build $(GOFLAGS) -o docgen-md ./api/docgen/cmd
docsgen-openrpc-bin: actors-gen
docsgen-openrpc-bin: api-gen actors-gen
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
./docgen-md "api/api_full.go" "FullNode" "api" "./api" > documentation/en/api-v1-unstable-methods.md
./docgen-md "api/v0api/full.go" "FullNode" "v0api" "./api/v0api" > documentation/en/api-v0-methods.md
docsgen-md-storage: docsgen-md-bin
./docgen-md "api/api_storage.go" "StorageMiner" > documentation/en/api-methods-miner.md
./docgen-md "api/api_storage.go" "StorageMiner" "api" "./api" > documentation/en/api-v0-methods-miner.md
docsgen-md-worker: docsgen-md-bin
./docgen-md "api/api_worker.go" "Worker" > documentation/en/api-methods-worker.md
./docgen-md "api/api_worker.go" "Worker" "api" "./api" > documentation/en/api-v0-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
./docgen-openrpc "api/api_full.go" "FullNode" "api" "./api" -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
./docgen-openrpc "api/api_storage.go" "StorageMiner" "api" "./api" -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
./docgen-openrpc "api/api_worker.go" "Worker" "api" "./api" -gzip > build/openrpc/worker.json.gz
.PHONY: docsgen docsgen-md-bin docsgen-openrpc-bin

14
api/README.md Normal file
View File

@ -0,0 +1,14 @@
## Lotus API
This package contains all lotus API definitions. Interfaces defined here are
exposed as JsonRPC 2.0 endpoints by lotus programs.
### Versions
| File | Alias File | Interface | Exposed by | Version | HTTP Endpoint | Status | Docs
|------------------|-------------------|----------------|--------------------|---------|---------------|------------------------------|------
| `api_common.go` | `v0api/latest.go` | `Common` | lotus; lotus-miner | v0 | `/rpc/v0` | Latest, Stable | [Methods](../documentation/en/api-v0-methods.md)
| `api_full.go` | `v1api/latest.go` | `FullNode` | lotus | v1 | `/rpc/v1` | Latest, **Work in progress** | [Methods](../documentation/en/api-v1-unstable-methods.md)
| `api_storage.go` | `v0api/latest.go` | `StorageMiner` | lotus-miner | v0 | `/rpc/v0` | Latest, Stable | [Methods](../documentation/en/api-v0-methods-miner.md)
| `api_worker.go` | `v0api/latest.go` | `Worker` | lotus-worker | v0 | `/rpc/v0` | Latest, Stable | [Methods](../documentation/en/api-v0-methods-worker.md)
| `v0api/full.go` | | `FullNode` | lotus | v0 | `/rpc/v0` | Stable | [Methods](../documentation/en/api-v0-methods.md)

View File

@ -15,6 +15,17 @@ import (
apitypes "github.com/filecoin-project/lotus/api/types"
)
// MODIFYING THE API INTERFACE
//
// When adding / changing methods in this file:
// * Do the change here
// * Adjust implementation in `node/impl/`
// * Run `make gen` - this will:
// * Generate proxy structs
// * Generate mocks
// * Generate markdown docs
// * Generate openrpc blobs
type Common interface {
// MethodGroup: Auth

View File

@ -39,6 +39,22 @@ type ChainIO interface {
ChainHasObj(context.Context, cid.Cid) (bool, error)
}
const LookbackNoLimit = abi.ChainEpoch(-1)
// MODIFYING THE API INTERFACE
//
// NOTE: This is the V1 (Unstable) API - to add methods to the V0 (Stable) API
// you'll have to add those methods to interfaces in `api/v0api`
//
// When adding / changing methods in this file:
// * Do the change here
// * Adjust implementation in `node/impl/`
// * Run `make gen` - this will:
// * Generate proxy structs
// * Generate mocks
// * Generate markdown docs
// * Generate openrpc blobs
// FullNode API is a low-level interface to the Filecoin network full node
type FullNode interface {
Common
@ -430,7 +446,7 @@ type FullNode interface {
StateSectorExpiration(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorExpiration, error) //perm:read
// StateSectorPartition finds deadline/partition with the specified sector
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 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
// a MsgLookup for the replacing message - the MsgLookup.Message will be a different
@ -438,48 +454,16 @@ type FullNode interface {
// result of the execution of the replacing message.
//
// If the caller wants to ensure that exactly the requested message was executed,
// they MUST check that MsgLookup.Message is equal to the provided 'cid'.
// Without this check both the requested and original message may appear as
// they must check that MsgLookup.Message is equal to the provided 'cid', or set the
// `allowReplaced` parameter to false. Without this check, and with `allowReplaced`
// set to true, 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.)
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
//
// NOTE: If a replacing message is found on chain, this method will return
// a MsgLookup for the replacing message - the MsgLookup.Message will be a different
// CID than the one provided in the 'cid' param, MsgLookup.Receipt will contain the
// result of the execution of the replacing message.
//
// If the caller wants to ensure that exactly the requested message was executed,
// they MUST check that MsgLookup.Message 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.)
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
// message arrives on chain, and gets to the indicated confidence depth.
//
// NOTE: If a replacing message is found on chain, this method will return
// a MsgLookup for the replacing message - the MsgLookup.Message will be a different
// CID than the one provided in the 'cid' param, MsgLookup.Receipt will contain the
// result of the execution of the replacing message.
//
// If the caller wants to ensure that exactly the requested message was executed,
// they MUST check that MsgLookup.Message 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.)
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.
StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*MsgLookup, error) //perm:read
// StateWaitMsg 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
// indicated confidence depth.
//
@ -489,14 +473,15 @@ type FullNode interface {
// result of the execution of the replacing message.
//
// If the caller wants to ensure that exactly the requested message was executed,
// they MUST check that MsgLookup.Message is equal to the provided 'cid'.
// Without this check both the requested and original message may appear as
// they must check that MsgLookup.Message is equal to the provided 'cid', or set the
// `allowReplaced` parameter to false. Without this check, and with `allowReplaced`
// set to true, 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.)
StateWaitMsgLimited(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch) (*MsgLookup, error) //perm:read
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*MsgLookup, error) //perm:read
// StateListMiners returns the addresses of every miner that has claimed power in the Power Actor
StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error) //perm:read
// StateListActors returns the addresses of every actor in the state
@ -516,16 +501,6 @@ type FullNode interface {
// StateChangedActors returns all the actors whose states change between the two given state CIDs
// TODO: Should this take tipset keys instead?
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
// matching gas-repriced replacing message
//
// 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
// requested message, use StateSearchMsg().Receipt, and check that MsgLookup.Message
// is matching the requested CID
//
// DEPRECATED: Use StateSearchMsg, this method won't be supported in v1 API
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(context.Context, address.Address, types.TipSetKey) (MinerSectors, error) //perm:read
// StateCompute is a flexible command that applies the given messages on the given tipset.
@ -1038,11 +1013,12 @@ type DealCollateralBounds struct {
}
type CirculatingSupply struct {
FilVested abi.TokenAmount
FilMined abi.TokenAmount
FilBurnt abi.TokenAmount
FilLocked abi.TokenAmount
FilCirculating abi.TokenAmount
FilVested abi.TokenAmount
FilMined abi.TokenAmount
FilBurnt abi.TokenAmount
FilLocked abi.TokenAmount
FilCirculating abi.TokenAmount
FilReserveDisbursed abi.TokenAmount
}
type MiningBaseInfo struct {

View File

@ -14,6 +14,20 @@ import (
"github.com/filecoin-project/lotus/chain/types"
)
// MODIFYING THE API INTERFACE
//
// NOTE: This is the V1 (Unstable) API - to add methods to the V0 (Stable) API
// you'll have to add those methods to interfaces in `api/v0api`
//
// When adding / changing methods in this file:
// * Do the change here
// * Adjust implementation in `node/impl/`
// * Run `make gen` - this will:
// * Generate proxy structs
// * Generate mocks
// * Generate markdown docs
// * Generate openrpc blobs
type Gateway interface {
ChainHasObj(context.Context, cid.Cid) (bool, error)
ChainHead(ctx context.Context) (*types.TipSet, error)
@ -31,7 +45,6 @@ type Gateway interface {
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (DealCollateralBounds, error)
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (MarketBalance, error)
@ -40,8 +53,9 @@ type Gateway interface {
StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error)
StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, 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)
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*MsgLookup, error)
StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*MsgLookup, error)
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*MsgLookup, error)
WalletBalance(context.Context, address.Address) (types.BigInt, error)
}

View File

@ -27,6 +27,17 @@ import (
"github.com/filecoin-project/lotus/extern/storage-sealing/sealiface"
)
// MODIFYING THE API INTERFACE
//
// When adding / changing methods in this file:
// * Do the change here
// * Adjust implementation in `node/impl/`
// * Run `make gen` - this will:
// * Generate proxy structs
// * Generate mocks
// * Generate markdown docs
// * Generate openrpc blobs
// StorageMiner is a low-level interface to the Filecoin network storage miner node
type StorageMiner interface {
Common

View File

@ -113,3 +113,9 @@ func TestReturnTypes(t *testing.T) {
t.Run("miner", tst(new(StorageMiner)))
t.Run("worker", tst(new(Worker)))
}
func TestPermTags(t *testing.T) {
_ = PermissionedFullAPI(&FullNodeStruct{})
_ = PermissionedStorMinerAPI(&StorageMinerStruct{})
_ = PermissionedWorkerAPI(&WorkerStruct{})
}

View File

@ -14,6 +14,17 @@ import (
"github.com/filecoin-project/specs-storage/storage"
)
// MODIFYING THE API INTERFACE
//
// When adding / changing methods in this file:
// * Do the change here
// * Adjust implementation in `node/impl/`
// * Run `make gen` - this will:
// * Generate proxy structs
// * Generate mocks
// * Generate markdown docs
// * Generate openrpc blobs
type Worker interface {
Version(context.Context) (Version, error) //perm:admin

View File

@ -1,9 +0,0 @@
package apistruct
import "testing"
func TestPermTags(t *testing.T) {
_ = PermissionedFullAPI(&FullNodeStruct{})
_ = PermissionedStorMinerAPI(&StorageMinerStruct{})
_ = PermissionedWorkerAPI(&WorkerStruct{})
}

View File

@ -10,13 +10,14 @@ import (
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/api/v1api"
"github.com/filecoin-project/lotus/lib/rpcenc"
)
// NewCommonRPC creates a new http jsonrpc client.
func NewCommonRPC(ctx context.Context, addr string, requestHeader http.Header) (api.Common, jsonrpc.ClientCloser, error) {
var res apistruct.CommonStruct
// NewCommonRPCV0 creates a new http jsonrpc client.
func NewCommonRPCV0(ctx context.Context, addr string, requestHeader http.Header) (api.Common, jsonrpc.ClientCloser, error) {
var res v0api.CommonStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
&res.Internal,
@ -27,9 +28,9 @@ func NewCommonRPC(ctx context.Context, addr string, requestHeader http.Header) (
return &res, closer, err
}
// NewFullNodeRPC creates a new http jsonrpc client.
func NewFullNodeRPC(ctx context.Context, addr string, requestHeader http.Header) (api.FullNode, jsonrpc.ClientCloser, error) {
var res apistruct.FullNodeStruct
// NewFullNodeRPCV0 creates a new http jsonrpc client.
func NewFullNodeRPCV0(ctx context.Context, addr string, requestHeader http.Header) (v0api.FullNode, jsonrpc.ClientCloser, error) {
var res v0api.FullNodeStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
&res.CommonStruct.Internal,
@ -39,9 +40,21 @@ func NewFullNodeRPC(ctx context.Context, addr string, requestHeader http.Header)
return &res, closer, err
}
// NewStorageMinerRPC creates a new http jsonrpc client for miner
func NewStorageMinerRPC(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (api.StorageMiner, jsonrpc.ClientCloser, error) {
var res apistruct.StorageMinerStruct
// NewFullNodeRPCV1 creates a new http jsonrpc client.
func NewFullNodeRPCV1(ctx context.Context, addr string, requestHeader http.Header) (api.FullNode, jsonrpc.ClientCloser, error) {
var res v1api.FullNodeStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
&res.CommonStruct.Internal,
&res.Internal,
}, requestHeader)
return &res, closer, err
}
// NewStorageMinerRPCV0 creates a new http jsonrpc client for miner
func NewStorageMinerRPCV0(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (v0api.StorageMiner, jsonrpc.ClientCloser, error) {
var res v0api.StorageMinerStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
&res.CommonStruct.Internal,
@ -54,7 +67,7 @@ func NewStorageMinerRPC(ctx context.Context, addr string, requestHeader http.Hea
return &res, closer, err
}
func NewWorkerRPC(ctx context.Context, addr string, requestHeader http.Header) (api.Worker, jsonrpc.ClientCloser, error) {
func NewWorkerRPCV0(ctx context.Context, addr string, requestHeader http.Header) (api.Worker, jsonrpc.ClientCloser, error) {
u, err := url.Parse(addr)
if err != nil {
return nil, nil, err
@ -69,7 +82,7 @@ func NewWorkerRPC(ctx context.Context, addr string, requestHeader http.Header) (
u.Path = path.Join(u.Path, "../streams/v0/push")
var res apistruct.WorkerStruct
var res api.WorkerStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
&res.Internal,
@ -83,9 +96,9 @@ func NewWorkerRPC(ctx context.Context, addr string, requestHeader http.Header) (
return &res, closer, err
}
// 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.Gateway, jsonrpc.ClientCloser, error) {
var res apistruct.GatewayStruct
// NewGatewayRPCV1 creates a new http jsonrpc client for a gateway node.
func NewGatewayRPCV1(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (api.Gateway, jsonrpc.ClientCloser, error) {
var res api.GatewayStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
&res.Internal,
@ -97,8 +110,22 @@ func NewGatewayRPC(ctx context.Context, addr string, requestHeader http.Header,
return &res, closer, err
}
func NewWalletRPC(ctx context.Context, addr string, requestHeader http.Header) (api.Wallet, jsonrpc.ClientCloser, error) {
var res apistruct.WalletStruct
// NewGatewayRPCV0 creates a new http jsonrpc client for a gateway node.
func NewGatewayRPCV0(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (v0api.Gateway, jsonrpc.ClientCloser, error) {
var res v0api.GatewayStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
&res.Internal,
},
requestHeader,
opts...,
)
return &res, closer, err
}
func NewWalletRPCV0(ctx context.Context, addr string, requestHeader http.Header) (api.Wallet, jsonrpc.ClientCloser, error) {
var res api.WalletStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
&res.Internal,

View File

@ -7,7 +7,8 @@ import (
"log"
"os"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/api/docgen"
docgen_openrpc "github.com/filecoin-project/lotus/api/docgen-openrpc"
)
@ -29,16 +30,12 @@ Use:
*/
func main() {
doc := docgen_openrpc.NewLotusOpenRPCDocument()
Comments, GroupDocs := docgen.ParseApiASTInfo(os.Args[1], os.Args[2], os.Args[3], os.Args[4])
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{})
}
doc := docgen_openrpc.NewLotusOpenRPCDocument(Comments, GroupDocs)
i, _, _, _ := docgen.GetAPIType(os.Args[2], os.Args[3])
doc.RegisterReceiverName("Filecoin", i)
out, err := doc.Discover()
if err != nil {
@ -52,7 +49,7 @@ func main() {
// 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" {
if len(os.Args) > 5 && os.Args[5] == "-gzip" {
jsonOut, err = json.Marshal(out)
if err != nil {
log.Fatalln(err)

View File

@ -4,7 +4,6 @@ import (
"encoding/json"
"go/ast"
"net"
"os"
"reflect"
"github.com/alecthomas/jsonschema"
@ -15,16 +14,6 @@ import (
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{}
@ -94,7 +83,7 @@ func OpenRPCSchemaTypeMapper(ty reflect.Type) *jsonschema.Type {
}
// NewLotusOpenRPCDocument defines application-specific documentation and configuration for its OpenRPC document.
func NewLotusOpenRPCDocument() *go_openrpc_reflect.Document {
func NewLotusOpenRPCDocument(Comments, GroupDocs map[string]string) *go_openrpc_reflect.Document {
d := &go_openrpc_reflect.Document{}
// Register "Meta" document fields.

View File

@ -4,39 +4,18 @@ 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])
comments, groupComments := docgen.ParseApiASTInfo(os.Args[1], os.Args[2], os.Args[3], os.Args[4])
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")
}
_, t, permStruct, commonPermStruct := docgen.GetAPIType(os.Args[2], os.Args[3])
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)

View File

@ -35,6 +35,7 @@ import (
"github.com/filecoin-project/lotus/api"
apitypes "github.com/filecoin-project/lotus/api/types"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/extern/sector-storage/sealtasks"
@ -113,7 +114,7 @@ func init() {
addExample(network.Connected)
addExample(dtypes.NetworkName("lotus"))
addExample(api.SyncStateStage(1))
addExample(api.FullAPIVersion)
addExample(api.FullAPIVersion1)
addExample(api.PCHInbound)
addExample(time.Minute)
addExample(datatransfer.TransferID(3))
@ -262,6 +263,42 @@ func init() {
)
}
func GetAPIType(name, pkg string) (i interface{}, t, permStruct, commonPermStruct reflect.Type) {
switch pkg {
case "api": // latest
switch name {
case "FullNode":
i = &api.FullNodeStruct{}
t = reflect.TypeOf(new(struct{ api.FullNode })).Elem()
permStruct = reflect.TypeOf(api.FullNodeStruct{}.Internal)
commonPermStruct = reflect.TypeOf(api.CommonStruct{}.Internal)
case "StorageMiner":
i = &api.StorageMinerStruct{}
t = reflect.TypeOf(new(struct{ api.StorageMiner })).Elem()
permStruct = reflect.TypeOf(api.StorageMinerStruct{}.Internal)
commonPermStruct = reflect.TypeOf(api.CommonStruct{}.Internal)
case "Worker":
i = &api.WorkerStruct{}
t = reflect.TypeOf(new(struct{ api.Worker })).Elem()
permStruct = reflect.TypeOf(api.WorkerStruct{}.Internal)
commonPermStruct = reflect.TypeOf(api.WorkerStruct{}.Internal)
default:
panic("unknown type")
}
case "v0api":
switch name {
case "FullNode":
i = v0api.FullNodeStruct{}
t = reflect.TypeOf(new(struct{ v0api.FullNode })).Elem()
permStruct = reflect.TypeOf(v0api.FullNodeStruct{}.Internal)
commonPermStruct = reflect.TypeOf(v0api.CommonStruct{}.Internal)
default:
panic("unknown type")
}
}
return
}
func ExampleValue(method string, t, parent reflect.Type) interface{} {
v, ok := ExampleValues[t]
if ok {
@ -342,9 +379,9 @@ func (v *Visitor) Visit(node ast.Node) ast.Visitor {
const NoComment = "There are not yet any comments for this method."
func ParseApiASTInfo(apiFile, iface string) (comments map[string]string, groupDocs map[string]string) { //nolint:golint
func ParseApiASTInfo(apiFile, iface, pkg, dir string) (comments map[string]string, groupDocs map[string]string) { //nolint:golint
fset := token.NewFileSet()
apiDir, err := filepath.Abs("./api")
apiDir, err := filepath.Abs(dir)
if err != nil {
fmt.Println("./api filepath absolute error: ", err)
return
@ -360,14 +397,14 @@ func ParseApiASTInfo(apiFile, iface string) (comments map[string]string, groupDo
return
}
ap := pkgs["api"]
ap := pkgs[pkg]
f := ap.Files[apiFile]
cmap := ast.NewCommentMap(fset, f, f.Comments)
v := &Visitor{iface, make(map[string]ast.Node)}
ast.Walk(v, pkgs["api"])
ast.Walk(v, ap)
comments = make(map[string]string)
groupDocs = make(map[string]string)

View File

@ -6,6 +6,8 @@ package mocks
import (
context "context"
reflect "reflect"
address "github.com/filecoin-project/go-address"
bitfield "github.com/filecoin-project/go-bitfield"
datatransfer "github.com/filecoin-project/go-data-transfer"
@ -33,7 +35,6 @@ import (
network0 "github.com/libp2p/go-libp2p-core/network"
peer "github.com/libp2p/go-libp2p-core/peer"
protocol "github.com/libp2p/go-libp2p-core/protocol"
reflect "reflect"
)
// MockFullNode is a mock of FullNode interface
@ -2094,21 +2095,6 @@ func (mr *MockFullNodeMockRecorder) StateGetActor(arg0, arg1, arg2 interface{})
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetActor", reflect.TypeOf((*MockFullNode)(nil).StateGetActor), arg0, arg1, arg2)
}
// StateGetReceipt mocks base method
func (m *MockFullNode) StateGetReceipt(arg0 context.Context, arg1 cid.Cid, arg2 types.TipSetKey) (*types.MessageReceipt, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateGetReceipt", arg0, arg1, arg2)
ret0, _ := ret[0].(*types.MessageReceipt)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateGetReceipt indicates an expected call of StateGetReceipt
func (mr *MockFullNodeMockRecorder) StateGetReceipt(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetReceipt", reflect.TypeOf((*MockFullNode)(nil).StateGetReceipt), arg0, arg1, arg2)
}
// StateListActors mocks base method
func (m *MockFullNode) StateListActors(arg0 context.Context, arg1 types.TipSetKey) ([]address.Address, error) {
m.ctrl.T.Helper()
@ -2500,33 +2486,18 @@ func (mr *MockFullNodeMockRecorder) StateReplay(arg0, arg1, arg2 interface{}) *g
}
// StateSearchMsg mocks base method
func (m *MockFullNode) StateSearchMsg(arg0 context.Context, arg1 cid.Cid) (*api.MsgLookup, error) {
func (m *MockFullNode) StateSearchMsg(arg0 context.Context, arg1 types.TipSetKey, arg2 cid.Cid, arg3 abi.ChainEpoch, arg4 bool) (*api.MsgLookup, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateSearchMsg", arg0, arg1)
ret := m.ctrl.Call(m, "StateSearchMsg", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(*api.MsgLookup)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateSearchMsg indicates an expected call of StateSearchMsg
func (mr *MockFullNodeMockRecorder) StateSearchMsg(arg0, arg1 interface{}) *gomock.Call {
func (mr *MockFullNodeMockRecorder) StateSearchMsg(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateSearchMsg", reflect.TypeOf((*MockFullNode)(nil).StateSearchMsg), arg0, arg1)
}
// StateSearchMsgLimited mocks base method
func (m *MockFullNode) StateSearchMsgLimited(arg0 context.Context, arg1 cid.Cid, arg2 abi.ChainEpoch) (*api.MsgLookup, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateSearchMsgLimited", arg0, arg1, arg2)
ret0, _ := ret[0].(*api.MsgLookup)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateSearchMsgLimited indicates an expected call of StateSearchMsgLimited
func (mr *MockFullNodeMockRecorder) StateSearchMsgLimited(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateSearchMsgLimited", reflect.TypeOf((*MockFullNode)(nil).StateSearchMsgLimited), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateSearchMsg", reflect.TypeOf((*MockFullNode)(nil).StateSearchMsg), arg0, arg1, arg2, arg3, arg4)
}
// StateSectorExpiration mocks base method
@ -2650,33 +2621,18 @@ func (mr *MockFullNodeMockRecorder) StateVerifierStatus(arg0, arg1, arg2 interfa
}
// StateWaitMsg mocks base method
func (m *MockFullNode) StateWaitMsg(arg0 context.Context, arg1 cid.Cid, arg2 uint64) (*api.MsgLookup, error) {
func (m *MockFullNode) StateWaitMsg(arg0 context.Context, arg1 cid.Cid, arg2 uint64, arg3 abi.ChainEpoch, arg4 bool) (*api.MsgLookup, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateWaitMsg", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "StateWaitMsg", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(*api.MsgLookup)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateWaitMsg indicates an expected call of StateWaitMsg
func (mr *MockFullNodeMockRecorder) StateWaitMsg(arg0, arg1, arg2 interface{}) *gomock.Call {
func (mr *MockFullNodeMockRecorder) StateWaitMsg(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateWaitMsg", reflect.TypeOf((*MockFullNode)(nil).StateWaitMsg), arg0, arg1, arg2)
}
// StateWaitMsgLimited mocks base method
func (m *MockFullNode) StateWaitMsgLimited(arg0 context.Context, arg1 cid.Cid, arg2 uint64, arg3 abi.ChainEpoch) (*api.MsgLookup, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateWaitMsgLimited", arg0, arg1, arg2, arg3)
ret0, _ := ret[0].(*api.MsgLookup)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateWaitMsgLimited indicates an expected call of StateWaitMsgLimited
func (mr *MockFullNodeMockRecorder) StateWaitMsgLimited(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateWaitMsgLimited", reflect.TypeOf((*MockFullNode)(nil).StateWaitMsgLimited), arg0, arg1, arg2, arg3)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateWaitMsg", reflect.TypeOf((*MockFullNode)(nil).StateWaitMsg), arg0, arg1, arg2, arg3, arg4)
}
// SyncCheckBad mocks base method

View File

@ -1,8 +1,7 @@
package apistruct
package api
import (
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/api"
)
const (
@ -17,27 +16,27 @@ const (
var AllPermissions = []auth.Permission{PermRead, PermWrite, PermSign, PermAdmin}
var DefaultPerms = []auth.Permission{PermRead}
func PermissionedStorMinerAPI(a api.StorageMiner) api.StorageMiner {
func PermissionedStorMinerAPI(a StorageMiner) StorageMiner {
var out StorageMinerStruct
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.CommonStruct.Internal)
return &out
}
func PermissionedFullAPI(a api.FullNode) api.FullNode {
func PermissionedFullAPI(a FullNode) FullNode {
var out FullNodeStruct
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.CommonStruct.Internal)
return &out
}
func PermissionedWorkerAPI(a api.Worker) api.Worker {
func PermissionedWorkerAPI(a Worker) Worker {
var out WorkerStruct
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
return &out
}
func PermissionedWalletAPI(a api.Wallet) api.Wallet {
func PermissionedWalletAPI(a Wallet) Wallet {
var out WalletStruct
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
return &out

3622
api/proxy_gen.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,8 @@ import (
"testing"
"time"
"github.com/filecoin-project/lotus/api"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-address"
@ -240,7 +242,7 @@ func TestDeadlineToggling(t *testing.T, b APIBuilder, blocktime time.Duration) {
}, nil)
require.NoError(t, err)
r, err := client.StateWaitMsg(ctx, m.Cid(), 2)
r, err := client.StateWaitMsg(ctx, m.Cid(), 2, api.LookbackNoLimit, true)
require.NoError(t, err)
require.Equal(t, exitcode.Ok, r.Receipt.ExitCode)
}
@ -323,7 +325,7 @@ func TestDeadlineToggling(t *testing.T, b APIBuilder, blocktime time.Duration) {
fmt.Println("sent termination message:", smsg.Cid())
r, err := client.StateWaitMsg(ctx, smsg.Cid(), 2)
r, err := client.StateWaitMsg(ctx, smsg.Cid(), 2, api.LookbackNoLimit, true)
require.NoError(t, err)
require.Equal(t, exitcode.Ok, r.Receipt.ExitCode)

View File

@ -235,7 +235,7 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
if err != nil {
t.Fatal(err)
}
res, err = paymentReceiver.StateWaitMsg(ctx, collectMsg, 3)
res, err = paymentReceiver.StateWaitMsg(ctx, collectMsg, 3, api.LookbackNoLimit, true)
if err != nil {
t.Fatal(err)
}
@ -287,7 +287,7 @@ func waitForBlocks(ctx context.Context, t *testing.T, bm *BlockMiner, paymentRec
t.Fatal(err)
}
_, err = paymentReceiver.StateWaitMsg(ctx, m.Cid(), 1)
_, err = paymentReceiver.StateWaitMsg(ctx, m.Cid(), 1, api.LookbackNoLimit, true)
if err != nil {
t.Fatal(err)
}
@ -299,7 +299,7 @@ func waitForMessage(ctx context.Context, t *testing.T, paymentCreator TestNode,
defer cancel()
fmt.Println("Waiting for", desc)
res, err := paymentCreator.StateWaitMsg(ctx, msgCid, 1)
res, err := paymentCreator.StateWaitMsg(ctx, msgCid, 1, api.LookbackNoLimit, true)
if err != nil {
fmt.Println("Error waiting for", desc, err)
t.Fatal(err)

View File

@ -19,7 +19,8 @@ import (
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/api"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v1api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
@ -39,7 +40,7 @@ func init() {
type StorageBuilder func(context.Context, *testing.T, abi.RegisteredSealProof, address.Address) TestStorageNode
type TestNode struct {
api.FullNode
v1api.FullNode
// ListenAddr is the address on which an API server is listening, if an
// API server is created for this Node
ListenAddr multiaddr.Multiaddr
@ -48,7 +49,7 @@ type TestNode struct {
}
type TestStorageNode struct {
api.StorageMiner
lapi.StorageMiner
// ListenAddr is the address on which an API server is listening, if an
// API server is created for this Node
ListenAddr multiaddr.Multiaddr
@ -200,9 +201,9 @@ var MineNext = miner.MineReq{
}
func (ts *testSuite) testVersion(t *testing.T) {
api.RunningNodeType = api.NodeFull
lapi.RunningNodeType = lapi.NodeFull
t.Cleanup(func() {
api.RunningNodeType = api.NodeUnknown
lapi.RunningNodeType = lapi.NodeUnknown
})
ctx := context.Background()
@ -244,7 +245,7 @@ func (ts *testSuite) testSearchMsg(t *testing.T) {
if err != nil {
t.Fatal(err)
}
res, err := api.StateWaitMsg(ctx, sm.Cid(), 1)
res, err := api.StateWaitMsg(ctx, sm.Cid(), 1, lapi.LookbackNoLimit, true)
if err != nil {
t.Fatal(err)
}
@ -252,7 +253,7 @@ func (ts *testSuite) testSearchMsg(t *testing.T) {
t.Fatal("did not successfully send message")
}
searchRes, err := api.StateSearchMsg(ctx, sm.Cid())
searchRes, err := api.StateSearchMsg(ctx, types.EmptyTSK, sm.Cid(), lapi.LookbackNoLimit, true)
if err != nil {
t.Fatal(err)
}

View File

@ -8,6 +8,7 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-address"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/miner"
)
@ -28,7 +29,7 @@ func SendFunds(ctx context.Context, t *testing.T, sender TestNode, addr address.
if err != nil {
t.Fatal(err)
}
res, err := sender.StateWaitMsg(ctx, sm.Cid(), 1)
res, err := sender.StateWaitMsg(ctx, sm.Cid(), 1, lapi.LookbackNoLimit, true)
if err != nil {
t.Fatal(err)
}

View File

@ -590,7 +590,7 @@ func TestWindowPostDispute(t *testing.T, b APIBuilder, blocktime time.Duration)
require.NoError(t, err)
fmt.Println("waiting dispute")
rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence)
rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence, api.LookbackNoLimit, true)
require.NoError(t, err)
require.Zero(t, rec.Receipt.ExitCode, "dispute not accepted: %s", rec.Receipt.ExitCode.Error())
}
@ -631,7 +631,7 @@ func TestWindowPostDispute(t *testing.T, b APIBuilder, blocktime time.Duration)
sm, err := client.MpoolPushMessage(ctx, msg, nil)
require.NoError(t, err)
rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence)
rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence, api.LookbackNoLimit, true)
require.NoError(t, err)
require.Zero(t, rec.Receipt.ExitCode, "recovery not accepted: %s", rec.Receipt.ExitCode.Error())
}
@ -710,7 +710,7 @@ func submitBadProof(
return err
}
rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence)
rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence, api.LookbackNoLimit, true)
if err != nil {
return err
}

701
api/v0api/full.go Normal file
View File

@ -0,0 +1,701 @@
package v0api
import (
"context"
"github.com/filecoin-project/go-address"
"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/storagemarket"
"github.com/filecoin-project/go-multistore"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/lotus/api"
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/paych"
"github.com/filecoin-project/lotus/chain/types"
marketevents "github.com/filecoin-project/lotus/markets/loggers"
"github.com/filecoin-project/lotus/node/modules/dtypes"
)
//go:generate go run github.com/golang/mock/mockgen -destination=v0mocks/mock_full.go -package=v0mocks . FullNode
// MODIFYING THE API INTERFACE
//
// NOTE: This is the V0 (Stable) API - when adding methods to this interface,
// you'll need to make sure they are also present on the V1 (Unstable) API
//
// This API is implemented in `v1_wrapper.go` as a compatibility layer backed
// by the V1 api
//
// When adding / changing methods in this file:
// * Do the change here
// * Adjust implementation in `node/impl/`
// * Run `make gen` - this will:
// * Generate proxy structs
// * Generate mocks
// * Generate markdown docs
// * Generate openrpc blobs
// FullNode API is a low-level interface to the Filecoin network full node
type FullNode interface {
Common
// MethodGroup: Chain
// The Chain method group contains methods for interacting with the
// blockchain, but that do not require any form of state computation.
// ChainNotify returns channel with chain head updates.
// First message is guaranteed to be of len == 1, and type == 'current'.
ChainNotify(context.Context) (<-chan []*api.HeadChange, error) //perm:read
// ChainHead returns the current head of the chain.
ChainHead(context.Context) (*types.TipSet, error) //perm:read
// 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) //perm:read
// 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) //perm:read
// ChainGetBlock returns the block specified by the given CID.
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error) //perm:read
// ChainGetTipSet returns the tipset specified by the given TipSetKey.
ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error) //perm:read
// 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
ChainGetBlockMessages(ctx context.Context, blockCid cid.Cid) (*api.BlockMessages, error) //perm:read
// ChainGetParentReceipts returns receipts for messages in parent tipset of
// 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.
ChainGetParentReceipts(ctx context.Context, blockCid cid.Cid) ([]*types.MessageReceipt, error) //perm:read
// ChainGetParentMessages returns messages stored in parent tipset of the
// specified block.
ChainGetParentMessages(ctx context.Context, blockCid cid.Cid) ([]api.Message, error) //perm:read
// 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
// will be returned.
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) //perm:read
// ChainReadObj reads ipld nodes referenced by the specified CID from chain
// blockstore and returns raw bytes.
ChainReadObj(context.Context, cid.Cid) ([]byte, error) //perm:read
// ChainDeleteObj deletes node referenced by the given CID
ChainDeleteObj(context.Context, cid.Cid) error //perm:admin
// ChainHasObj checks if a given CID exists in the chain blockstore.
ChainHasObj(context.Context, cid.Cid) (bool, error) //perm:read
// ChainStatObj returns statistics about the graph referenced by 'obj'.
// If 'base' is also specified, then the returned stat will be a diff
// between the two objects.
ChainStatObj(ctx context.Context, obj cid.Cid, base cid.Cid) (api.ObjStat, error) //perm:read
// ChainSetHead forcefully sets current chain head. Use with caution.
ChainSetHead(context.Context, types.TipSetKey) error //perm:admin
// ChainGetGenesis returns the genesis tipset.
ChainGetGenesis(context.Context) (*types.TipSet, error) //perm:read
// ChainTipSetWeight computes weight for the specified tipset.
ChainTipSetWeight(context.Context, types.TipSetKey) (types.BigInt, error) //perm:read
ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) //perm:read
// ChainGetMessage reads a message referenced by the specified CID from the
// chain blockstore.
ChainGetMessage(context.Context, cid.Cid) (*types.Message, error) //perm:read
// ChainGetPath returns a set of revert/apply operations needed to get from
// one tipset to another, for example:
//```
// to
// ^
// from tAA
// ^ ^
// tBA tAB
// ^---*--^
// ^
// tRR
//```
// Would return `[revert(tBA), apply(tAB), apply(tAA)]`
ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*api.HeadChange, error) //perm:read
// ChainExport returns a stream of bytes with CAR dump of chain data.
// The exported chain data includes the header chain from the given tipset
// back to genesis, the entire genesis state, and the most recent 'nroots'
// state trees.
// 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) //perm:read
// MethodGroup: Beacon
// The Beacon method group contains methods for interacting with the random beacon (DRAND)
// 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
// becomes available
BeaconGetEntry(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) //perm:read
// GasEstimateFeeCap estimates gas fee cap
GasEstimateFeeCap(context.Context, *types.Message, int64, types.TipSetKey) (types.BigInt, error) //perm:read
// GasEstimateGasLimit estimates gas used by the message and returns it.
// It fails if message fails to execute.
GasEstimateGasLimit(context.Context, *types.Message, types.TipSetKey) (int64, error) //perm:read
// GasEstimateGasPremium estimates what gas price should be used for a
// message to have high likelihood of inclusion in `nblocksincl` epochs.
GasEstimateGasPremium(_ context.Context, nblocksincl uint64,
sender address.Address, gaslimit int64, tsk types.TipSetKey) (types.BigInt, error) //perm:read
// GasEstimateMessageGas estimates gas values for unset message gas fields
GasEstimateMessageGas(context.Context, *types.Message, *api.MessageSendSpec, types.TipSetKey) (*types.Message, error) //perm:read
// MethodGroup: Sync
// The Sync method group contains methods for interacting with and
// observing the lotus sync service.
// SyncState returns the current status of the lotus sync system.
SyncState(context.Context) (*api.SyncState, error) //perm:read
// SyncSubmitBlock can be used to submit a newly created block to the.
// network through this node
SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error //perm:write
// SyncIncomingBlocks returns a channel streaming incoming, potentially not
// yet synced block headers.
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(ctx context.Context, tsk types.TipSetKey) error //perm:admin
// SyncMarkBad marks a blocks as bad, meaning that it won't ever by synced.
// Use with extreme caution.
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(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(ctx context.Context) error //perm:admin
// SyncCheckBad checks if a block was marked as bad, and if it was, returns
// the reason.
SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) //perm:read
// SyncValidateTipset indicates whether the provided tipset is valid or not
SyncValidateTipset(ctx context.Context, tsk types.TipSetKey) (bool, error) //perm:read
// MethodGroup: Mpool
// The Mpool methods are for interacting with the message pool. The message pool
// manages all incoming and outgoing 'messages' going over the network.
// MpoolPending returns pending mempool messages.
MpoolPending(context.Context, types.TipSetKey) ([]*types.SignedMessage, error) //perm:read
// MpoolSelect returns a list of pending messages for inclusion in the next block
MpoolSelect(context.Context, types.TipSetKey, float64) ([]*types.SignedMessage, error) //perm:read
// MpoolPush pushes a signed message to mempool.
MpoolPush(context.Context, *types.SignedMessage) (cid.Cid, error) //perm:write
// MpoolPushUntrusted pushes a signed message to mempool from untrusted sources.
MpoolPushUntrusted(context.Context, *types.SignedMessage) (cid.Cid, error) //perm:write
// MpoolPushMessage atomically assigns a nonce, signs, and pushes a message
// to mempool.
// maxFee is only used when GasFeeCap/GasPremium fields aren't specified
//
// When maxFee is set to 0, MpoolPushMessage will guess appropriate fee
// based on current chain conditions
MpoolPushMessage(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec) (*types.SignedMessage, error) //perm:sign
// MpoolBatchPush batch pushes a signed message to mempool.
MpoolBatchPush(context.Context, []*types.SignedMessage) ([]cid.Cid, error) //perm:write
// MpoolBatchPushUntrusted batch pushes a signed message to mempool from untrusted sources.
MpoolBatchPushUntrusted(context.Context, []*types.SignedMessage) ([]cid.Cid, error) //perm:write
// MpoolBatchPushMessage batch pushes a unsigned message to mempool.
MpoolBatchPushMessage(context.Context, []*types.Message, *api.MessageSendSpec) ([]*types.SignedMessage, error) //perm:sign
// MpoolGetNonce gets next nonce for the specified sender.
// Note that this method may not be atomic. Use MpoolPushMessage instead.
MpoolGetNonce(context.Context, address.Address) (uint64, error) //perm:read
MpoolSub(context.Context) (<-chan api.MpoolUpdate, error) //perm:read
// MpoolClear clears pending messages from the mpool
MpoolClear(context.Context, bool) error //perm:write
// MpoolGetConfig returns (a copy of) the current mpool config
MpoolGetConfig(context.Context) (*types.MpoolConfig, error) //perm:read
// MpoolSetConfig sets the mpool config to (a copy of) the supplied config
MpoolSetConfig(context.Context, *types.MpoolConfig) error //perm:admin
// MethodGroup: Miner
MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*api.MiningBaseInfo, error) //perm:read
MinerCreateBlock(context.Context, *api.BlockTemplate) (*types.BlockMsg, error) //perm:write
// // UX ?
// MethodGroup: Wallet
// WalletNew creates a new address in the wallet with the given sigType.
// Available key types: bls, secp256k1, secp256k1-ledger
// Support for numerical types: 1 - secp256k1, 2 - BLS is deprecated
WalletNew(context.Context, types.KeyType) (address.Address, error) //perm:write
// WalletHas indicates whether the given address is in the wallet.
WalletHas(context.Context, address.Address) (bool, error) //perm:write
// WalletList lists all the addresses in the wallet.
WalletList(context.Context) ([]address.Address, error) //perm:write
// WalletBalance returns the balance of the given address at the current head of the chain.
WalletBalance(context.Context, address.Address) (types.BigInt, error) //perm:read
// WalletSign signs the given bytes using the given address.
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error) //perm:sign
// WalletSignMessage signs the given message using the given address.
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.
// The address does not have to be in the wallet.
WalletVerify(context.Context, address.Address, []byte, *crypto.Signature) (bool, error) //perm:read
// WalletDefaultAddress returns the address marked as default in the wallet.
WalletDefaultAddress(context.Context) (address.Address, error) //perm:write
// WalletSetDefault marks the given address as as the default one.
WalletSetDefault(context.Context, address.Address) error //perm:write
// WalletExport returns the private key of an address in the wallet.
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(context.Context, *types.KeyInfo) (address.Address, error) //perm:admin
// WalletDelete deletes an address from the wallet.
WalletDelete(context.Context, address.Address) error //perm:admin
// WalletValidateAddress validates whether a given string can be decoded as a well-formed address
WalletValidateAddress(context.Context, string) (address.Address, error) //perm:read
// Other
// MethodGroup: Client
// The Client methods all have to do with interacting with the storage and
// retrieval markets as a client
// ClientImport imports file under the specified path into filestore.
ClientImport(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) //perm:admin
// ClientRemoveImport removes file import
ClientRemoveImport(ctx context.Context, importID multistore.StoreID) error //perm:admin
// ClientStartDeal proposes a deal with a miner.
ClientStartDeal(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) //perm:admin
// ClientGetDealInfo returns the latest information about a given deal.
ClientGetDealInfo(context.Context, cid.Cid) (*api.DealInfo, error) //perm:read
// ClientListDeals returns information about the deals made by the local client.
ClientListDeals(ctx context.Context) ([]api.DealInfo, error) //perm:write
// ClientGetDealUpdates returns the status of updated deals
ClientGetDealUpdates(ctx context.Context) (<-chan api.DealInfo, error) //perm:write
// ClientGetDealStatus returns status given a code
ClientGetDealStatus(ctx context.Context, statusCode uint64) (string, error) //perm:read
// ClientHasLocal indicates whether a certain CID is locally stored.
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(ctx context.Context, root cid.Cid, piece *cid.Cid) ([]api.QueryOffer, error) //perm:read
// ClientMinerQueryOffer returns a QueryOffer for the specific miner and file.
ClientMinerQueryOffer(ctx context.Context, miner address.Address, root cid.Cid, piece *cid.Cid) (api.QueryOffer, error) //perm:read
// ClientRetrieve initiates the retrieval of a file, as specified in the order.
ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error //perm:admin
// ClientRetrieveWithEvents initiates the retrieval of a file, as specified in the order, and provides a channel
// of status updates.
ClientRetrieveWithEvents(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) (<-chan marketevents.RetrievalEvent, error) //perm:admin
// ClientQueryAsk returns a signed StorageAsk from the specified miner.
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
ClientDealPieceCID(ctx context.Context, root cid.Cid) (api.DataCIDSize, error) //perm:read
// ClientCalcCommP calculates the CommP for a specified file
ClientCalcCommP(ctx context.Context, inpath string) (*api.CommPRet, error) //perm:write
// ClientGenCar generates a CAR file for the specified file.
ClientGenCar(ctx context.Context, ref api.FileRef, outpath string) error //perm:write
// ClientDealSize calculates real deal data size
ClientDealSize(ctx context.Context, root cid.Cid) (api.DataSize, error) //perm:read
// ClientListTransfers returns the status of all ongoing transfers of data
ClientListDataTransfers(ctx context.Context) ([]api.DataTransferChannel, error) //perm:write
ClientDataTransferUpdates(ctx context.Context) (<-chan api.DataTransferChannel, error) //perm:write
// 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 //perm:write
// 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 //perm:write
// ClientRetrieveTryRestartInsufficientFunds attempts to restart stalled retrievals on a given payment channel
// which are stuck due to insufficient funds
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(path string)
// ClientListImports lists imported files and their root CIDs
ClientListImports(ctx context.Context) ([]api.Import, error) //perm:write
//ClientListAsks() []Ask
// MethodGroup: State
// The State methods are used to query, inspect, and interact with chain state.
// Most methods take a TipSetKey as a parameter. The state looked up is the parent state of the tipset.
// A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used.
// StateCall runs the given message and returns its result without any persisted changes.
//
// StateCall applies the message to the tipset's parent state. The
// message is not applied on-top-of the messages in the passed-in
// tipset.
StateCall(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) //perm:read
// StateReplay replays a given message, assuming it was included in a block in the specified tipset.
//
// 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) (*api.InvocResult, error) //perm:read
// StateGetActor returns the indicated actor's nonce and balance.
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) //perm:read
// StateReadState returns the indicated actor's state.
StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) //perm:read
// StateListMessages looks back and returns all messages with a matching to or from address, stopping at the given height.
StateListMessages(ctx context.Context, match *api.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(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(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(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(context.Context, address.Address, types.TipSetKey) ([]*miner.SectorOnChainInfo, error) //perm:read
// StateMinerProvingDeadline calculates the deadline at some epoch for a proving period
// and returns the deadline-related calculations.
StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) //perm:read
// StateMinerPower returns the power of the indicated miner
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) //perm:read
// StateMinerInfo returns info about the indicated miner
StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) //perm:read
// StateMinerDeadlines returns all the proving deadlines for the given miner
StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]api.Deadline, error) //perm:read
// StateMinerPartitions returns all partitions in the specified deadline
StateMinerPartitions(ctx context.Context, m address.Address, dlIdx uint64, tsk types.TipSetKey) ([]api.Partition, error) //perm:read
// StateMinerFaults returns a bitfield indicating the faulty sectors of the given miner
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(ctx context.Context, lookback abi.ChainEpoch, ts types.TipSetKey) ([]*api.Fault, error) //perm:read
// StateMinerRecoveries returns a bitfield indicating the recovering sectors of the given miner
StateMinerRecoveries(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) //perm:read
// StateMinerInitialPledgeCollateral returns the precommit deposit for the specified miner's sector
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(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(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) //perm:read
// StateMinerSectorAllocated checks if a sector is allocated
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(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
// NOTE: returned info.Expiration may not be accurate in some cases, use StateSectorExpiration to get accurate
// expiration epoch
StateSectorGetInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error) //perm:read
// StateSectorExpiration returns epoch at which given sector will expire
StateSectorExpiration(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorExpiration, error) //perm:read
// StateSectorPartition finds deadline/partition with the specified sector
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
//
// NOTE: If a replacing message is found on chain, this method will return
// a MsgLookup for the replacing message - the MsgLookup.Message will be a different
// CID than the one provided in the 'cid' param, MsgLookup.Receipt will contain the
// result of the execution of the replacing message.
//
// If the caller wants to ensure that exactly the requested message was executed,
// they MUST check that MsgLookup.Message 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.)
StateSearchMsg(context.Context, cid.Cid) (*api.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
//
// NOTE: If a replacing message is found on chain, this method will return
// a MsgLookup for the replacing message - the MsgLookup.Message will be a different
// CID than the one provided in the 'cid' param, MsgLookup.Receipt will contain the
// result of the execution of the replacing message.
//
// If the caller wants to ensure that exactly the requested message was executed,
// they MUST check that MsgLookup.Message 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.)
StateSearchMsgLimited(ctx context.Context, msg cid.Cid, limit abi.ChainEpoch) (*api.MsgLookup, error) //perm:read
// 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.
//
// NOTE: If a replacing message is found on chain, this method will return
// a MsgLookup for the replacing message - the MsgLookup.Message will be a different
// CID than the one provided in the 'cid' param, MsgLookup.Receipt will contain the
// result of the execution of the replacing message.
//
// If the caller wants to ensure that exactly the requested message was executed,
// they MUST check that MsgLookup.Message 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.)
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) //perm:read
// 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
// indicated confidence depth.
//
// NOTE: If a replacing message is found on chain, this method will return
// a MsgLookup for the replacing message - the MsgLookup.Message will be a different
// CID than the one provided in the 'cid' param, MsgLookup.Receipt will contain the
// result of the execution of the replacing message.
//
// If the caller wants to ensure that exactly the requested message was executed,
// they MUST check that MsgLookup.Message 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.)
StateWaitMsgLimited(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch) (*api.MsgLookup, error) //perm:read
// StateListMiners returns the addresses of every miner that has claimed power in the Power Actor
StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error) //perm:read
// StateListActors returns the addresses of every actor in the state
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(context.Context, address.Address, types.TipSetKey) (api.MarketBalance, error) //perm:read
// StateMarketParticipants returns the Escrow and Locked balances of every participant in the Storage Market
StateMarketParticipants(context.Context, types.TipSetKey) (map[string]api.MarketBalance, error) //perm:read
// StateMarketDeals returns information about every deal in the Storage Market
StateMarketDeals(context.Context, types.TipSetKey) (map[string]api.MarketDeal, error) //perm:read
// StateMarketStorageDeal returns information about the indicated deal
StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error) //perm:read
// StateLookupID retrieves the ID address of the given address
StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error) //perm:read
// StateAccountKey returns the public key address of the given ID address
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
// TODO: Should this take tipset keys instead?
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
// matching gas-repriced replacing message
//
// 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
// requested message, use StateSearchMsg().Receipt, and check that MsgLookup.Message
// is matching the requested CID
//
// DEPRECATED: Use StateSearchMsg, this method won't be supported in v1 API
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(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) //perm:read
// 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.
//
// 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) (*api.ComputeStateOutput, error) //perm:read
// StateVerifierStatus returns the data cap for the given address.
// Returns nil if there is no entry in the data cap table for the
// address.
StateVerifierStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) //perm:read
// StateVerifiedClientStatus returns the data cap for the given address.
// Returns nil if there is no entry in the data cap table for the
// address.
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
StateVerifiedRegistryRootKey(ctx context.Context, tsk types.TipSetKey) (address.Address, error) //perm:read
// StateDealProviderCollateralBounds returns the min and max collateral a storage provider
// can issue. It takes the deal size and verified status as parameters.
StateDealProviderCollateralBounds(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (api.DealCollateralBounds, error) //perm:read
// 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.
StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error) //perm:read
// 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.
StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error) //perm:read
// StateNetworkVersion returns the network version at the given tipset
StateNetworkVersion(context.Context, types.TipSetKey) (apitypes.NetworkVersion, error) //perm:read
// MethodGroup: Msig
// The Msig methods are used to interact with multisig wallets on the
// filecoin network
// 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) //perm:read
// MsigGetVestingSchedule returns the vesting details of a given multisig.
MsigGetVestingSchedule(context.Context, address.Address, types.TipSetKey) (api.MsigVesting, error) //perm:read
// 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>
MsigGetVested(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) //perm:read
//MsigGetPending returns pending transactions for the given multisig
//wallet. Once pending transactions are fully approved, they will no longer
//appear here.
MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*api.MsigTransaction, error) //perm:read
// MsigCreate creates a multisig wallet
// It takes the following params: <required number of senders>, <approving addresses>, <unlock duration>
//<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) //perm:sign
// MsigPropose proposes a multisig message
// 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>
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
// It takes the following params: <multisig address>, <proposed transaction ID> <signer address>
MsigApprove(context.Context, address.Address, uint64, address.Address) (cid.Cid, error) //perm:sign
// MsigApproveTxnHash approves a previously-proposed multisig message, specified
// using both transaction ID and a hash of the parameters used in the
// proposal. This method of approval can be used to ensure you only approve
// exactly the transaction you think you are.
// 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>
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
// 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>
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
// It takes the following params: <multisig address>, <sender address of the propose msg>,
// <new signer>, <whether the number of required signers should be increased>
MsigAddPropose(context.Context, address.Address, address.Address, address.Address, bool) (cid.Cid, error) //perm:sign
// MsigAddApprove approves a previously proposed AddSigner message
// 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>
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
// 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>
MsigAddCancel(context.Context, address.Address, address.Address, uint64, address.Address, bool) (cid.Cid, error) //perm:sign
// MsigSwapPropose proposes swapping 2 signers in the multisig
// It takes the following params: <multisig address>, <sender address of the propose msg>,
// <old signer>, <new signer>
MsigSwapPropose(context.Context, address.Address, address.Address, address.Address, address.Address) (cid.Cid, error) //perm:sign
// MsigSwapApprove approves a previously proposed SwapSigner
// It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
// <proposer address>, <old signer>, <new signer>
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
// It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
// <old signer>, <new signer>
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.
// 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
// indicating whether or not the signing threshold should be lowered by one
// along with the address removal.
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(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(ctx context.Context, addr address.Address) (types.BigInt, error) //perm:sign
// MarketReserveFunds reserves funds for a deal
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(ctx context.Context, addr address.Address, amt types.BigInt) error //perm:sign
// MarketWithdraw withdraws unlocked funds from the market actor
MarketWithdraw(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) //perm:sign
// MethodGroup: Paych
// The Paych methods are for interacting with and managing payment channels
PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) //perm:sign
PaychGetWaitReady(context.Context, cid.Cid) (address.Address, error) //perm:sign
PaychAvailableFunds(ctx context.Context, ch address.Address) (*api.ChannelAvailableFunds, error) //perm:sign
PaychAvailableFundsByFromTo(ctx context.Context, from, to address.Address) (*api.ChannelAvailableFunds, error) //perm:sign
PaychList(context.Context) ([]address.Address, error) //perm:read
PaychStatus(context.Context, address.Address) (*api.PaychStatus, error) //perm:read
PaychSettle(context.Context, address.Address) (cid.Cid, error) //perm:sign
PaychCollect(context.Context, address.Address) (cid.Cid, error) //perm:sign
PaychAllocateLane(ctx context.Context, ch address.Address) (uint64, error) //perm:sign
PaychNewPayment(ctx context.Context, from, to address.Address, vouchers []api.VoucherSpec) (*api.PaymentInfo, error) //perm:sign
PaychVoucherCheckValid(context.Context, address.Address, *paych.SignedVoucher) error //perm:read
PaychVoucherCheckSpendable(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (bool, error) //perm:read
PaychVoucherCreate(context.Context, address.Address, types.BigInt, uint64) (*api.VoucherCreateResult, error) //perm:sign
PaychVoucherAdd(context.Context, address.Address, *paych.SignedVoucher, []byte, types.BigInt) (types.BigInt, error) //perm:write
PaychVoucherList(context.Context, address.Address) ([]*paych.SignedVoucher, error) //perm:write
PaychVoucherSubmit(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (cid.Cid, error) //perm:sign
// CreateBackup creates node backup onder the specified file name. The
// method requires that the lotus daemon is running with the
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
// the path specified when calling CreateBackup is within the base path
CreateBackup(ctx context.Context, fpath string) error //perm:admin
}

68
api/v0api/gateway.go Normal file
View File

@ -0,0 +1,68 @@
package v0api
import (
"context"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types"
)
// MODIFYING THE API INTERFACE
//
// NOTE: This is the V0 (Stable) API - when adding methods to this interface,
// you'll need to make sure they are also present on the V1 (Unstable) API
//
// This API is implemented in `v1_wrapper.go` as a compatibility layer backed
// by the V1 api
//
// When adding / changing methods in this file:
// * Do the change here
// * Adjust implementation in `node/impl/`
// * Run `make gen` - this will:
// * Generate proxy structs
// * Generate mocks
// * Generate markdown docs
// * Generate openrpc blobs
type Gateway interface {
ChainHasObj(context.Context, cid.Cid) (bool, error)
ChainHead(ctx context.Context) (*types.TipSet, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error)
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
ChainNotify(context.Context) (<-chan []*api.HeadChange, error)
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*api.MsigTransaction, error)
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error)
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error)
StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error)
StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error)
StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error)
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
StateSearchMsg(ctx context.Context, msg cid.Cid) (*api.MsgLookup, 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)
StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
WalletBalance(context.Context, address.Address) (types.BigInt, error)
}
var _ Gateway = *new(FullNode)

25
api/v0api/latest.go Normal file
View File

@ -0,0 +1,25 @@
package v0api
import (
"github.com/filecoin-project/lotus/api"
)
type Common = api.Common
type CommonStruct = api.CommonStruct
type CommonStub = api.CommonStub
type StorageMiner = api.StorageMiner
type StorageMinerStruct = api.StorageMinerStruct
type Worker = api.Worker
type WorkerStruct = api.WorkerStruct
type Wallet = api.Wallet
func PermissionedStorMinerAPI(a StorageMiner) StorageMiner {
return api.PermissionedStorMinerAPI(a)
}
func PermissionedWorkerAPI(a Worker) Worker {
return api.PermissionedWorkerAPI(a)
}

13
api/v0api/permissioned.go Normal file
View File

@ -0,0 +1,13 @@
package v0api
import (
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/api"
)
func PermissionedFullAPI(a FullNode) FullNode {
var out FullNodeStruct
auth.PermissionedProxy(api.AllPermissions, api.DefaultPerms, a, &out.Internal)
auth.PermissionedProxy(api.AllPermissions, api.DefaultPerms, a, &out.CommonStruct.Internal)
return &out
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

60
api/v0api/v1_wrapper.go Normal file
View File

@ -0,0 +1,60 @@
package v0api
import (
"context"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v1api"
)
type WrapperV1Full struct {
v1api.FullNode
}
func (w *WrapperV1Full) StateSearchMsg(ctx context.Context, msg cid.Cid) (*api.MsgLookup, error) {
return w.FullNode.StateSearchMsg(ctx, types.EmptyTSK, msg, api.LookbackNoLimit, true)
}
func (w *WrapperV1Full) StateSearchMsgLimited(ctx context.Context, msg cid.Cid, limit abi.ChainEpoch) (*api.MsgLookup, error) {
return w.FullNode.StateSearchMsg(ctx, types.EmptyTSK, msg, limit, true)
}
func (w *WrapperV1Full) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
return w.FullNode.StateWaitMsg(ctx, msg, confidence, api.LookbackNoLimit, true)
}
func (w *WrapperV1Full) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, limit abi.ChainEpoch) (*api.MsgLookup, error) {
return w.FullNode.StateWaitMsg(ctx, msg, confidence, limit, true)
}
func (w *WrapperV1Full) StateGetReceipt(ctx context.Context, msg cid.Cid, from types.TipSetKey) (*types.MessageReceipt, error) {
ml, err := w.FullNode.StateSearchMsg(ctx, from, msg, api.LookbackNoLimit, true)
if err != nil {
return nil, err
}
if ml == nil {
return nil, nil
}
return &ml.Receipt, nil
}
func (w *WrapperV1Full) Version(ctx context.Context) (api.APIVersion, error) {
ver, err := w.FullNode.Version(ctx)
if err != nil {
return api.APIVersion{}, err
}
ver.APIVersion = api.FullAPIVersion0
return ver, nil
}
var _ FullNode = &WrapperV1Full{}

12
api/v1api/latest.go Normal file
View File

@ -0,0 +1,12 @@
package v1api
import (
"github.com/filecoin-project/lotus/api"
)
type FullNode = api.FullNode
type FullNodeStruct = api.FullNodeStruct
func PermissionedFullAPI(a FullNode) FullNode {
return api.PermissionedFullAPI(a)
}

View File

@ -42,11 +42,11 @@ var RunningNodeType NodeType
func VersionForType(nodeType NodeType) (Version, error) {
switch nodeType {
case NodeFull:
return FullAPIVersion, nil
return FullAPIVersion1, nil
case NodeMiner:
return MinerAPIVersion, nil
return MinerAPIVersion0, nil
case NodeWorker:
return WorkerAPIVersion, nil
return WorkerAPIVersion0, nil
default:
return Version(0), xerrors.Errorf("unknown node type %d", nodeType)
}
@ -54,9 +54,11 @@ func VersionForType(nodeType NodeType) (Version, error) {
// semver versions of the rpc api exposed
var (
FullAPIVersion = newVer(1, 2, 0)
MinerAPIVersion = newVer(1, 0, 1)
WorkerAPIVersion = newVer(1, 0, 0)
FullAPIVersion0 = newVer(1, 3, 0)
FullAPIVersion1 = newVer(2, 1, 0)
MinerAPIVersion0 = newVer(1, 0, 1)
WorkerAPIVersion0 = newVer(1, 0, 0)
)
//nolint:varcheck,deadcode

32
api/wrap.go Normal file
View File

@ -0,0 +1,32 @@
package api
import (
"reflect"
)
// Wrap adapts partial api impl to another version
// proxyT is the proxy type used as input in wrapperT
// Usage: Wrap(new(v1api.FullNodeStruct), new(v0api.WrapperV1Full), eventsApi).(EventAPI)
func Wrap(proxyT, wrapperT, impl interface{}) interface{} {
proxy := reflect.New(reflect.TypeOf(proxyT).Elem())
proxyMethods := proxy.Elem().FieldByName("Internal")
ri := reflect.ValueOf(impl)
for i := 0; i < ri.NumMethod(); i++ {
mt := ri.Type().Method(i)
if proxyMethods.FieldByName(mt.Name).Kind() == reflect.Invalid {
continue
}
fn := ri.Method(i)
of := proxyMethods.FieldByName(mt.Name)
proxyMethods.FieldByName(mt.Name).Set(reflect.MakeFunc(of.Type(), func(args []reflect.Value) (results []reflect.Value) {
return fn.Call(args)
}))
}
wp := reflect.New(reflect.TypeOf(wrapperT).Elem())
wp.Elem().Field(0).Set(proxy)
return wp.Interface()
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -33,19 +33,19 @@ type heightHandler struct {
revert RevertHandler
}
type eventAPI interface {
type EventAPI interface {
ChainNotify(context.Context) (<-chan []*api.HeadChange, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
ChainHead(context.Context) (*types.TipSet, error)
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error)
ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error)
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // optional / for CalledMsg
}
type Events struct {
api eventAPI
api EventAPI
tsc *tipSetCache
lk sync.Mutex
@ -59,7 +59,7 @@ type Events struct {
observers []TipSetObserver
}
func NewEventsWithConfidence(ctx context.Context, api eventAPI, gcConfidence abi.ChainEpoch) *Events {
func NewEventsWithConfidence(ctx context.Context, api EventAPI, gcConfidence abi.ChainEpoch) *Events {
tsc := newTSCache(gcConfidence, api)
e := &Events{
@ -93,7 +93,7 @@ func NewEventsWithConfidence(ctx context.Context, api eventAPI, gcConfidence abi
return e
}
func NewEvents(ctx context.Context, api eventAPI) *Events {
func NewEvents(ctx context.Context, api EventAPI) *Events {
gcConfidence := 2 * build.ForkLengthThreshold
return NewEventsWithConfidence(ctx, api, gcConfidence)
}

View File

@ -5,6 +5,8 @@ import (
"math"
"sync"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
@ -66,7 +68,7 @@ type queuedEvent struct {
// Manages chain head change events, which may be forward (new tipset added to
// chain) or backward (chain branch discarded in favour of heavier branch)
type hcEvents struct {
cs eventAPI
cs EventAPI
tsc *tipSetCache
ctx context.Context
gcConfidence uint64
@ -93,7 +95,7 @@ type hcEvents struct {
watcherEvents
}
func newHCEvents(ctx context.Context, cs eventAPI, tsc *tipSetCache, gcConfidence uint64) *hcEvents {
func newHCEvents(ctx context.Context, cs EventAPI, tsc *tipSetCache, gcConfidence uint64) *hcEvents {
e := hcEvents{
ctx: ctx,
cs: cs,
@ -355,14 +357,14 @@ type headChangeAPI interface {
// watcherEvents watches for a state change
type watcherEvents struct {
ctx context.Context
cs eventAPI
cs EventAPI
hcAPI headChangeAPI
lk sync.RWMutex
matchers map[triggerID]StateMatchFunc
}
func newWatcherEvents(ctx context.Context, hcAPI headChangeAPI, cs eventAPI) watcherEvents {
func newWatcherEvents(ctx context.Context, hcAPI headChangeAPI, cs EventAPI) watcherEvents {
return watcherEvents{
ctx: ctx,
cs: cs,
@ -457,14 +459,14 @@ func (we *watcherEvents) StateChanged(check CheckFunc, scHnd StateChangeHandler,
// messageEvents watches for message calls to actors
type messageEvents struct {
ctx context.Context
cs eventAPI
cs EventAPI
hcAPI headChangeAPI
lk sync.RWMutex
matchers map[triggerID]MsgMatchFunc
}
func newMessageEvents(ctx context.Context, hcAPI headChangeAPI, cs eventAPI) messageEvents {
func newMessageEvents(ctx context.Context, hcAPI headChangeAPI, cs EventAPI) messageEvents {
return messageEvents{
ctx: ctx,
cs: cs,
@ -585,12 +587,16 @@ func (me *messageEvents) Called(check CheckFunc, msgHnd MsgHandler, rev RevertHa
panic("expected msg")
}
rec, err := me.cs.StateGetReceipt(me.ctx, msg.Cid(), ts.Key())
ml, err := me.cs.StateSearchMsg(me.ctx, ts.Key(), msg.Cid(), stmgr.LookbackNoLimit, true)
if err != nil {
return false, err
}
return msgHnd(msg, rec, ts, height)
if ml == nil {
return msgHnd(msg, nil, ts, height)
}
return msgHnd(msg, &ml.Receipt, ts, height)
}
id, err := me.hcAPI.onHeadChanged(check, hnd, rev, confidence, timeout)

View File

@ -54,7 +54,7 @@ func (fcs *fakeCS) ChainGetTipSet(ctx context.Context, key types.TipSetKey) (*ty
return fcs.tipsets[key], nil
}
func (fcs *fakeCS) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) {
func (fcs *fakeCS) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) {
return nil, nil
}
@ -229,7 +229,7 @@ func (fcs *fakeCS) notifDone() {
fcs.sync.Unlock()
}
var _ eventAPI = &fakeCS{}
var _ EventAPI = &fakeCS{}
func TestAt(t *testing.T) {
fcs := &fakeCS{

View File

@ -3,6 +3,8 @@ package events
import (
"context"
"github.com/filecoin-project/lotus/chain/stmgr"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/types"
@ -22,12 +24,16 @@ func (me *messageEvents) CheckMsg(ctx context.Context, smsg types.ChainMsg, hnd
return false, true, nil
}
rec, err := me.cs.StateGetReceipt(ctx, smsg.VMMessage().Cid(), ts.Key())
ml, err := me.cs.StateSearchMsg(me.ctx, ts.Key(), msg.Cid(), stmgr.LookbackNoLimit, true)
if err != nil {
return false, true, xerrors.Errorf("getting receipt in CheckMsg: %w", err)
}
more, err = hnd(msg, rec, ts, ts.Height())
if ml == nil {
more, err = hnd(msg, nil, ts, ts.Height())
} else {
more, err = hnd(msg, &ml.Receipt, ts, ts.Height())
}
return true, more, err
}

View File

@ -36,7 +36,7 @@ type FundManagerAPI struct {
type fundManagerAPI interface {
MpoolPushMessage(context.Context, *types.Message, *api.MessageSendSpec) (*types.SignedMessage, error)
StateMarketBalance(context.Context, address.Address, types.TipSetKey) (api.MarketBalance, error)
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error)
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error)
}
// FundManager keeps track of funds in a set of addresses
@ -721,6 +721,6 @@ func (env *fundManagerEnvironment) WithdrawFunds(
}
func (env *fundManagerEnvironment) WaitMsg(ctx context.Context, c cid.Cid) error {
_, err := env.api.StateWaitMsg(ctx, c, build.MessageConfidence)
_, err := env.api.StateWaitMsg(ctx, c, build.MessageConfidence, api.LookbackNoLimit, true)
return err
}

View File

@ -793,7 +793,7 @@ func (mapi *mockFundManagerAPI) publish(addr address.Address, amt abi.TokenAmoun
mapi.escrow[addr] = escrow
}
func (mapi *mockFundManagerAPI) StateWaitMsg(ctx context.Context, c cid.Cid, confidence uint64) (*api.MsgLookup, error) {
func (mapi *mockFundManagerAPI) StateWaitMsg(ctx context.Context, c cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) {
res := &api.MsgLookup{
Message: c,
Receipt: types.MessageReceipt{

View File

@ -938,7 +938,7 @@ func (mp *MessagePool) addLocked(ctx context.Context, m *types.SignedMessage, st
return nil
}
func (mp *MessagePool) GetNonce(ctx context.Context, addr address.Address) (uint64, error) {
func (mp *MessagePool) GetNonce(ctx context.Context, addr address.Address, _ types.TipSetKey) (uint64, error) {
mp.curTsLk.Lock()
defer mp.curTsLk.Unlock()

View File

@ -201,7 +201,7 @@ func (tma *testMpoolAPI) ChainComputeBaseFee(ctx context.Context, ts *types.TipS
func assertNonce(t *testing.T, mp *MessagePool, addr address.Address, val uint64) {
t.Helper()
n, err := mp.GetNonce(context.TODO(), addr)
n, err := mp.GetNonce(context.Background(), addr, types.EmptyTSK)
if err != nil {
t.Fatal(err)
}

View File

@ -23,7 +23,7 @@ const dsKeyActorNonce = "ActorNextNonce"
var log = logging.Logger("messagesigner")
type MpoolNonceAPI interface {
GetNonce(context.Context, address.Address) (uint64, error)
GetNonce(context.Context, address.Address, types.TipSetKey) (uint64, error)
}
// MessageSigner keeps track of nonces per address, and increments the nonce
@ -97,7 +97,7 @@ func (ms *MessageSigner) nextNonce(ctx context.Context, addr address.Address) (u
// that have mempool nonces, so first check the mempool for a nonce for
// this address. Note that the mempool returns the actor state's nonce
// by default.
nonce, err := ms.mpool.GetNonce(ctx, addr)
nonce, err := ms.mpool.GetNonce(ctx, addr, types.EmptyTSK)
if err != nil {
return 0, xerrors.Errorf("failed to get nonce from mempool: %w", err)
}

View File

@ -37,7 +37,7 @@ func (mp *mockMpool) setNonce(addr address.Address, nonce uint64) {
mp.nonces[addr] = nonce
}
func (mp *mockMpool) GetNonce(ctx context.Context, addr address.Address) (uint64, error) {
func (mp *mockMpool) GetNonce(_ context.Context, addr address.Address, _ types.TipSetKey) (uint64, error) {
mp.lk.RLock()
defer mp.lk.RUnlock()

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"sync"
"sync/atomic"
"github.com/filecoin-project/lotus/chain/actors/policy"
@ -12,6 +13,7 @@ import (
cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2"
cbg "github.com/whyrusleeping/cbor-gen"
"go.opencensus.io/stats"
"go.opencensus.io/trace"
"golang.org/x/xerrors"
@ -45,9 +47,10 @@ import (
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/metrics"
)
const LookbackNoLimit = abi.ChainEpoch(-1)
const LookbackNoLimit = api.LookbackNoLimit
const ReceiptAmtBitwidth = 3
var log = logging.Logger("statemgr")
@ -293,6 +296,13 @@ func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (c
type ExecCallback func(cid.Cid, *types.Message, *vm.ApplyRet) error
func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEpoch, pstate cid.Cid, bms []store.BlockMessages, epoch abi.ChainEpoch, r vm.Rand, cb ExecCallback, baseFee abi.TokenAmount, ts *types.TipSet) (cid.Cid, cid.Cid, error) {
done := metrics.Timer(ctx, metrics.VMApplyBlocksTotal)
defer done()
partDone := metrics.Timer(ctx, metrics.VMApplyEarly)
defer func() {
partDone()
}()
makeVmWithBaseState := func(base cid.Cid) (*vm.VM, error) {
vmopt := &vm.VMOpts{
@ -316,7 +326,6 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
}
runCron := func(epoch abi.ChainEpoch) error {
cronMsg := &types.Message{
To: cron.Address,
From: builtin.SystemActorAddr,
@ -375,6 +384,9 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
pstate = newState
}
partDone()
partDone = metrics.Timer(ctx, metrics.VMApplyMessages)
var receipts []cbg.CBORMarshaler
processedMsgs := make(map[cid.Cid]struct{})
for _, b := range bms {
@ -439,10 +451,16 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
}
}
partDone()
partDone = metrics.Timer(ctx, metrics.VMApplyCron)
if err := runCron(epoch); err != nil {
return cid.Cid{}, cid.Cid{}, err
}
partDone()
partDone = metrics.Timer(ctx, metrics.VMApplyFlush)
rectarr := blockadt.MakeEmptyArray(sm.cs.ActorStore(ctx))
for i, receipt := range receipts {
if err := rectarr.Set(uint64(i), receipt); err != nil {
@ -459,6 +477,9 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
return cid.Undef, cid.Undef, xerrors.Errorf("vm flush failed: %w", err)
}
stats.Record(ctx, metrics.VMSends.M(int64(atomic.LoadUint64(&vm.StatSends))),
metrics.VMApplied.M(int64(atomic.LoadUint64(&vm.StatApplied))))
return st, rectroot, nil
}
@ -623,24 +644,10 @@ func (sm *StateManager) LookupID(ctx context.Context, addr address.Address, ts *
return state.LookupID(addr)
}
func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.TipSet) (*types.MessageReceipt, error) {
m, err := sm.cs.GetCMessage(msg)
if err != nil {
return nil, fmt.Errorf("failed to load message: %w", err)
}
_, r, _, err := sm.searchBackForMsg(ctx, ts, m, LookbackNoLimit)
if err != nil {
return nil, fmt.Errorf("failed to look back through chain for message: %w", err)
}
return r, nil
}
// WaitForMessage blocks until a message appears on chain. It looks backwards in the chain to see if this has already
// happened, with an optional limit to how many epochs it will search. It guarantees that the message has been on
// chain for at least confidence epochs without being reverted before returning.
func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confidence uint64, lookbackLimit abi.ChainEpoch) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confidence uint64, lookbackLimit abi.ChainEpoch, allowReplaced bool) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
@ -664,7 +671,7 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confid
return nil, nil, cid.Undef, fmt.Errorf("expected current head on SHC stream (got %s)", head[0].Type)
}
r, foundMsg, err := sm.tipsetExecutedMessage(head[0].Val, mcid, msg.VMMessage())
r, foundMsg, err := sm.tipsetExecutedMessage(head[0].Val, mcid, msg.VMMessage(), allowReplaced)
if err != nil {
return nil, nil, cid.Undef, err
}
@ -678,7 +685,7 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confid
var backFm cid.Cid
backSearchWait := make(chan struct{})
go func() {
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head[0].Val, msg, lookbackLimit)
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head[0].Val, msg, lookbackLimit, allowReplaced)
if err != nil {
log.Warnf("failed to look back through chain for message: %v", err)
return
@ -717,7 +724,7 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confid
if candidateTs != nil && val.Val.Height() >= candidateTs.Height()+abi.ChainEpoch(confidence) {
return candidateTs, candidateRcp, candidateFm, nil
}
r, foundMsg, err := sm.tipsetExecutedMessage(val.Val, mcid, msg.VMMessage())
r, foundMsg, err := sm.tipsetExecutedMessage(val.Val, mcid, msg.VMMessage(), allowReplaced)
if err != nil {
return nil, nil, cid.Undef, err
}
@ -753,15 +760,13 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confid
}
}
func (sm *StateManager) SearchForMessage(ctx context.Context, mcid cid.Cid, lookbackLimit abi.ChainEpoch) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
func (sm *StateManager) SearchForMessage(ctx context.Context, head *types.TipSet, mcid cid.Cid, lookbackLimit abi.ChainEpoch, allowReplaced bool) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
msg, err := sm.cs.GetCMessage(mcid)
if err != nil {
return nil, nil, cid.Undef, fmt.Errorf("failed to load message: %w", err)
}
head := sm.cs.GetHeaviestTipSet()
r, foundMsg, err := sm.tipsetExecutedMessage(head, mcid, msg.VMMessage())
r, foundMsg, err := sm.tipsetExecutedMessage(head, mcid, msg.VMMessage(), allowReplaced)
if err != nil {
return nil, nil, cid.Undef, err
}
@ -770,7 +775,7 @@ func (sm *StateManager) SearchForMessage(ctx context.Context, mcid cid.Cid, look
return head, r, foundMsg, nil
}
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head, msg, lookbackLimit)
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head, msg, lookbackLimit, allowReplaced)
if err != nil {
log.Warnf("failed to look back through chain for message %s", mcid)
@ -790,7 +795,7 @@ func (sm *StateManager) SearchForMessage(ctx context.Context, mcid cid.Cid, look
// - 0 then no tipsets are searched
// - 5 then five tipset are searched
// - LookbackNoLimit then there is no limit
func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet, m types.ChainMsg, limit abi.ChainEpoch) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet, m types.ChainMsg, limit abi.ChainEpoch, allowReplaced bool) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
limitHeight := from.Height() - limit
noLimit := limit == LookbackNoLimit
@ -840,7 +845,7 @@ func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet
// check that between cur and parent tipset the nonce fell into range of our message
if actorNoExist || (curActor.Nonce > mNonce && act.Nonce <= mNonce) {
r, foundMsg, err := sm.tipsetExecutedMessage(cur, m.Cid(), m.VMMessage())
r, foundMsg, err := sm.tipsetExecutedMessage(cur, m.Cid(), m.VMMessage(), allowReplaced)
if err != nil {
return nil, nil, cid.Undef, xerrors.Errorf("checking for message execution during lookback: %w", err)
}
@ -855,7 +860,7 @@ func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet
}
}
func (sm *StateManager) tipsetExecutedMessage(ts *types.TipSet, msg cid.Cid, vmm *types.Message) (*types.MessageReceipt, cid.Cid, error) {
func (sm *StateManager) tipsetExecutedMessage(ts *types.TipSet, msg cid.Cid, vmm *types.Message, allowReplaced bool) (*types.MessageReceipt, cid.Cid, error) {
// The genesis block did not execute any messages
if ts.Height() == 0 {
return nil, cid.Undef, nil
@ -878,7 +883,7 @@ func (sm *StateManager) tipsetExecutedMessage(ts *types.TipSet, msg cid.Cid, vmm
if m.VMMessage().From == vmm.From { // cheaper to just check origin first
if m.VMMessage().Nonce == vmm.Nonce {
if m.VMMessage().EqualCall(vmm) {
if allowReplaced && m.VMMessage().EqualCall(vmm) {
if m.Cid() != msg {
log.Warnw("found message with equal nonce and call params but different CID",
"wanted", msg, "found", m.Cid(), "nonce", vmm.Nonce, "from", vmm.From)
@ -1354,11 +1359,12 @@ func (sm *StateManager) GetVMCirculatingSupplyDetailed(ctx context.Context, heig
}
return api.CirculatingSupply{
FilVested: filVested,
FilMined: filMined,
FilBurnt: filBurnt,
FilLocked: filLocked,
FilCirculating: ret,
FilVested: filVested,
FilMined: filMined,
FilBurnt: filBurnt,
FilLocked: filLocked,
FilCirculating: ret,
FilReserveDisbursed: filReserveDisbursed,
}, nil
}

View File

@ -676,17 +676,17 @@ func TestDuplicateNonce(t *testing.T) {
var includedMsg cid.Cid
var skippedMsg cid.Cid
r0, err0 := tu.nds[0].StateGetReceipt(context.TODO(), msgs[0][0].Cid(), ts2.TipSet().Key())
r1, err1 := tu.nds[0].StateGetReceipt(context.TODO(), msgs[1][0].Cid(), ts2.TipSet().Key())
r0, err0 := tu.nds[0].StateSearchMsg(context.TODO(), ts2.TipSet().Key(), msgs[0][0].Cid(), api.LookbackNoLimit, true)
r1, err1 := tu.nds[0].StateSearchMsg(context.TODO(), ts2.TipSet().Key(), msgs[1][0].Cid(), api.LookbackNoLimit, true)
if err0 == nil {
require.Error(t, err1, "at least one of the StateGetReceipt calls should fail")
require.True(t, r0.ExitCode.IsSuccess())
require.True(t, r0.Receipt.ExitCode.IsSuccess())
includedMsg = msgs[0][0].Message.Cid()
skippedMsg = msgs[1][0].Message.Cid()
} else {
require.NoError(t, err1, "both the StateGetReceipt calls should not fail")
require.True(t, r1.ExitCode.IsSuccess())
require.True(t, r1.Receipt.ExitCode.IsSuccess())
includedMsg = msgs[1][0].Message.Cid()
skippedMsg = msgs[0][0].Message.Cid()
}
@ -916,6 +916,8 @@ func TestSyncInputs(t *testing.T) {
}
func TestSyncCheckpointHead(t *testing.T) {
t.Skip("flaky")
H := 10
tu := prepSyncTest(t, H)
@ -958,6 +960,8 @@ func TestSyncCheckpointHead(t *testing.T) {
}
func TestSyncCheckpointEarlierThanHead(t *testing.T) {
t.Skip("flaky")
H := 10
tu := prepSyncTest(t, H)

View File

@ -20,12 +20,12 @@ func SetupRemoteWallet(info string) func(mctx helpers.MetricsCtx, lc fx.Lifecycl
return func(mctx helpers.MetricsCtx, lc fx.Lifecycle) (*RemoteWallet, error) {
ai := cliutil.ParseApiInfo(info)
url, err := ai.DialArgs()
url, err := ai.DialArgs("v0")
if err != nil {
return nil, err
}
wapi, closer, err := client.NewWalletRPC(mctx, url, ai.AuthHeader())
wapi, closer, err := client.NewWalletRPCV0(mctx, url, ai.AuthHeader())
if err != nil {
return nil, xerrors.Errorf("creating jsonrpc client: %w", err)
}

View File

@ -8,7 +8,7 @@ import (
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/api"
cliutil "github.com/filecoin-project/lotus/cli/util"
"github.com/filecoin-project/lotus/node/repo"
)
@ -47,18 +47,18 @@ var AuthCreateAdminToken = &cli.Command{
perm := cctx.String("perm")
idx := 0
for i, p := range apistruct.AllPermissions {
for i, p := range api.AllPermissions {
if auth.Permission(perm) == p {
idx = i + 1
}
}
if idx == 0 {
return fmt.Errorf("--perm flag has to be one of: %s", apistruct.AllPermissions)
return fmt.Errorf("--perm flag has to be one of: %s", api.AllPermissions)
}
// slice on [:idx] so for example: 'sign' gives you [read, write, sign]
token, err := napi.AuthNew(ctx, apistruct.AllPermissions[:idx])
token, err := napi.AuthNew(ctx, api.AllPermissions[:idx])
if err != nil {
return err
}
@ -95,18 +95,18 @@ var AuthApiInfoToken = &cli.Command{
perm := cctx.String("perm")
idx := 0
for i, p := range apistruct.AllPermissions {
for i, p := range api.AllPermissions {
if auth.Permission(perm) == p {
idx = i + 1
}
}
if idx == 0 {
return fmt.Errorf("--perm flag has to be one of: %s", apistruct.AllPermissions)
return fmt.Errorf("--perm flag has to be one of: %s", api.AllPermissions)
}
// slice on [:idx] so for example: 'sign' gives you [read, write, sign]
token, err := napi.AuthNew(ctx, apistruct.AllPermissions[:idx])
token, err := napi.AuthNew(ctx, api.AllPermissions[:idx])
if err != nil {
return err
}

View File

@ -32,6 +32,7 @@ import (
"golang.org/x/xerrors"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/stmgr"
@ -806,7 +807,7 @@ var ChainGetCmd = &cli.Command{
type apiIpldStore struct {
ctx context.Context
api lapi.FullNode
api v0api.FullNode
}
func (ht *apiIpldStore) Context() context.Context {
@ -834,7 +835,7 @@ func (ht *apiIpldStore) Put(ctx context.Context, v interface{}) (cid.Cid, error)
panic("No mutations allowed")
}
func handleAmt(ctx context.Context, api lapi.FullNode, r cid.Cid) error {
func handleAmt(ctx context.Context, api v0api.FullNode, r cid.Cid) error {
s := &apiIpldStore{ctx, api}
mp, err := adt.AsArray(s, r)
if err != nil {
@ -847,7 +848,7 @@ func handleAmt(ctx context.Context, api lapi.FullNode, r cid.Cid) error {
})
}
func handleHamtEpoch(ctx context.Context, api lapi.FullNode, r cid.Cid) error {
func handleHamtEpoch(ctx context.Context, api v0api.FullNode, r cid.Cid) error {
s := &apiIpldStore{ctx, api}
mp, err := adt.AsMap(s, r)
if err != nil {
@ -865,7 +866,7 @@ func handleHamtEpoch(ctx context.Context, api lapi.FullNode, r cid.Cid) error {
})
}
func handleHamtAddress(ctx context.Context, api lapi.FullNode, r cid.Cid) error {
func handleHamtAddress(ctx context.Context, api v0api.FullNode, r cid.Cid) error {
s := &apiIpldStore{ctx, api}
mp, err := adt.AsMap(s, r)
if err != nil {

View File

@ -40,6 +40,7 @@ import (
"github.com/filecoin-project/lotus/api"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
@ -1348,7 +1349,7 @@ type QueriedAsk struct {
Ping time.Duration
}
func GetAsks(ctx context.Context, api lapi.FullNode) ([]QueriedAsk, error) {
func GetAsks(ctx context.Context, api v0api.FullNode) ([]QueriedAsk, error) {
isTTY := true
if fileInfo, _ := os.Stdout.Stat(); (fileInfo.Mode() & os.ModeCharDevice) == 0 {
isTTY = false
@ -1655,7 +1656,7 @@ var clientListDeals = &cli.Command{
},
}
func dealFromDealInfo(ctx context.Context, full api.FullNode, head *types.TipSet, v api.DealInfo) deal {
func dealFromDealInfo(ctx context.Context, full v0api.FullNode, head *types.TipSet, v api.DealInfo) deal {
if v.DealID == 0 {
return deal{
LocalDeal: v,
@ -1674,7 +1675,7 @@ func dealFromDealInfo(ctx context.Context, full api.FullNode, head *types.TipSet
}
}
func outputStorageDeals(ctx context.Context, out io.Writer, full lapi.FullNode, localDeals []lapi.DealInfo, verbose bool, color bool, showFailed bool) error {
func outputStorageDeals(ctx context.Context, out io.Writer, full v0api.FullNode, localDeals []lapi.DealInfo, verbose bool, color bool, showFailed bool) error {
sort.Slice(localDeals, func(i, j int) bool {
return localDeals[i].CreationTime.Before(localDeals[j].CreationTime)
})
@ -2293,7 +2294,7 @@ func ellipsis(s string, length int) string {
return s
}
func inspectDealCmd(ctx context.Context, api lapi.FullNode, proposalCid string, dealId int) error {
func inspectDealCmd(ctx context.Context, api v0api.FullNode, proposalCid string, dealId int) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
@ -2346,7 +2347,7 @@ func renderDeal(di *lapi.DealInfo) {
}
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))
msg := fmt.Sprintf("%s %s: %s (expected duration: %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)
}

View File

@ -50,6 +50,7 @@ var DaemonContext = cliutil.DaemonContext
var ReqContext = cliutil.ReqContext
var GetFullNodeAPI = cliutil.GetFullNodeAPI
var GetFullNodeAPIV1 = cliutil.GetFullNodeAPIV1
var GetGatewayAPI = cliutil.GetGatewayAPI
var GetStorageMinerAPI = cliutil.GetStorageMinerAPI

View File

@ -22,6 +22,7 @@ import (
logging "github.com/ipfs/go-log/v2"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/chain/store"
"github.com/urfave/cli/v2"
)
@ -356,7 +357,7 @@ var disputerStartCmd = &cli.Command{
// for a given miner, index, and maxPostIndex, tries to dispute posts from 0...postsSnapshotted-1
// returns a list of DisputeWindowedPoSt msgs that are expected to succeed if sent
func makeDisputeWindowedPosts(ctx context.Context, api lapi.FullNode, dl minerDeadline, postsSnapshotted uint64, sender address.Address) ([]*types.Message, error) {
func makeDisputeWindowedPosts(ctx context.Context, api v0api.FullNode, dl minerDeadline, postsSnapshotted uint64, sender address.Address) ([]*types.Message, error) {
disputes := make([]*types.Message, 0)
for i := uint64(0); i < postsSnapshotted; i++ {
@ -388,7 +389,7 @@ func makeDisputeWindowedPosts(ctx context.Context, api lapi.FullNode, dl minerDe
return disputes, nil
}
func makeMinerDeadline(ctx context.Context, api lapi.FullNode, mAddr address.Address) (abi.ChainEpoch, *minerDeadline, error) {
func makeMinerDeadline(ctx context.Context, api v0api.FullNode, mAddr address.Address) (abi.ChainEpoch, *minerDeadline, error) {
dl, err := api.StateMinerProvingDeadline(ctx, mAddr, types.EmptyTSK)
if err != nil {
return -1, nil, xerrors.Errorf("getting proving index list: %w", err)
@ -400,7 +401,7 @@ func makeMinerDeadline(ctx context.Context, api lapi.FullNode, mAddr address.Add
}, nil
}
func getSender(ctx context.Context, api lapi.FullNode, fromStr string) (address.Address, error) {
func getSender(ctx context.Context, api v0api.FullNode, fromStr string) (address.Address, error) {
if fromStr == "" {
return api.WalletDefaultAddress(ctx)
}

View File

@ -4,7 +4,7 @@ import (
"context"
"fmt"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
verifreg4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg"
@ -254,7 +254,7 @@ var filplusCheckNotaryCmd = &cli.Command{
},
}
func checkNotary(ctx context.Context, api api.FullNode, vaddr address.Address) (bool, abi.StoragePower, error) {
func checkNotary(ctx context.Context, api v0api.FullNode, vaddr address.Address) (bool, abi.StoragePower, error) {
vid, err := api.StateLookupID(ctx, vaddr, types.EmptyTSK)
if err != nil {
return false, big.Zero(), err

View File

@ -11,7 +11,7 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/chain/stmgr"
types "github.com/filecoin-project/lotus/chain/types"
cid "github.com/ipfs/go-cid"
@ -35,7 +35,7 @@ type ServicesAPI interface {
}
type ServicesImpl struct {
api api.FullNode
api v0api.FullNode
closer jsonrpc.ClientCloser
}

View File

@ -9,7 +9,7 @@ import (
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/mocks"
mocks "github.com/filecoin-project/lotus/api/v0api/v0mocks"
types "github.com/filecoin-project/lotus/chain/types"
gomock "github.com/golang/mock/gomock"
cid "github.com/ipfs/go-cid"

View File

@ -15,6 +15,8 @@ import (
"strings"
"time"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/fatih/color"
"github.com/filecoin-project/lotus/chain/actors/builtin"
@ -178,7 +180,7 @@ func ParseTipSetString(ts string) ([]cid.Cid, error) {
return cids, nil
}
func LoadTipSet(ctx context.Context, cctx *cli.Context, api api.FullNode) (*types.TipSet, error) {
func LoadTipSet(ctx context.Context, cctx *cli.Context, api v0api.FullNode) (*types.TipSet, error) {
tss := cctx.String("tipset")
if tss == "" {
return nil, nil
@ -187,7 +189,7 @@ func LoadTipSet(ctx context.Context, cctx *cli.Context, api api.FullNode) (*type
return ParseTipSetRef(ctx, api, tss)
}
func ParseTipSetRef(ctx context.Context, api api.FullNode, tss string) (*types.TipSet, error) {
func ParseTipSetRef(ctx context.Context, api v0api.FullNode, tss string) (*types.TipSet, error) {
if tss[0] == '@' {
if tss == "@head" {
return api.ChainHead(ctx)
@ -574,7 +576,7 @@ var StateListMinersCmd = &cli.Command{
},
}
func getDealsCounts(ctx context.Context, lapi api.FullNode) (map[address.Address]int, error) {
func getDealsCounts(ctx context.Context, lapi v0api.FullNode) (map[address.Address]int, error) {
allDeals, err := lapi.StateMarketDeals(ctx, types.EmptyTSK)
if err != nil {
return nil, err
@ -1443,7 +1445,7 @@ var StateSearchMsgCmd = &cli.Command{
},
}
func printReceiptReturn(ctx context.Context, api api.FullNode, m *types.Message, r types.MessageReceipt) error {
func printReceiptReturn(ctx context.Context, api v0api.FullNode, m *types.Message, r types.MessageReceipt) error {
if len(r.Return) == 0 {
return nil
}
@ -1463,8 +1465,7 @@ func printReceiptReturn(ctx context.Context, api api.FullNode, m *types.Message,
return nil
}
func printMsg(ctx context.Context, api api.FullNode, msg cid.Cid, mw *lapi.MsgLookup, m *types.Message) error {
func printMsg(ctx context.Context, api v0api.FullNode, msg cid.Cid, mw *lapi.MsgLookup, m *types.Message) error {
if mw == nil {
fmt.Println("message was not found on chain")
return nil

View File

@ -12,6 +12,7 @@ import (
"github.com/urfave/cli/v2"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/build"
)
@ -240,7 +241,7 @@ var SyncCheckpointCmd = &cli.Command{
},
}
func SyncWait(ctx context.Context, napi api.FullNode, watch bool) error {
func SyncWait(ctx context.Context, napi v0api.FullNode, watch bool) error {
tick := time.Second / 4
lastLines := 0

View File

@ -10,12 +10,12 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
)
func parseTipSet(ctx context.Context, api api.FullNode, vals []string) (*types.TipSet, error) {
func parseTipSet(ctx context.Context, api v0api.FullNode, vals []string) (*types.TipSet, error) {
var headers []*types.BlockHeader
for _, c := range vals {
blkc, err := cid.Decode(c)

View File

@ -18,6 +18,8 @@ import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/client"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/api/v1api"
"github.com/filecoin-project/lotus/node/repo"
)
@ -133,13 +135,13 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) {
}, nil
}
func GetRawAPI(ctx *cli.Context, t repo.RepoType) (string, http.Header, error) {
func GetRawAPI(ctx *cli.Context, t repo.RepoType, version string) (string, http.Header, error) {
ainfo, err := GetAPIInfo(ctx, t)
if err != nil {
return "", nil, xerrors.Errorf("could not get API info: %w", err)
}
addr, err := ainfo.DialArgs()
addr, err := ainfo.DialArgs(version)
if err != nil {
return "", nil, xerrors.Errorf("could not get DialArgs: %w", err)
}
@ -165,25 +167,38 @@ func GetAPI(ctx *cli.Context) (api.Common, jsonrpc.ClientCloser, error) {
return tn.(api.FullNode), func() {}, nil
}
addr, headers, err := GetRawAPI(ctx, t)
addr, headers, err := GetRawAPI(ctx, t, "v0")
if err != nil {
return nil, nil, err
}
return client.NewCommonRPC(ctx.Context, addr, headers)
return client.NewCommonRPCV0(ctx.Context, addr, headers)
}
func GetFullNodeAPI(ctx *cli.Context) (api.FullNode, jsonrpc.ClientCloser, error) {
func GetFullNodeAPI(ctx *cli.Context) (v0api.FullNode, jsonrpc.ClientCloser, error) {
if tn, ok := ctx.App.Metadata["testnode-full"]; ok {
return tn.(api.FullNode), func() {}, nil
return &v0api.WrapperV1Full{FullNode: tn.(v1api.FullNode)}, func() {}, nil
}
addr, headers, err := GetRawAPI(ctx, repo.FullNode)
addr, headers, err := GetRawAPI(ctx, repo.FullNode, "v0")
if err != nil {
return nil, nil, err
}
return client.NewFullNodeRPC(ctx.Context, addr, headers)
return client.NewFullNodeRPCV0(ctx.Context, addr, headers)
}
func GetFullNodeAPIV1(ctx *cli.Context) (v1api.FullNode, jsonrpc.ClientCloser, error) {
if tn, ok := ctx.App.Metadata["testnode-full"]; ok {
return tn.(v1api.FullNode), func() {}, nil
}
addr, headers, err := GetRawAPI(ctx, repo.FullNode, "v1")
if err != nil {
return nil, nil, err
}
return client.NewFullNodeRPCV1(ctx.Context, addr, headers)
}
type GetStorageMinerOptions struct {
@ -206,7 +221,7 @@ func GetStorageMinerAPI(ctx *cli.Context, opts ...GetStorageMinerOption) (api.St
return tn.(api.StorageMiner), func() {}, nil
}
addr, headers, err := GetRawAPI(ctx, repo.StorageMiner)
addr, headers, err := GetRawAPI(ctx, repo.StorageMiner, "v0")
if err != nil {
return nil, nil, err
}
@ -227,25 +242,34 @@ func GetStorageMinerAPI(ctx *cli.Context, opts ...GetStorageMinerOption) (api.St
addr = u.String()
}
return client.NewStorageMinerRPC(ctx.Context, addr, headers)
return client.NewStorageMinerRPCV0(ctx.Context, addr, headers)
}
func GetWorkerAPI(ctx *cli.Context) (api.Worker, jsonrpc.ClientCloser, error) {
addr, headers, err := GetRawAPI(ctx, repo.Worker)
addr, headers, err := GetRawAPI(ctx, repo.Worker, "v0")
if err != nil {
return nil, nil, err
}
return client.NewWorkerRPC(ctx.Context, addr, headers)
return client.NewWorkerRPCV0(ctx.Context, addr, headers)
}
func GetGatewayAPI(ctx *cli.Context) (api.Gateway, jsonrpc.ClientCloser, error) {
addr, headers, err := GetRawAPI(ctx, repo.FullNode)
addr, headers, err := GetRawAPI(ctx, repo.FullNode, "v1")
if err != nil {
return nil, nil, err
}
return client.NewGatewayRPC(ctx.Context, addr, headers)
return client.NewGatewayRPCV1(ctx.Context, addr, headers)
}
func GetGatewayAPIV0(ctx *cli.Context) (v0api.Gateway, jsonrpc.ClientCloser, error) {
addr, headers, err := GetRawAPI(ctx, repo.FullNode, "v0")
if err != nil {
return nil, nil, err
}
return client.NewGatewayRPCV0(ctx.Context, addr, headers)
}
func DaemonContext(cctx *cli.Context) context.Context {

View File

@ -36,7 +36,7 @@ func ParseApiInfo(s string) APIInfo {
}
}
func (a APIInfo) DialArgs() (string, error) {
func (a APIInfo) DialArgs(version string) (string, error) {
ma, err := multiaddr.NewMultiaddr(a.Addr)
if err == nil {
_, addr, err := manet.DialArgs(ma)
@ -44,14 +44,14 @@ func (a APIInfo) DialArgs() (string, error) {
return "", err
}
return "ws://" + addr + "/rpc/v0", nil
return "ws://" + addr + "/rpc/" + version, nil
}
_, err = url.Parse(a.Addr)
if err != nil {
return "", err
}
return a.Addr + "/rpc/v0", nil
return a.Addr + "/rpc/" + version, nil
}
func (a APIInfo) Host() (string, error) {

View File

@ -8,7 +8,7 @@ import (
"time"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
@ -72,7 +72,7 @@ var runCmd = &cli.Command{
},
}
func sendSmallFundsTxs(ctx context.Context, api api.FullNode, from address.Address, rate, limit int) error {
func sendSmallFundsTxs(ctx context.Context, api v0api.FullNode, from address.Address, rate, limit int) error {
var sendSet []address.Address
for i := 0; i < 20; i++ {
naddr, err := api.WalletNew(ctx, types.KTSecp256k1)

View File

@ -14,7 +14,7 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
@ -1026,7 +1026,7 @@ func (p *Processor) storeMinersPower(miners []minerActorInfo) error {
}
// load the power actor state clam as an adt.Map at the tipset `ts`.
func getPowerActorState(ctx context.Context, api api.FullNode, ts types.TipSetKey) (power.State, error) {
func getPowerActorState(ctx context.Context, api v0api.FullNode, ts types.TipSetKey) (power.State, error) {
powerActor, err := api.StateGetActor(ctx, power.Address, ts)
if err != nil {
return nil, err

View File

@ -17,7 +17,7 @@ import (
"github.com/filecoin-project/go-state-types/abi"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/chain/types"
cw_util "github.com/filecoin-project/lotus/cmd/lotus-chainwatch/util"
"github.com/filecoin-project/lotus/lib/parmap"
@ -28,7 +28,7 @@ var log = logging.Logger("processor")
type Processor struct {
db *sql.DB
node api.FullNode
node v0api.FullNode
ctxStore *cw_util.APIIpldStore
genesisTs *types.TipSet
@ -52,7 +52,7 @@ type actorInfo struct {
state string
}
func NewProcessor(ctx context.Context, db *sql.DB, node api.FullNode, batch int) *Processor {
func NewProcessor(ctx context.Context, db *sql.DB, node v0api.FullNode, batch int) *Processor {
ctxStore := cw_util.NewAPIIpldStore(ctx, node)
return &Processor{
db: db,

View File

@ -8,6 +8,8 @@ import (
"os"
"strings"
"github.com/filecoin-project/lotus/api/v0api"
_ "github.com/lib/pq"
"github.com/filecoin-project/go-jsonrpc"
@ -15,7 +17,6 @@ import (
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/cmd/lotus-chainwatch/processor"
"github.com/filecoin-project/lotus/cmd/lotus-chainwatch/scheduler"
@ -44,7 +45,7 @@ var runCmd = &cli.Command{
return err
}
var api api.FullNode
var api v0api.FullNode
var closer jsonrpc.ClientCloser
var err error
if tokenMaddr := cctx.String("api"); tokenMaddr != "" {

View File

@ -13,7 +13,7 @@ import (
"github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log/v2"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
)
@ -26,10 +26,10 @@ type Syncer struct {
lookbackLimit uint64
headerLk sync.Mutex
node api.FullNode
node v0api.FullNode
}
func NewSyncer(db *sql.DB, node api.FullNode, lookbackLimit uint64) *Syncer {
func NewSyncer(db *sql.DB, node v0api.FullNode, lookbackLimit uint64) *Syncer {
return &Syncer{
db: db,
node: node,

View File

@ -5,13 +5,13 @@ import (
"net/http"
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/client"
"github.com/filecoin-project/lotus/api/v0api"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
)
func GetFullNodeAPIUsingCredentials(ctx context.Context, listenAddr, token string) (api.FullNode, jsonrpc.ClientCloser, error) {
func GetFullNodeAPIUsingCredentials(ctx context.Context, listenAddr, token string) (v0api.FullNode, jsonrpc.ClientCloser, error) {
parsedAddr, err := ma.NewMultiaddr(listenAddr)
if err != nil {
return nil, nil, err
@ -22,7 +22,7 @@ func GetFullNodeAPIUsingCredentials(ctx context.Context, listenAddr, token strin
return nil, nil, err
}
return client.NewFullNodeRPC(ctx, apiURI(addr), apiHeaders(token))
return client.NewFullNodeRPCV0(ctx, apiURI(addr), apiHeaders(token))
}
func apiURI(addr string) string {
return "ws://" + addr + "/rpc/v0"

View File

@ -8,7 +8,7 @@ import (
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
)
// TODO extract this to a common location in lotus and reuse the code
@ -16,10 +16,10 @@ import (
// APIIpldStore is required for AMT and HAMT access.
type APIIpldStore struct {
ctx context.Context
api api.FullNode
api v0api.FullNode
}
func NewAPIIpldStore(ctx context.Context, api api.FullNode) *APIIpldStore {
func NewAPIIpldStore(ctx context.Context, api v0api.FullNode) *APIIpldStore {
return &APIIpldStore{
ctx: ctx,
api: api,

View File

@ -15,7 +15,7 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
@ -143,7 +143,7 @@ func prepFundsHtml(box *rice.Box) http.HandlerFunc {
type handler struct {
ctx context.Context
api api.FullNode
api v0api.FullNode
from address.Address
sendPerRequest types.FIL

View File

@ -52,14 +52,13 @@ type gatewayDepsAPI interface {
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error)
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error)
StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error)
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
StateSearchMsgLimited(ctx context.Context, msg cid.Cid, lookbackLimit abi.ChainEpoch) (*api.MsgLookup, error)
StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error)
StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error)
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error)
StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error)
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error)
StateMinerFaults(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error)
@ -72,8 +71,11 @@ type gatewayDepsAPI interface {
StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error)
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error)
WalletBalance(context.Context, address.Address) (types.BigInt, error) //perm:read
}
var _ gatewayDepsAPI = *new(api.FullNode) // gateway depends on latest
type GatewayAPI struct {
api gatewayDepsAPI
lookbackCap time.Duration
@ -261,14 +263,6 @@ func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, t
return a.api.StateGetActor(ctx, actor, tsk)
}
func (a *GatewayAPI) StateGetReceipt(ctx context.Context, c cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return a.api.StateGetReceipt(ctx, c, tsk)
}
func (a *GatewayAPI) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
@ -309,12 +303,29 @@ func (a *GatewayAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKe
return a.api.StateNetworkVersion(ctx, tsk)
}
func (a *GatewayAPI) StateSearchMsg(ctx context.Context, msg cid.Cid) (*api.MsgLookup, error) {
return a.api.StateSearchMsgLimited(ctx, msg, a.stateWaitLookbackLimit)
func (a *GatewayAPI) StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) {
if limit == api.LookbackNoLimit {
limit = a.stateWaitLookbackLimit
}
if a.stateWaitLookbackLimit != api.LookbackNoLimit && limit > a.stateWaitLookbackLimit {
limit = a.stateWaitLookbackLimit
}
if err := a.checkTipsetKey(ctx, from); err != nil {
return nil, err
}
return a.api.StateSearchMsg(ctx, from, msg, limit, allowReplaced)
}
func (a *GatewayAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
return a.api.StateWaitMsgLimited(ctx, msg, confidence, a.stateWaitLookbackLimit)
func (a *GatewayAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error) {
if limit == api.LookbackNoLimit {
limit = a.stateWaitLookbackLimit
}
if a.stateWaitLookbackLimit != api.LookbackNoLimit && limit > a.stateWaitLookbackLimit {
limit = a.stateWaitLookbackLimit
}
return a.api.StateWaitMsg(ctx, msg, confidence, limit, allowReplaced)
}
func (a *GatewayAPI) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) {
@ -404,6 +415,10 @@ func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg []
return sigs.Verify(sig, k, msg) == nil, nil
}
func (a *GatewayAPI) WalletBalance(ctx context.Context, k address.Address) (types.BigInt, error) {
return a.api.WalletBalance(ctx, k)
}
var _ api.Gateway = (*GatewayAPI)(nil)
var _ full.ChainModuleAPI = (*GatewayAPI)(nil)
var _ full.GasModuleAPI = (*GatewayAPI)(nil)

View File

@ -24,6 +24,8 @@ import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/client"
"github.com/filecoin-project/lotus/api/test"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/api/v1api"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
@ -103,7 +105,7 @@ func TestWalletMsig(t *testing.T) {
addProposal, err := lite.MsigCreate(ctx, 2, msigAddrs, abi.ChainEpoch(50), amt, liteWalletAddr, types.NewInt(0))
require.NoError(t, err)
res, err := lite.StateWaitMsg(ctx, addProposal, 1)
res, err := lite.StateWaitMsg(ctx, addProposal, 1, api.LookbackNoLimit, true)
require.NoError(t, err)
require.EqualValues(t, 0, res.Receipt.ExitCode)
@ -123,7 +125,7 @@ func TestWalletMsig(t *testing.T) {
addProposal, err = lite.MsigAddPropose(ctx, msig, walletAddrs[0], walletAddrs[3], false)
require.NoError(t, err)
res, err = lite.StateWaitMsg(ctx, addProposal, 1)
res, err = lite.StateWaitMsg(ctx, addProposal, 1, api.LookbackNoLimit, true)
require.NoError(t, err)
require.EqualValues(t, 0, res.Receipt.ExitCode)
@ -137,7 +139,7 @@ func TestWalletMsig(t *testing.T) {
approval1, err := lite.MsigAddApprove(ctx, msig, walletAddrs[1], txnID, walletAddrs[0], walletAddrs[3], false)
require.NoError(t, err)
res, err = lite.StateWaitMsg(ctx, approval1, 1)
res, err = lite.StateWaitMsg(ctx, approval1, 1, api.LookbackNoLimit, true)
require.NoError(t, err)
require.EqualValues(t, 0, res.Receipt.ExitCode)
@ -245,12 +247,15 @@ func startNodes(
// Create a gateway server in front of the full node
gapiImpl := newGatewayAPI(fullNode, lookbackCap, stateWaitLookbackLimit)
_, addr, err := builder.CreateRPCServer(t, gapiImpl)
_, addr, err := builder.CreateRPCServer(t, map[string]interface{}{
"/rpc/v1": gapiImpl,
"/rpc/v0": api.Wrap(new(v1api.FullNodeStruct), new(v0api.WrapperV1Full), gapiImpl),
})
require.NoError(t, err)
// Create a gateway client API that connects to the gateway server
var gapi api.Gateway
gapi, closer, err = client.NewGatewayRPC(ctx, addr, nil)
gapi, closer, err = client.NewGatewayRPCV1(ctx, addr+"/rpc/v1", nil)
require.NoError(t, err)
// Provide the gateway API to dependency injection
@ -299,7 +304,7 @@ func sendFunds(ctx context.Context, fromNode test.TestNode, fromAddr address.Add
return err
}
res, err := fromNode.StateWaitMsg(ctx, sm.Cid(), 1)
res, err := fromNode.StateWaitMsg(ctx, sm.Cid(), 1, api.LookbackNoLimit, true)
if err != nil {
return err
}

View File

@ -11,6 +11,9 @@ import (
promclient "github.com/prometheus/client_golang/prometheus"
"go.opencensus.io/tag"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/api/v1api"
"github.com/filecoin-project/lotus/build"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/lib/lotuslog"
@ -82,7 +85,7 @@ var runCmd = &cli.Command{
log.Fatalf("Cannot register the view: %v", err)
}
api, closer, err := lcli.GetFullNodeAPI(cctx)
api, closer, err := lcli.GetFullNodeAPIV1(cctx)
if err != nil {
return err
}
@ -93,14 +96,21 @@ var runCmd = &cli.Command{
log.Info("Setting up API endpoint at " + address)
serverOptions := make([]jsonrpc.ServerOption, 0)
if maxRequestSize := cctx.Int("api-max-req-size"); maxRequestSize != 0 {
serverOptions = append(serverOptions, jsonrpc.WithMaxRequestSize(int64(maxRequestSize)))
}
rpcServer := jsonrpc.NewServer(serverOptions...)
rpcServer.Register("Filecoin", metrics.MetricedGatewayAPI(NewGatewayAPI(api)))
serveRpc := func(path string, hnd interface{}) {
serverOptions := make([]jsonrpc.ServerOption, 0)
if maxRequestSize := cctx.Int("api-max-req-size"); maxRequestSize != 0 {
serverOptions = append(serverOptions, jsonrpc.WithMaxRequestSize(int64(maxRequestSize)))
}
rpcServer := jsonrpc.NewServer(serverOptions...)
rpcServer.Register("Filecoin", hnd)
mux.Handle("/rpc/v0", rpcServer)
mux.Handle(path, rpcServer)
}
ma := metrics.MetricedGatewayAPI(NewGatewayAPI(api))
serveRpc("/rpc/v1", ma)
serveRpc("/rpc/v0", lapi.Wrap(new(v1api.FullNodeStruct), new(v0api.WrapperV1Full), ma))
registry := promclient.DefaultRegisterer.(*promclient.Registry)
exporter, err := prometheus.NewExporter(prometheus.Options{

View File

@ -8,13 +8,14 @@ import (
"syscall"
"time"
"github.com/filecoin-project/lotus/api/v0api"
cid "github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log/v2"
"github.com/urfave/cli/v2"
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
@ -180,7 +181,7 @@ func checkWindow(window CidWindow, t int) bool {
* returns a slice of slices of Cids
* len of slice <= `t` - threshold
*/
func updateWindow(ctx context.Context, a api.FullNode, w CidWindow, t int, r int, to time.Duration) (CidWindow, error) {
func updateWindow(ctx context.Context, a v0api.FullNode, w CidWindow, t int, r int, to time.Duration) (CidWindow, error) {
head, err := getHead(ctx, a, r, to)
if err != nil {
return nil, err
@ -194,7 +195,7 @@ func updateWindow(ctx context.Context, a api.FullNode, w CidWindow, t int, r int
* retries if API no available
* returns tipset
*/
func getHead(ctx context.Context, a api.FullNode, r int, t time.Duration) (*types.TipSet, error) {
func getHead(ctx context.Context, a v0api.FullNode, r int, t time.Duration) (*types.TipSet, error) {
for i := 0; i < r; i++ {
head, err := a.ChainHead(ctx)
if err != nil && i == (r-1) {
@ -226,7 +227,7 @@ func appendCIDsToWindow(w CidWindow, c []cid.Cid, t int) CidWindow {
/*
* wait for node to sync
*/
func waitForSyncComplete(ctx context.Context, a api.FullNode, r int, t time.Duration) error {
func waitForSyncComplete(ctx context.Context, a v0api.FullNode, r int, t time.Duration) error {
for {
select {
case <-ctx.Done():
@ -248,7 +249,7 @@ func waitForSyncComplete(ctx context.Context, a api.FullNode, r int, t time.Dura
* A thin wrapper around lotus cli GetFullNodeAPI
* Adds retry logic
*/
func getFullNodeAPI(ctx *cli.Context, r int, t time.Duration) (api.FullNode, jsonrpc.ClientCloser, error) {
func getFullNodeAPI(ctx *cli.Context, r int, t time.Duration) (v0api.FullNode, jsonrpc.ClientCloser, error) {
for i := 0; i < r; i++ {
api, closer, err := lcli.GetFullNodeAPI(ctx)
if err != nil && i == (r-1) {

View File

@ -28,7 +28,6 @@ import (
"github.com/filecoin-project/go-statestore"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/build"
lcli "github.com/filecoin-project/lotus/cli"
cliutil "github.com/filecoin-project/lotus/cli/util"
@ -211,8 +210,8 @@ var runCmd = &cli.Command{
if err != nil {
return err
}
if v.APIVersion != api.MinerAPIVersion {
return xerrors.Errorf("lotus-miner API version doesn't match: expected: %s", api.APIVersion{APIVersion: api.MinerAPIVersion})
if v.APIVersion != api.MinerAPIVersion0 {
return xerrors.Errorf("lotus-miner API version doesn't match: expected: %s", api.APIVersion{APIVersion: api.MinerAPIVersion0})
}
log.Infof("Remote version %s", v)
@ -366,7 +365,7 @@ var runCmd = &cli.Command{
fh := &stores.FetchHandler{Local: localStore}
remoteHandler := func(w http.ResponseWriter, r *http.Request) {
if !auth.HasPerm(r.Context(), nil, apistruct.PermAdmin) {
if !auth.HasPerm(r.Context(), nil, api.PermAdmin) {
w.WriteHeader(401)
_ = json.NewEncoder(w).Encode(struct{ Error string }{"unauthorized: missing admin permission"})
return
@ -394,7 +393,7 @@ var runCmd = &cli.Command{
readerHandler, readerServerOpt := rpcenc.ReaderParamDecoder()
rpcServer := jsonrpc.NewServer(readerServerOpt)
rpcServer.Register("Filecoin", apistruct.PermissionedWorkerAPI(metrics.MetricedWorkerAPI(workerApi)))
rpcServer.Register("Filecoin", api.PermissionedWorkerAPI(metrics.MetricedWorkerAPI(workerApi)))
mux.Handle("/rpc/v0", rpcServer)
mux.Handle("/rpc/streams/v0/push/{uuid}", readerHandler)

View File

@ -26,7 +26,7 @@ type worker struct {
}
func (w *worker) Version(context.Context) (api.Version, error) {
return api.WorkerAPIVersion, nil
return api.WorkerAPIVersion0, nil
}
func (w *worker) StorageAddLocal(ctx context.Context, path string) error {

View File

@ -10,6 +10,8 @@ import (
"strings"
"time"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/gen/genesis"
_init "github.com/filecoin-project/lotus/chain/actors/builtin/init"
@ -64,12 +66,64 @@ var auditsCmd = &cli.Command{
Description: "a collection of utilities for auditing the filecoin chain",
Subcommands: []*cli.Command{
chainBalanceCmd,
chainBalanceSanityCheckCmd,
chainBalanceStateCmd,
chainPledgeCmd,
fillBalancesCmd,
},
}
var chainBalanceSanityCheckCmd = &cli.Command{
Name: "chain-balance-sanity",
Description: "Confirms that the total balance of every actor in state is still 2 billion",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "tipset",
Usage: "specify tipset to start from",
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := lcli.ReqContext(cctx)
ts, err := lcli.LoadTipSet(ctx, cctx, api)
if err != nil {
return err
}
tsk := ts.Key()
actors, err := api.StateListActors(ctx, tsk)
if err != nil {
return err
}
bal := big.Zero()
for _, addr := range actors {
act, err := api.StateGetActor(ctx, addr, tsk)
if err != nil {
return err
}
bal = big.Add(bal, act.Balance)
}
attoBase := big.Mul(big.NewInt(int64(build.FilBase)), big.NewInt(int64(build.FilecoinPrecision)))
if big.Cmp(attoBase, bal) != 0 {
return xerrors.Errorf("sanity check failed (expected %s, actual %s)", attoBase, bal)
}
fmt.Println("sanity check successful")
return nil
},
}
var chainBalanceCmd = &cli.Command{
Name: "chain-balances",
Description: "Produces a csv file of all account balances",

View File

@ -113,12 +113,12 @@ var consensusCheckCmd = &cli.Command{
return err
}
ainfo := cliutil.APIInfo{Addr: apima.String()}
addr, err := ainfo.DialArgs()
addr, err := ainfo.DialArgs("v1")
if err != nil {
return err
}
api, closer, err := client.NewFullNodeRPC(cctx.Context, addr, nil)
api, closer, err := client.NewFullNodeRPCV1(cctx.Context, addr, nil)
if err != nil {
return err
}

View File

@ -15,7 +15,8 @@ import (
"github.com/urfave/cli/v2"
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules"
)
@ -98,19 +99,19 @@ var jwtTokenCmd = &cli.Command{
perms := []auth.Permission{}
if cctx.Bool("read") {
perms = append(perms, apistruct.PermRead)
perms = append(perms, api.PermRead)
}
if cctx.Bool("write") {
perms = append(perms, apistruct.PermWrite)
perms = append(perms, api.PermWrite)
}
if cctx.Bool("sign") {
perms = append(perms, apistruct.PermSign)
perms = append(perms, api.PermSign)
}
if cctx.Bool("admin") {
perms = append(perms, apistruct.PermAdmin)
perms = append(perms, api.PermAdmin)
}
p := modules.JwtPayload{
@ -152,7 +153,7 @@ var jwtNewCmd = &cli.Command{
}
p := modules.JwtPayload{
Allow: apistruct.AllPermissions,
Allow: api.AllPermissions,
}
token, err := jwt.Sign(&p, jwt.NewHS256(keyInfo.PrivateKey))

View File

@ -6,13 +6,14 @@ import (
"strconv"
"strings"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/urfave/cli/v2"
ledgerfil "github.com/whyrusleeping/ledger-filecoin-go"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger"
lcli "github.com/filecoin-project/lotus/cli"
@ -42,7 +43,7 @@ var ledgerListAddressesCmd = &cli.Command{
},
},
Action: func(cctx *cli.Context) error {
var api api.FullNode
var api v0api.FullNode
if cctx.Bool("print-balances") {
a, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {

View File

@ -28,6 +28,10 @@ var rpcCmd = &cli.Command{
&cli.BoolFlag{
Name: "miner",
},
&cli.StringFlag{
Name: "version",
Value: "v0",
},
},
Action: func(cctx *cli.Context) error {
rt := repo.FullNode
@ -35,7 +39,7 @@ var rpcCmd = &cli.Command{
rt = repo.StorageMiner
}
addr, headers, err := lcli.GetRawAPI(cctx, rt)
addr, headers, err := lcli.GetRawAPI(cctx, rt, cctx.String("version"))
if err != nil {
return err
}

View File

@ -37,6 +37,8 @@ import (
power2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/power"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/api/v1api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
@ -149,7 +151,11 @@ var initCmd = &cli.Command{
log.Info("Trying to connect to full node RPC")
api, closer, err := lcli.GetFullNodeAPI(cctx) // TODO: consider storing full node address in config
if err := checkV1ApiSupport(ctx, cctx); err != nil {
return err
}
api, closer, err := lcli.GetFullNodeAPIV1(cctx) // TODO: consider storing full node address in config
if err != nil {
return err
}
@ -158,7 +164,7 @@ var initCmd = &cli.Command{
log.Info("Checking full node sync status")
if !cctx.Bool("genesis-miner") && !cctx.Bool("nosync") {
if err := lcli.SyncWait(ctx, api, false); err != nil {
if err := lcli.SyncWait(ctx, &v0api.WrapperV1Full{FullNode: api}, false); err != nil {
return xerrors.Errorf("sync wait: %w", err)
}
}
@ -186,8 +192,8 @@ var initCmd = &cli.Command{
return err
}
if !v.APIVersion.EqMajorMinor(lapi.FullAPIVersion) {
return xerrors.Errorf("Remote API version didn't match (expected %s, remote %s)", lapi.FullAPIVersion, v.APIVersion)
if !v.APIVersion.EqMajorMinor(lapi.FullAPIVersion1) {
return xerrors.Errorf("Remote API version didn't match (expected %s, remote %s)", lapi.FullAPIVersion1, v.APIVersion)
}
log.Info("Initializing repo")
@ -269,7 +275,7 @@ var initCmd = &cli.Command{
},
}
func migratePreSealMeta(ctx context.Context, api lapi.FullNode, metadata string, maddr address.Address, mds dtypes.MetadataDS) error {
func migratePreSealMeta(ctx context.Context, api v1api.FullNode, metadata string, maddr address.Address, mds dtypes.MetadataDS) error {
metadata, err := homedir.Expand(metadata)
if err != nil {
return xerrors.Errorf("expanding preseal dir: %w", err)
@ -379,7 +385,7 @@ func migratePreSealMeta(ctx context.Context, api lapi.FullNode, metadata string,
return mds.Put(datastore.NewKey(modules.StorageCounterDSPrefix), buf[:size])
}
func findMarketDealID(ctx context.Context, api lapi.FullNode, deal market2.DealProposal) (abi.DealID, error) {
func findMarketDealID(ctx context.Context, api v1api.FullNode, deal market2.DealProposal) (abi.DealID, error) {
// TODO: find a better way
// (this is only used by genesis miners)
@ -398,7 +404,7 @@ func findMarketDealID(ctx context.Context, api lapi.FullNode, deal market2.DealP
return 0, xerrors.New("deal not found")
}
func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode, r repo.Repo, ssize abi.SectorSize, gasPrice types.BigInt) error {
func storageMinerInit(ctx context.Context, cctx *cli.Context, api v1api.FullNode, r repo.Repo, ssize abi.SectorSize, gasPrice types.BigInt) error {
lr, err := r.Lock(repo.StorageMiner)
if err != nil {
return err
@ -562,7 +568,7 @@ func makeHostKey(lr repo.LockedRepo) (crypto.PrivKey, error) {
return pk, nil
}
func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address.Address, peerid peer.ID, gasPrice types.BigInt) error {
func configureStorageMiner(ctx context.Context, api v1api.FullNode, addr address.Address, peerid peer.ID, gasPrice types.BigInt) error {
mi, err := api.StateMinerInfo(ctx, addr, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("getWorkerAddr returned bad address: %w", err)
@ -588,7 +594,7 @@ func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address.
}
log.Info("Waiting for message: ", smsg.Cid())
ret, err := api.StateWaitMsg(ctx, smsg.Cid(), build.MessageConfidence)
ret, err := api.StateWaitMsg(ctx, smsg.Cid(), build.MessageConfidence, lapi.LookbackNoLimit, true)
if err != nil {
return err
}
@ -600,7 +606,7 @@ func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address.
return nil
}
func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID, gasPrice types.BigInt, cctx *cli.Context) (address.Address, error) {
func createStorageMiner(ctx context.Context, api v1api.FullNode, peerid peer.ID, gasPrice types.BigInt, cctx *cli.Context) (address.Address, error) {
var err error
var owner address.Address
if cctx.String("owner") != "" {
@ -642,7 +648,7 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID,
log.Infof("Initializing worker account %s, message: %s", worker, signed.Cid())
log.Infof("Waiting for confirmation")
mw, err := api.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence)
mw, err := api.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence, lapi.LookbackNoLimit, true)
if err != nil {
return address.Undef, xerrors.Errorf("waiting for worker init: %w", err)
}
@ -700,7 +706,7 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID,
log.Infof("Pushed CreateMiner message: %s", signed.Cid())
log.Infof("Waiting for confirmation")
mw, err := api.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence)
mw, err := api.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence, lapi.LookbackNoLimit, true)
if err != nil {
return address.Undef, xerrors.Errorf("waiting for createMiner message: %w", err)
}
@ -717,3 +723,24 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID,
log.Infof("New miners address is: %s (%s)", retval.IDAddress, retval.RobustAddress)
return retval.IDAddress, nil
}
func checkV1ApiSupport(ctx context.Context, cctx *cli.Context) error {
// check v0 api version to make sure it supports v1 api
api0, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
v, err := api0.Version(ctx)
closer()
if err != nil {
return err
}
if !v.APIVersion.EqMajorMinor(lapi.FullAPIVersion0) {
return xerrors.Errorf("Remote API version didn't match (expected %s, remote %s)", lapi.FullAPIVersion0, v.APIVersion)
}
return nil
}

View File

@ -6,6 +6,8 @@ import (
"io/ioutil"
"os"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/docker/go-units"
"github.com/ipfs/go-datastore"
"github.com/libp2p/go-libp2p-core/peer"
@ -52,9 +54,15 @@ var initRestoreCmd = &cli.Command{
return xerrors.Errorf("expected 1 argument")
}
ctx := lcli.ReqContext(cctx)
log.Info("Trying to connect to full node RPC")
api, closer, err := lcli.GetFullNodeAPI(cctx) // TODO: consider storing full node address in config
if err := checkV1ApiSupport(ctx, cctx); err != nil {
return err
}
api, closer, err := lcli.GetFullNodeAPIV1(cctx) // TODO: consider storing full node address in config
if err != nil {
return err
}
@ -62,19 +70,17 @@ var initRestoreCmd = &cli.Command{
log.Info("Checking full node version")
ctx := lcli.ReqContext(cctx)
v, err := api.Version(ctx)
if err != nil {
return err
}
if !v.APIVersion.EqMajorMinor(lapi.FullAPIVersion) {
return xerrors.Errorf("Remote API version didn't match (expected %s, remote %s)", lapi.FullAPIVersion, v.APIVersion)
if !v.APIVersion.EqMajorMinor(lapi.FullAPIVersion1) {
return xerrors.Errorf("Remote API version didn't match (expected %s, remote %s)", lapi.FullAPIVersion1, v.APIVersion)
}
if !cctx.Bool("nosync") {
if err := lcli.SyncWait(ctx, api, false); err != nil {
if err := lcli.SyncWait(ctx, &v0api.WrapperV1Full{FullNode: api}, false); err != nil {
return xerrors.Errorf("sync wait: %w", err)
}
}

View File

@ -9,6 +9,10 @@ import (
"os/signal"
"syscall"
"github.com/filecoin-project/lotus/api/v1api"
"github.com/filecoin-project/lotus/api/v0api"
mux "github.com/gorilla/mux"
"github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
@ -22,7 +26,6 @@ import (
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/build"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/lib/ulimit"
@ -64,19 +67,13 @@ var runCmd = &cli.Command{
}
}
nodeApi, ncloser, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return xerrors.Errorf("getting full node api: %w", err)
}
defer ncloser()
ctx, _ := tag.New(lcli.DaemonContext(cctx),
tag.Insert(metrics.Version, build.BuildVersion),
tag.Insert(metrics.Commit, build.CurrentCommit),
tag.Insert(metrics.NodeType, "miner"),
)
// Register all metric views
if err = view.Register(
if err := view.Register(
metrics.MinerNodeViews...,
); err != nil {
log.Fatalf("Cannot register the view: %v", err)
@ -84,6 +81,16 @@ var runCmd = &cli.Command{
// Set the metric to one so it is published to the exporter
stats.Record(ctx, metrics.LotusInfo.M(1))
if err := checkV1ApiSupport(ctx, cctx); err != nil {
return err
}
nodeApi, ncloser, err := lcli.GetFullNodeAPIV1(cctx)
if err != nil {
return xerrors.Errorf("getting full node api: %w", err)
}
defer ncloser()
v, err := nodeApi.Version(ctx)
if err != nil {
return err
@ -95,14 +102,14 @@ var runCmd = &cli.Command{
}
}
if v.APIVersion != api.FullAPIVersion {
return xerrors.Errorf("lotus-daemon API version doesn't match: expected: %s", api.APIVersion{APIVersion: api.FullAPIVersion})
if v.APIVersion != api.FullAPIVersion1 {
return xerrors.Errorf("lotus-daemon API version doesn't match: expected: %s", api.APIVersion{APIVersion: api.FullAPIVersion1})
}
log.Info("Checking full node sync status")
if !cctx.Bool("nosync") {
if err := lcli.SyncWait(ctx, nodeApi, false); err != nil {
if err := lcli.SyncWait(ctx, &v0api.WrapperV1Full{FullNode: nodeApi}, false); err != nil {
return xerrors.Errorf("sync wait: %w", err)
}
}
@ -134,7 +141,7 @@ var runCmd = &cli.Command{
node.Override(new(dtypes.APIEndpoint), func() (dtypes.APIEndpoint, error) {
return multiaddr.NewMultiaddr("/ip4/127.0.0.1/tcp/" + cctx.String("miner-api"))
})),
node.Override(new(api.FullNode), nodeApi),
node.Override(new(v1api.FullNode), nodeApi),
)
if err != nil {
return xerrors.Errorf("creating node: %w", err)
@ -165,7 +172,7 @@ var runCmd = &cli.Command{
mux := mux.NewRouter()
rpcServer := jsonrpc.NewServer()
rpcServer.Register("Filecoin", apistruct.PermissionedStorMinerAPI(metrics.MetricedStorMinerAPI(minerapi)))
rpcServer.Register("Filecoin", api.PermissionedStorMinerAPI(metrics.MetricedStorMinerAPI(minerapi)))
mux.Handle("/rpc/v0", rpcServer)
mux.PathPrefix("/remote").HandlerFunc(minerapi.(*impl.StorageMinerAPI).ServeRemote)

View File

@ -12,6 +12,8 @@ import (
"strings"
"time"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/docker/go-units"
"github.com/fatih/color"
"github.com/google/uuid"
@ -668,7 +670,7 @@ var storageCleanupCmd = &cli.Command{
},
}
func cleanupRemovedSectorData(ctx context.Context, api api.StorageMiner, napi api.FullNode) error {
func cleanupRemovedSectorData(ctx context.Context, api api.StorageMiner, napi v0api.FullNode) error {
sectors, err := api.SectorsList(ctx)
if err != nil {
return err

View File

@ -20,6 +20,7 @@ import (
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/stmgr"
@ -30,8 +31,8 @@ import (
type InteractiveWallet struct {
lk sync.Mutex
apiGetter func() (api.FullNode, jsonrpc.ClientCloser, error)
under api.Wallet
apiGetter func() (v0api.FullNode, jsonrpc.ClientCloser, error)
under v0api.Wallet
}
func (c *InteractiveWallet) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) {

View File

@ -6,6 +6,8 @@ import (
"net/http"
"os"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/gorilla/mux"
logging "github.com/ipfs/go-log/v2"
"github.com/urfave/cli/v2"
@ -149,10 +151,10 @@ var runCmd = &cli.Command{
log.Info("Setting up API endpoint at " + address)
if cctx.Bool("interactive") {
var ag func() (api.FullNode, jsonrpc.ClientCloser, error)
var ag func() (v0api.FullNode, jsonrpc.ClientCloser, error)
if !cctx.Bool("offline") {
ag = func() (api.FullNode, jsonrpc.ClientCloser, error) {
ag = func() (v0api.FullNode, jsonrpc.ClientCloser, error) {
return lcli.GetFullNodeAPI(cctx)
}
}

View File

@ -22,7 +22,8 @@ import (
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/api/v1api"
"github.com/filecoin-project/lotus/metrics"
"github.com/filecoin-project/lotus/node"
"github.com/filecoin-project/lotus/node/impl"
@ -30,21 +31,27 @@ import (
var log = logging.Logger("main")
func serveRPC(a api.FullNode, stop node.StopFunc, addr multiaddr.Multiaddr, shutdownCh <-chan struct{}, maxRequestSize int64) error {
func serveRPC(a v1api.FullNode, stop node.StopFunc, addr multiaddr.Multiaddr, shutdownCh <-chan struct{}, maxRequestSize int64) error {
serverOptions := make([]jsonrpc.ServerOption, 0)
if maxRequestSize != 0 { // config set
serverOptions = append(serverOptions, jsonrpc.WithMaxRequestSize(maxRequestSize))
}
rpcServer := jsonrpc.NewServer(serverOptions...)
rpcServer.Register("Filecoin", apistruct.PermissionedFullAPI(metrics.MetricedFullAPI(a)))
rpcServer.AliasMethod("rpc.discover", "Filecoin.Discover")
serveRpc := func(path string, hnd interface{}) {
rpcServer := jsonrpc.NewServer(serverOptions...)
rpcServer.Register("Filecoin", hnd)
ah := &auth.Handler{
Verify: a.AuthVerify,
Next: rpcServer.ServeHTTP,
ah := &auth.Handler{
Verify: a.AuthVerify,
Next: rpcServer.ServeHTTP,
}
http.Handle(path, ah)
}
http.Handle("/rpc/v0", ah)
pma := api.PermissionedFullAPI(metrics.MetricedFullAPI(a))
serveRpc("/rpc/v1", pma)
serveRpc("/rpc/v0", &v0api.WrapperV1Full{FullNode: pma})
importAH := &auth.Handler{
Verify: a.AuthVerify,
@ -109,7 +116,7 @@ func handleImport(a *impl.FullNodeAPI) func(w http.ResponseWriter, r *http.Reque
w.WriteHeader(404)
return
}
if !auth.HasPerm(r.Context(), nil, apistruct.PermWrite) {
if !auth.HasPerm(r.Context(), nil, api.PermWrite) {
w.WriteHeader(401)
_ = json.NewEncoder(w).Encode(struct{ Error string }{"unauthorized: missing write permission"})
return

View File

@ -8,6 +8,8 @@ import (
"io"
"log"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/fatih/color"
"github.com/filecoin-project/go-address"
@ -318,7 +320,7 @@ func doExtractMessage(opts extractOpts) error {
// resolveFromChain queries the chain for the provided message, using the block CID to
// speed up the query, if provided
func resolveFromChain(ctx context.Context, api api.FullNode, mcid cid.Cid, block string) (msg *types.Message, execTs *types.TipSet, incTs *types.TipSet, err error) {
func resolveFromChain(ctx context.Context, api v0api.FullNode, mcid cid.Cid, block string) (msg *types.Message, execTs *types.TipSet, incTs *types.TipSet, err error) {
// Extract the full message.
msg, err = api.ChainGetMessage(ctx, mcid)
if err != nil {
@ -373,7 +375,7 @@ func resolveFromChain(ctx context.Context, api api.FullNode, mcid cid.Cid, block
// as the previous tipset. In the context of vector generation, the target
// tipset is the one where a message was executed, and the previous tipset is
// the one where the message was included.
func fetchThisAndPrevTipset(ctx context.Context, api api.FullNode, target types.TipSetKey) (targetTs *types.TipSet, prevTs *types.TipSet, err error) {
func fetchThisAndPrevTipset(ctx context.Context, api v0api.FullNode, target types.TipSetKey) (targetTs *types.TipSet, prevTs *types.TipSet, err error) {
// get the tipset on which this message was "executed" on.
// https://github.com/filecoin-project/lotus/issues/2847
targetTs, err = api.ChainGetTipSet(ctx, target)

View File

@ -9,13 +9,13 @@ import (
"github.com/filecoin-project/go-jsonrpc"
"github.com/urfave/cli/v2"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
lcli "github.com/filecoin-project/lotus/cli"
)
// FullAPI is a JSON-RPC client targeting a full node. It's initialized in a
// cli.BeforeFunc.
var FullAPI api.FullNode
var FullAPI v0api.FullNode
// Closer is the closer for the JSON-RPC client, which must be called on
// cli.AfterFunc.

View File

@ -6,6 +6,8 @@ import (
"io"
"log"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
@ -13,7 +15,6 @@ import (
"github.com/ipld/go-car"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/lotus/api"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
@ -23,13 +24,13 @@ import (
// StateSurgeon is an object used to fetch and manipulate state.
type StateSurgeon struct {
ctx context.Context
api api.FullNode
api v0api.FullNode
stores *Stores
}
// NewSurgeon returns a state surgeon, an object used to fetch and manipulate
// state.
func NewSurgeon(ctx context.Context, api api.FullNode, stores *Stores) *StateSurgeon {
func NewSurgeon(ctx context.Context, api v0api.FullNode, stores *Stores) *StateSurgeon {
return &StateSurgeon{
ctx: ctx,
api: api,
@ -85,7 +86,7 @@ func (sg *StateSurgeon) GetMaskedStateTree(previousRoot cid.Cid, retain []addres
// GetAccessedActors identifies the actors that were accessed during the
// execution of a message.
func (sg *StateSurgeon) GetAccessedActors(ctx context.Context, a api.FullNode, mid cid.Cid) ([]address.Address, error) {
func (sg *StateSurgeon) GetAccessedActors(ctx context.Context, a v0api.FullNode, mid cid.Cid) ([]address.Address, error) {
log.Printf("calculating accessed actors during execution of message: %s", mid)
msgInfo, err := a.StateSearchMsg(ctx, mid)
if err != nil {

View File

@ -5,10 +5,11 @@ import (
"log"
"sync"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/fatih/color"
dssync "github.com/ipfs/go-datastore/sync"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/chain/actors/adt"
@ -40,7 +41,7 @@ type Stores struct {
// NewProxyingStores is a set of Stores backed by a proxying Blockstore that
// proxies Get requests for unknown CIDs to a Filecoin node, via the
// ChainReadObj RPC.
func NewProxyingStores(ctx context.Context, api api.FullNode) *Stores {
func NewProxyingStores(ctx context.Context, api v0api.FullNode) *Stores {
ds := dssync.MutexWrap(ds.NewMapDatastore())
bs := &proxyingBlockstore{
ctx: ctx,
@ -85,7 +86,7 @@ type TracingBlockstore interface {
// a Filecoin node via JSON-RPC.
type proxyingBlockstore struct {
ctx context.Context
api api.FullNode
api v0api.FullNode
lk sync.Mutex
tracing bool

View File

@ -10,14 +10,14 @@ import (
"github.com/filecoin-project/test-vectors/schema"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)
type RecordingRand struct {
reporter Reporter
api api.FullNode
api v0api.FullNode
// once guards the loading of the head tipset.
// can be removed when https://github.com/filecoin-project/lotus/issues/4223
@ -33,7 +33,7 @@ var _ vm.Rand = (*RecordingRand)(nil)
// NewRecordingRand returns a vm.Rand implementation that proxies calls to a
// full Lotus node via JSON-RPC, and records matching rules and responses so
// they can later be embedded in test vectors.
func NewRecordingRand(reporter Reporter, api api.FullNode) *RecordingRand {
func NewRecordingRand(reporter Reporter, api v0api.FullNode) *RecordingRand {
return &RecordingRand{reporter: reporter, api: api}
}

View File

@ -197,7 +197,7 @@ Response:
```json
{
"Version": "string value",
"APIVersion": 66048,
"APIVersion": 131328,
"BlockDelay": 42
}
```

View File

@ -145,7 +145,7 @@ Perms: admin
Inputs: `null`
Response: `66048`
Response: `131328`
## Add

View File

@ -276,7 +276,7 @@ Response:
```json
{
"Version": "string value",
"APIVersion": 66048,
"APIVersion": 131328,
"BlockDelay": 42
}
```
@ -4943,7 +4943,8 @@ Response:
"FilMined": "0",
"FilBurnt": "0",
"FilLocked": "0",
"FilCirculating": "0"
"FilCirculating": "0",
"FilReserveDisbursed": "0"
}
```

File diff suppressed because it is too large Load Diff

View File

@ -208,6 +208,7 @@ func (m *Manager) schedFetch(sector storage.SectorRef, ft storiface.SectorFileTy
func (m *Manager) readPiece(sink io.Writer, sector storage.SectorRef, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, rok *bool) func(ctx context.Context, w Worker) error {
return func(ctx context.Context, w Worker) error {
log.Debugf("read piece data from sector %d, offset %d, size %d", sector.ID, offset, size)
r, err := m.waitSimpleCall(ctx)(w.ReadPiece(ctx, sink, sector, offset, size))
if err != nil {
return err
@ -215,6 +216,7 @@ func (m *Manager) readPiece(sink io.Writer, sector storage.SectorRef, offset sto
if r != nil {
*rok = r.(bool)
}
log.Debugf("completed read piece data from sector %d, offset %d, size %d: read ok? %t", sector.ID, offset, size, *rok)
return nil
}
}
@ -225,11 +227,13 @@ func (m *Manager) tryReadUnsealedPiece(ctx context.Context, sink io.Writer, sect
ctx, cancel := context.WithCancel(ctx)
defer cancel()
log.Debugf("acquire read sector lock for sector %d", sector.ID)
if err := m.index.StorageLock(ctx, sector.ID, storiface.FTUnsealed, storiface.FTNone); err != nil {
returnErr = xerrors.Errorf("acquiring read sector lock: %w", err)
return
}
log.Debugf("find unsealed sector %d", sector.ID)
// passing 0 spt because we only need it when allowFetch is true
best, err := m.index.StorageFindSector(ctx, sector.ID, storiface.FTUnsealed, 0, false)
if err != nil {
@ -240,41 +244,49 @@ func (m *Manager) tryReadUnsealedPiece(ctx context.Context, sink io.Writer, sect
foundUnsealed = len(best) > 0
if foundUnsealed { // append to existing
// There is unsealed sector, see if we can read from it
log.Debugf("found unsealed sector %d", sector.ID)
selector = newExistingSelector(m.index, sector.ID, storiface.FTUnsealed, false)
log.Debugf("scheduling read of unsealed sector %d", sector.ID)
err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, m.schedFetch(sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove),
m.readPiece(sink, sector, offset, size, &readOk))
if err != nil {
returnErr = xerrors.Errorf("reading piece from sealed sector: %w", err)
}
} else {
log.Debugf("did not find unsealed sector %d", sector.ID)
selector = newAllocSelector(m.index, storiface.FTUnsealed, storiface.PathSealing)
}
return
}
func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector storage.SectorRef, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, ticket abi.SealRandomness, unsealed cid.Cid) error {
log.Debugf("fetch and read piece in sector %d, offset %d, size %d", sector.ID, offset, size)
foundUnsealed, readOk, selector, err := m.tryReadUnsealedPiece(ctx, sink, sector, offset, size)
if err != nil {
return err
}
if readOk {
log.Debugf("completed read of unsealed piece in sector %d, offset %d, size %d", sector.ID, offset, size)
return nil
}
ctx, cancel := context.WithCancel(ctx)
defer cancel()
log.Debugf("acquire unseal sector lock for sector %d", sector.ID)
if err := m.index.StorageLock(ctx, sector.ID, storiface.FTSealed|storiface.FTCache, storiface.FTUnsealed); err != nil {
return xerrors.Errorf("acquiring unseal sector lock: %w", err)
}
unsealFetch := func(ctx context.Context, worker Worker) error {
log.Debugf("copy sealed/cache sector data for sector %d", sector.ID)
if _, err := m.waitSimpleCall(ctx)(worker.Fetch(ctx, sector, storiface.FTSealed|storiface.FTCache, storiface.PathSealing, storiface.AcquireCopy)); err != nil {
return xerrors.Errorf("copy sealed/cache sector data: %w", err)
}
if foundUnsealed {
log.Debugf("copy unsealed sector data for sector %d", sector.ID)
if _, err := m.waitSimpleCall(ctx)(worker.Fetch(ctx, sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove)); err != nil {
return xerrors.Errorf("copy unsealed sector data: %w", err)
}
@ -291,13 +303,16 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector storage.
return xerrors.Errorf("getting sector size: %w", err)
}
log.Debugf("schedule unseal for sector %d", sector.ID)
err = m.sched.Schedule(ctx, sector, sealtasks.TTUnseal, selector, unsealFetch, func(ctx context.Context, w Worker) error {
// TODO: make restartable
// NOTE: we're unsealing the whole sector here as with SDR we can't really
// unseal the sector partially. Requesting the whole sector here can
// save us some work in case another piece is requested from here
log.Debugf("unseal sector %d", sector.ID)
_, err := m.waitSimpleCall(ctx)(w.UnsealPiece(ctx, sector, 0, abi.PaddedPieceSize(ssize).Unpadded(), ticket, unsealed))
log.Debugf("completed unseal sector %d", sector.ID)
return err
})
if err != nil {
@ -306,6 +321,7 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector storage.
selector = newExistingSelector(m.index, sector.ID, storiface.FTUnsealed, false)
log.Debugf("schedule read piece for sector %d, offset %d, size %d", sector.ID, offset, size)
err = m.sched.Schedule(ctx, sector, sealtasks.TTReadUnsealed, selector, m.schedFetch(sector, storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove),
m.readPiece(sink, sector, offset, size, &readOk))
if err != nil {
@ -316,6 +332,7 @@ func (m *Manager) ReadPiece(ctx context.Context, sink io.Writer, sector storage.
return xerrors.Errorf("failed to read unsealed piece")
}
log.Debugf("completed read of piece in sector %d, offset %d, size %d", sector.ID, offset, size)
return nil
}

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