Merge branch 'testnet/3' into feat/specs-actors

This commit is contained in:
Łukasz Magiera 2020-02-24 18:32:02 +01:00
commit d787aa5007
92 changed files with 1813 additions and 647 deletions

View File

@ -7,6 +7,9 @@ executors:
docker: docker:
- image: circleci/golang:1.13 - image: circleci/golang:1.13
resource_class: 2xlarge resource_class: 2xlarge
ubuntu:
docker:
- image: ubuntu:19.10
commands: commands:
install-deps: install-deps:
@ -24,6 +27,8 @@ commands:
description: is a darwin build environment? description: is a darwin build environment?
type: boolean type: boolean
steps: steps:
- checkout
- git_fetch_all_tags
- checkout - checkout
- when: - when:
condition: << parameters.linux >> condition: << parameters.linux >>
@ -46,7 +51,27 @@ commands:
key: 'v20-1k-lotus-params' key: 'v20-1k-lotus-params'
paths: paths:
- /var/tmp/filecoin-proof-parameters/ - /var/tmp/filecoin-proof-parameters/
install_ipfs:
steps:
- run: |
apt update
apt install -y wget
wget https://github.com/ipfs/go-ipfs/releases/download/v0.4.22/go-ipfs_v0.4.22_linux-amd64.tar.gz
wget https://github.com/ipfs/go-ipfs/releases/download/v0.4.22/go-ipfs_v0.4.22_linux-amd64.tar.gz.sha512
if [ "$(sha512sum go-ipfs_v0.4.22_linux-amd64.tar.gz)" != "$(cat go-ipfs_v0.4.22_linux-amd64.tar.gz.sha512)" ]
then
echo "ipfs failed checksum check"
exit 1
fi
tar -xf go-ipfs_v0.4.22_linux-amd64.tar.gz
mv go-ipfs/ipfs /usr/local/bin/ipfs
chmod +x /usr/local/bin/ipfs
git_fetch_all_tags:
steps:
- run:
name: fetch all tags
command: |
git fetch --all
jobs: jobs:
mod-tidy-check: mod-tidy-check:
@ -74,6 +99,13 @@ jobs:
path: lotus path: lotus
- store_artifacts: - store_artifacts:
path: lotus-storage-miner path: lotus-storage-miner
- store_artifacts:
path: lotus-seal-worker
- run: mkdir linux && mv lotus lotus-storage-miner lotus-seal-worker linux/
- persist_to_workspace:
root: "."
paths:
- linux
test: &test test: &test
description: | description: |
@ -153,7 +185,7 @@ jobs:
- "~/go/src/github.com" - "~/go/src/github.com"
- "~/go/src/golang.org" - "~/go/src/golang.org"
test-short: test-short:
<<: *test <<: *test
build-macos: build-macos:
@ -196,6 +228,13 @@ jobs:
path: lotus path: lotus
- store_artifacts: - store_artifacts:
path: lotus-storage-miner path: lotus-storage-miner
- store_artifacts:
path: lotus-seal-worker
- run: mkdir darwin && mv lotus lotus-storage-miner lotus-seal-worker darwin/
- persist_to_workspace:
root: "."
paths:
- darwin
- save_cache: - save_cache:
name: save cargo cache name: save cargo cache
key: v3-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.sum" }} key: v3-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.sum" }}
@ -246,6 +285,26 @@ jobs:
lint-all: lint-all:
<<: *lint <<: *lint
publish:
description: publish binary artifacts
executor: ubuntu
steps:
- run:
name: Install git jq curl
command: apt update && apt install -y git jq curl
- checkout
- git_fetch_all_tags
- checkout
- install_ipfs
- attach_workspace:
at: "."
- run:
name: Create bundles
command: ./scripts/build-bundle.sh
- run:
name: Publish release
command: ./scripts/publish-release.sh
workflows: workflows:
version: 2.1 version: 2.1
@ -255,8 +314,38 @@ workflows:
args: "--new-from-rev origin/master" args: "--new-from-rev origin/master"
- test: - test:
codecov-upload: true codecov-upload: true
- mod-tidy-check
- test-short: - test-short:
go-test-flags: "--timeout 10m --short" go-test-flags: "--timeout 10m --short"
- mod-tidy-check filters:
- build-all tags:
- build-macos only:
- /^v\d+\.\d+\.\d+$/
- build-all:
requires:
- test-short
filters:
tags:
only:
- /^v\d+\.\d+\.\d+$/
- build-macos:
requires:
- test-short
filters:
branches:
ignore:
- /.*/
tags:
only:
- /^v\d+\.\d+\.\d+$/
- publish:
requires:
- build-all
- build-macos
filters:
branches:
ignore:
- /.*/
tags:
only:
- /^v\d+\.\d+\.\d+$/

3
.gitignore vendored
View File

@ -26,6 +26,9 @@ build/paramfetch.sh
/blocks.svg /blocks.svg
/chainwatch /chainwatch
/chainwatch.db /chainwatch.db
/bundle
/darwin
/linux
*-fuzz.zip *-fuzz.zip
/chain/types/work_msg/ /chain/types/work_msg/

View File

@ -1,7 +1,8 @@
linters: linters:
disable-all: true disable-all: true
enable: enable:
- vet - gofmt
- govet
- goimports - goimports
- misspell - misspell
- goconst - goconst

View File

@ -23,12 +23,16 @@ type Common interface {
NetConnect(context.Context, peer.AddrInfo) error NetConnect(context.Context, peer.AddrInfo) error
NetAddrsListen(context.Context) (peer.AddrInfo, error) NetAddrsListen(context.Context) (peer.AddrInfo, error)
NetDisconnect(context.Context, peer.ID) error NetDisconnect(context.Context, peer.ID) error
NetFindPeer(context.Context, peer.ID) (peer.AddrInfo, error)
// ID returns peerID of libp2p node backing this API // ID returns peerID of libp2p node backing this API
ID(context.Context) (peer.ID, error) ID(context.Context) (peer.ID, error)
// Version provides information about API provider // Version provides information about API provider
Version(context.Context) (Version, error) Version(context.Context) (Version, error)
LogList(context.Context) ([]string, error)
LogSetLevel(context.Context, string, string) error
} }
// Version provides various build-time information // Version provides various build-time information

View File

@ -37,25 +37,26 @@ type FullNode interface {
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error) ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error) ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error)
ChainGetParentMessages(context.Context, cid.Cid) ([]Message, error) ChainGetParentMessages(context.Context, cid.Cid) ([]Message, error)
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, *types.TipSet) (*types.TipSet, error) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
ChainReadObj(context.Context, cid.Cid) ([]byte, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error)
ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHasObj(context.Context, cid.Cid) (bool, error)
ChainSetHead(context.Context, *types.TipSet) error ChainSetHead(context.Context, types.TipSetKey) error
ChainGetGenesis(context.Context) (*types.TipSet, error) ChainGetGenesis(context.Context) (*types.TipSet, error)
ChainTipSetWeight(context.Context, *types.TipSet) (types.BigInt, error) ChainTipSetWeight(context.Context, types.TipSetKey) (types.BigInt, error)
ChainGetNode(ctx context.Context, p string) (interface{}, error) ChainGetNode(ctx context.Context, p string) (interface{}, error)
ChainGetMessage(context.Context, cid.Cid) (*types.Message, error) ChainGetMessage(context.Context, cid.Cid) (*types.Message, error)
ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*store.HeadChange, error) ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*store.HeadChange, error)
ChainExport(context.Context, *types.TipSet) (<-chan []byte, error) ChainExport(context.Context, types.TipSetKey) (<-chan []byte, error)
// syncer // syncer
SyncState(context.Context) (*SyncState, error) SyncState(context.Context) (*SyncState, error)
SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error
SyncIncomingBlocks(ctx context.Context) (<-chan *types.BlockHeader, error) SyncIncomingBlocks(ctx context.Context) (<-chan *types.BlockHeader, error)
SyncMarkBad(ctx context.Context, bcid cid.Cid) error SyncMarkBad(ctx context.Context, bcid cid.Cid) error
SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error)
// messages // messages
MpoolPending(context.Context, *types.TipSet) ([]*types.SignedMessage, error) MpoolPending(context.Context, types.TipSetKey) ([]*types.SignedMessage, error)
MpoolPush(context.Context, *types.SignedMessage) (cid.Cid, error) MpoolPush(context.Context, *types.SignedMessage) (cid.Cid, error)
MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error) // get nonce, sign, push MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error) // get nonce, sign, push
MpoolGetNonce(context.Context, address.Address) (uint64, error) MpoolGetNonce(context.Context, address.Address) (uint64, error)
@ -65,7 +66,7 @@ type FullNode interface {
// miner // miner
MinerCreateBlock(context.Context, address.Address, *types.TipSet, *types.Ticket, *types.EPostProof, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error) MinerCreateBlock(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error)
// // UX ? // // UX ?
@ -103,35 +104,35 @@ type FullNode interface {
//ClientListAsks() []Ask //ClientListAsks() []Ask
// if tipset is nil, we'll use heaviest // if tipset is nil, we'll use heaviest
StateCall(context.Context, *types.Message, *types.TipSet) (*MethodCall, error) StateCall(context.Context, *types.Message, types.TipSetKey) (*MethodCall, error)
StateReplay(context.Context, *types.TipSet, cid.Cid) (*ReplayResults, error) StateReplay(context.Context, types.TipSetKey, cid.Cid) (*ReplayResults, error)
StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
StateReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*ActorState, error) StateReadState(ctx context.Context, act *types.Actor, tsk types.TipSetKey) (*ActorState, error)
StateListMessages(ctx context.Context, match *types.Message, ts *types.TipSet, toht abi.ChainEpoch) ([]cid.Cid, error) StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error)
StateMinerSectors(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error) StateMinerSectors(context.Context, address.Address, types.TipSetKey) ([]*ChainSectorInfo, error)
StateMinerProvingSet(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error) StateMinerProvingSet(context.Context, address.Address, types.TipSetKey) ([]*ChainSectorInfo, error)
StateMinerPower(context.Context, address.Address, *types.TipSet) (MinerPower, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (MinerPower, error)
StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error) StateMinerWorker(context.Context, address.Address, types.TipSetKey) (address.Address, error)
StateMinerPeerID(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) StateMinerPeerID(ctx context.Context, m address.Address, tsk types.TipSetKey) (peer.ID, error)
StateMinerPostState(ctx context.Context, actor address.Address, ts *types.TipSet) (*miner.PoStState, error) StateMinerPostState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*miner.PoStState, error)
StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (abi.SectorSize, error) StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error)
StateMinerFaults(context.Context, address.Address, *types.TipSet) ([]abi.SectorNumber, error) StateMinerFaults(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error)
StatePledgeCollateral(context.Context, *types.TipSet) (types.BigInt, error) StatePledgeCollateral(context.Context, types.TipSetKey) (types.BigInt, error)
StateWaitMsg(context.Context, cid.Cid) (*MsgWait, error) StateWaitMsg(context.Context, cid.Cid) (*MsgWait, error)
StateListMiners(context.Context, *types.TipSet) ([]address.Address, error) StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error)
StateListActors(context.Context, *types.TipSet) ([]address.Address, error) StateListActors(context.Context, types.TipSetKey) ([]address.Address, error)
StateMarketBalance(context.Context, address.Address, *types.TipSet) (MarketBalance, error) StateMarketBalance(context.Context, address.Address, types.TipSetKey) (MarketBalance, error)
StateMarketParticipants(context.Context, *types.TipSet) (map[string]MarketBalance, error) StateMarketParticipants(context.Context, types.TipSetKey) (map[string]MarketBalance, error)
StateMarketDeals(context.Context, *types.TipSet) (map[string]MarketDeal, error) StateMarketDeals(context.Context, types.TipSetKey) (map[string]MarketDeal, error)
StateMarketStorageDeal(context.Context, abi.DealID, *types.TipSet) (*MarketDeal, error) StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*MarketDeal, error)
StateLookupID(context.Context, address.Address, *types.TipSet) (address.Address, error) StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error)
StateChangedActors(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) StateChangedActors(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error)
StateGetReceipt(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateMinerSectorCount(context.Context, address.Address, *types.TipSet) (MinerSectors, error) StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error)
StateCompute(context.Context, abi.ChainEpoch, []*types.Message, *types.TipSet) (cid.Cid, error) StateCompute(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (cid.Cid, error)
MsigGetAvailableBalance(context.Context, address.Address, *types.TipSet) (types.BigInt, error) MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
MarketEnsureAvailable(context.Context, address.Address, types.BigInt) error MarketEnsureAvailable(context.Context, address.Address, types.BigInt) error
// MarketFreeBalance // MarketFreeBalance

View File

@ -33,9 +33,13 @@ type CommonStruct struct {
NetConnect func(context.Context, peer.AddrInfo) error `perm:"write"` NetConnect func(context.Context, peer.AddrInfo) error `perm:"write"`
NetAddrsListen func(context.Context) (peer.AddrInfo, error) `perm:"read"` NetAddrsListen func(context.Context) (peer.AddrInfo, error) `perm:"read"`
NetDisconnect func(context.Context, peer.ID) error `perm:"write"` NetDisconnect func(context.Context, peer.ID) error `perm:"write"`
NetFindPeer func(context.Context, peer.ID) (peer.AddrInfo, error) `perm:"read"`
ID func(context.Context) (peer.ID, error) `perm:"read"` ID func(context.Context) (peer.ID, error) `perm:"read"`
Version func(context.Context) (api.Version, error) `perm:"read"` Version func(context.Context) (api.Version, error) `perm:"read"`
LogList func(context.Context) ([]string, error) `perm:"write"`
LogSetLevel func(context.Context, string, string) error `perm:"write"`
} }
} }
@ -52,29 +56,30 @@ type FullNodeStruct struct {
ChainGetBlockMessages func(context.Context, cid.Cid) (*api.BlockMessages, error) `perm:"read"` ChainGetBlockMessages func(context.Context, cid.Cid) (*api.BlockMessages, error) `perm:"read"`
ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"` ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"`
ChainGetTipSetByHeight func(context.Context, abi.ChainEpoch, *types.TipSet) (*types.TipSet, error) `perm:"read"` ChainGetTipSetByHeight func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"` ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"` ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"`
ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"` ChainSetHead func(context.Context, types.TipSetKey) error `perm:"admin"`
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"` ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainTipSetWeight func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"` ChainTipSetWeight func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"`
ChainGetNode func(ctx context.Context, p string) (interface{}, error) `perm:"read"` ChainGetNode func(ctx context.Context, p string) (interface{}, error) `perm:"read"`
ChainGetMessage func(context.Context, cid.Cid) (*types.Message, error) `perm:"read"` ChainGetMessage func(context.Context, cid.Cid) (*types.Message, error) `perm:"read"`
ChainGetPath func(context.Context, types.TipSetKey, types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"` ChainGetPath func(context.Context, types.TipSetKey, types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"`
ChainExport func(context.Context, *types.TipSet) (<-chan []byte, error) `perm:"read"` ChainExport func(context.Context, types.TipSetKey) (<-chan []byte, error) `perm:"read"`
SyncState func(context.Context) (*api.SyncState, error) `perm:"read"` SyncState func(context.Context) (*api.SyncState, error) `perm:"read"`
SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"` SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"`
SyncIncomingBlocks func(ctx context.Context) (<-chan *types.BlockHeader, error) `perm:"read"` SyncIncomingBlocks func(ctx context.Context) (<-chan *types.BlockHeader, error) `perm:"read"`
SyncMarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"` SyncMarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"`
SyncCheckBad func(ctx context.Context, bcid cid.Cid) (string, error) `perm:"read"`
MpoolPending func(context.Context, *types.TipSet) ([]*types.SignedMessage, error) `perm:"read"` MpoolPending func(context.Context, types.TipSetKey) ([]*types.SignedMessage, error) `perm:"read"`
MpoolPush func(context.Context, *types.SignedMessage) (cid.Cid, error) `perm:"write"` MpoolPush func(context.Context, *types.SignedMessage) (cid.Cid, error) `perm:"write"`
MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"` MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"` MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"` MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"`
MinerCreateBlock func(context.Context, address.Address, *types.TipSet, *types.Ticket, *types.EPostProof, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error) `perm:"write"` MinerCreateBlock func(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error) `perm:"write"`
WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"` WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"`
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"` WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
@ -97,34 +102,34 @@ type FullNodeStruct struct {
ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, path string) error `perm:"admin"` ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, path string) error `perm:"admin"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) `perm:"read"` ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) `perm:"read"` StateMinerSectors func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) `perm:"read"` StateMinerProvingSet func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, *types.TipSet) (api.MinerPower, error) `perm:"read"` StateMinerPower func(context.Context, address.Address, types.TipSetKey) (api.MinerPower, error) `perm:"read"`
StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"` StateMinerWorker func(context.Context, address.Address, types.TipSetKey) (address.Address, error) `perm:"read"`
StateMinerPeerID func(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) `perm:"read"` StateMinerPeerID func(ctx context.Context, m address.Address, tsk types.TipSetKey) (peer.ID, error) `perm:"read"`
StateMinerPostState func(ctx context.Context, actor address.Address, ts *types.TipSet) (*miner.PoStState, error) `perm:"read"` StateMinerPostState func(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*miner.PoStState, error) `perm:"read"`
StateMinerSectorSize func(context.Context, address.Address, *types.TipSet) (abi.SectorSize, error) `perm:"read"` StateMinerSectorSize func(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error) `perm:"read"`
StateMinerFaults func(context.Context, address.Address, *types.TipSet) ([]abi.SectorNumber, error) `perm:"read"` StateMinerFaults func(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error) `perm:"read"`
StateCall func(context.Context, *types.Message, *types.TipSet) (*api.MethodCall, error) `perm:"read"` StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.MethodCall, error) `perm:"read"`
StateReplay func(context.Context, *types.TipSet, cid.Cid) (*api.ReplayResults, error) `perm:"read"` StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.ReplayResults, error) `perm:"read"`
StateGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"` StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"`
StateReadState func(context.Context, *types.Actor, *types.TipSet) (*api.ActorState, error) `perm:"read"` StateReadState func(context.Context, *types.Actor, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
StatePledgeCollateral func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"` StatePledgeCollateral func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"`
StateWaitMsg func(context.Context, cid.Cid) (*api.MsgWait, error) `perm:"read"` StateWaitMsg func(context.Context, cid.Cid) (*api.MsgWait, error) `perm:"read"`
StateListMiners func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"` StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
StateListActors func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"` StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
StateMarketBalance func(context.Context, address.Address, *types.TipSet) (api.MarketBalance, error) `perm:"read"` StateMarketBalance func(context.Context, address.Address, types.TipSetKey) (api.MarketBalance, error) `perm:"read"`
StateMarketParticipants func(context.Context, *types.TipSet) (map[string]api.MarketBalance, error) `perm:"read"` StateMarketParticipants func(context.Context, types.TipSetKey) (map[string]api.MarketBalance, error) `perm:"read"`
StateMarketDeals func(context.Context, *types.TipSet) (map[string]api.MarketDeal, error) `perm:"read"` StateMarketDeals func(context.Context, types.TipSetKey) (map[string]api.MarketDeal, error) `perm:"read"`
StateMarketStorageDeal func(context.Context, abi.DealID, *types.TipSet) (*api.MarketDeal, error) `perm:"read"` StateMarketStorageDeal func(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error) `perm:"read"`
StateLookupID func(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) `perm:"read"` StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) `perm:"read"`
StateChangedActors func(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) `perm:"read"` StateChangedActors func(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) `perm:"read"`
StateGetReceipt func(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"` StateGetReceipt func(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"`
StateMinerSectorCount func(context.Context, address.Address, *types.TipSet) (api.MinerSectors, error) `perm:"read"` StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"`
StateListMessages func(ctx context.Context, match *types.Message, ts *types.TipSet, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"`
StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, *types.TipSet) (cid.Cid, error) `perm:"read"` StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (cid.Cid, error) `perm:"read"`
MsigGetAvailableBalance func(context.Context, address.Address, *types.TipSet) (types.BigInt, error) `perm:"read"` MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
MarketEnsureAvailable func(context.Context, address.Address, types.BigInt) error `perm:"sign"` MarketEnsureAvailable func(context.Context, address.Address, types.BigInt) error `perm:"sign"`
@ -144,8 +149,8 @@ type FullNodeStruct struct {
} }
} }
func (c *FullNodeStruct) StateMinerSectorCount(ctx context.Context, addr address.Address, ts *types.TipSet) (api.MinerSectors, error) { func (c *FullNodeStruct) StateMinerSectorCount(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MinerSectors, error) {
return c.Internal.StateMinerSectorCount(ctx, addr, ts) return c.Internal.StateMinerSectorCount(ctx, addr, tsk)
} }
type StorageMinerStruct struct { type StorageMinerStruct struct {
@ -197,6 +202,10 @@ func (c *CommonStruct) NetDisconnect(ctx context.Context, p peer.ID) error {
return c.Internal.NetDisconnect(ctx, p) return c.Internal.NetDisconnect(ctx, p)
} }
func (c *CommonStruct) NetFindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) {
return c.Internal.NetFindPeer(ctx, p)
}
// ID implements API.ID // ID implements API.ID
func (c *CommonStruct) ID(ctx context.Context) (peer.ID, error) { func (c *CommonStruct) ID(ctx context.Context) (peer.ID, error) {
return c.Internal.ID(ctx) return c.Internal.ID(ctx)
@ -207,6 +216,14 @@ func (c *CommonStruct) Version(ctx context.Context) (api.Version, error) {
return c.Internal.Version(ctx) return c.Internal.Version(ctx)
} }
func (c *CommonStruct) LogList(ctx context.Context) ([]string, error) {
return c.Internal.LogList(ctx)
}
func (c *CommonStruct) LogSetLevel(ctx context.Context, group, level string) error {
return c.Internal.LogSetLevel(ctx, group, level)
}
func (c *FullNodeStruct) ClientListImports(ctx context.Context) ([]api.Import, error) { func (c *FullNodeStruct) ClientListImports(ctx context.Context) ([]api.Import, error) {
return c.Internal.ClientListImports(ctx) return c.Internal.ClientListImports(ctx)
} }
@ -242,8 +259,8 @@ func (c *FullNodeStruct) ClientQueryAsk(ctx context.Context, p peer.ID, miner ad
return c.Internal.ClientQueryAsk(ctx, p, miner) return c.Internal.ClientQueryAsk(ctx, p, miner)
} }
func (c *FullNodeStruct) MpoolPending(ctx context.Context, ts *types.TipSet) ([]*types.SignedMessage, error) { func (c *FullNodeStruct) MpoolPending(ctx context.Context, tsk types.TipSetKey) ([]*types.SignedMessage, error) {
return c.Internal.MpoolPending(ctx, ts) return c.Internal.MpoolPending(ctx, tsk)
} }
func (c *FullNodeStruct) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) { func (c *FullNodeStruct) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) {
@ -258,7 +275,7 @@ func (c *FullNodeStruct) MpoolSub(ctx context.Context) (<-chan api.MpoolUpdate,
return c.Internal.MpoolSub(ctx) return c.Internal.MpoolSub(ctx)
} }
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) { func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base types.TipSetKey, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts) return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts)
} }
@ -270,8 +287,8 @@ func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, tsk types.TipSe
return c.Internal.ChainGetRandomness(ctx, tsk, personalization, randEpoch, entropy) return c.Internal.ChainGetRandomness(ctx, tsk, personalization, randEpoch, entropy)
} }
func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, ts *types.TipSet) (*types.TipSet, error) { func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
return c.Internal.ChainGetTipSetByHeight(ctx, h, ts) return c.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
} }
func (c *FullNodeStruct) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) { func (c *FullNodeStruct) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
@ -350,16 +367,16 @@ func (c *FullNodeStruct) ChainHasObj(ctx context.Context, o cid.Cid) (bool, erro
return c.Internal.ChainHasObj(ctx, o) return c.Internal.ChainHasObj(ctx, o)
} }
func (c *FullNodeStruct) ChainSetHead(ctx context.Context, ts *types.TipSet) error { func (c *FullNodeStruct) ChainSetHead(ctx context.Context, tsk types.TipSetKey) error {
return c.Internal.ChainSetHead(ctx, ts) return c.Internal.ChainSetHead(ctx, tsk)
} }
func (c *FullNodeStruct) ChainGetGenesis(ctx context.Context) (*types.TipSet, error) { func (c *FullNodeStruct) ChainGetGenesis(ctx context.Context) (*types.TipSet, error) {
return c.Internal.ChainGetGenesis(ctx) return c.Internal.ChainGetGenesis(ctx)
} }
func (c *FullNodeStruct) ChainTipSetWeight(ctx context.Context, ts *types.TipSet) (types.BigInt, error) { func (c *FullNodeStruct) ChainTipSetWeight(ctx context.Context, tsk types.TipSetKey) (types.BigInt, error) {
return c.Internal.ChainTipSetWeight(ctx, ts) return c.Internal.ChainTipSetWeight(ctx, tsk)
} }
func (c *FullNodeStruct) ChainGetNode(ctx context.Context, p string) (interface{}, error) { func (c *FullNodeStruct) ChainGetNode(ctx context.Context, p string) (interface{}, error) {
@ -374,8 +391,8 @@ func (c *FullNodeStruct) ChainGetPath(ctx context.Context, from types.TipSetKey,
return c.Internal.ChainGetPath(ctx, from, to) return c.Internal.ChainGetPath(ctx, from, to)
} }
func (c *FullNodeStruct) ChainExport(ctx context.Context, ts *types.TipSet) (<-chan []byte, error) { func (c *FullNodeStruct) ChainExport(ctx context.Context, tsk types.TipSetKey) (<-chan []byte, error) {
return c.Internal.ChainExport(ctx, ts) return c.Internal.ChainExport(ctx, tsk)
} }
func (c *FullNodeStruct) SyncState(ctx context.Context) (*api.SyncState, error) { func (c *FullNodeStruct) SyncState(ctx context.Context) (*api.SyncState, error) {
@ -394,107 +411,111 @@ func (c *FullNodeStruct) SyncMarkBad(ctx context.Context, bcid cid.Cid) error {
return c.Internal.SyncMarkBad(ctx, bcid) return c.Internal.SyncMarkBad(ctx, bcid)
} }
func (c *FullNodeStruct) StateMinerSectors(ctx context.Context, addr address.Address, ts *types.TipSet) ([]*api.ChainSectorInfo, error) { func (c *FullNodeStruct) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) {
return c.Internal.StateMinerSectors(ctx, addr, ts) return c.Internal.SyncCheckBad(ctx, bcid)
} }
func (c *FullNodeStruct) StateMinerProvingSet(ctx context.Context, addr address.Address, ts *types.TipSet) ([]*api.ChainSectorInfo, error) { func (c *FullNodeStruct) StateMinerSectors(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.ChainSectorInfo, error) {
return c.Internal.StateMinerProvingSet(ctx, addr, ts) return c.Internal.StateMinerSectors(ctx, addr, tsk)
} }
func (c *FullNodeStruct) StateMinerPower(ctx context.Context, a address.Address, ts *types.TipSet) (api.MinerPower, error) { func (c *FullNodeStruct) StateMinerProvingSet(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.ChainSectorInfo, error) {
return c.Internal.StateMinerPower(ctx, a, ts) return c.Internal.StateMinerProvingSet(ctx, addr, tsk)
} }
func (c *FullNodeStruct) StateMinerWorker(ctx context.Context, m address.Address, ts *types.TipSet) (address.Address, error) { func (c *FullNodeStruct) StateMinerPower(ctx context.Context, a address.Address, tsk types.TipSetKey) (api.MinerPower, error) {
return c.Internal.StateMinerWorker(ctx, m, ts) return c.Internal.StateMinerPower(ctx, a, tsk)
} }
func (c *FullNodeStruct) StateMinerPeerID(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) { func (c *FullNodeStruct) StateMinerWorker(ctx context.Context, m address.Address, tsk types.TipSetKey) (address.Address, error) {
return c.Internal.StateMinerPeerID(ctx, m, ts) return c.Internal.StateMinerWorker(ctx, m, tsk)
} }
func (c *FullNodeStruct) StateMinerPostState(ctx context.Context, actor address.Address, ts *types.TipSet) (*miner.PoStState, error) { func (c *FullNodeStruct) StateMinerPeerID(ctx context.Context, m address.Address, tsk types.TipSetKey) (peer.ID, error) {
return c.Internal.StateMinerPostState(ctx, actor, ts) return c.Internal.StateMinerPeerID(ctx, m, tsk)
} }
func (c *FullNodeStruct) StateMinerSectorSize(ctx context.Context, actor address.Address, ts *types.TipSet) (abi.SectorSize, error) { func (c *FullNodeStruct) StateMinerPostState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*miner.PoStState, error) {
return c.Internal.StateMinerSectorSize(ctx, actor, ts) return c.Internal.StateMinerPostState(ctx, actor, tsk)
} }
func (c *FullNodeStruct) StateMinerFaults(ctx context.Context, actor address.Address, ts *types.TipSet) ([]abi.SectorNumber, error) { func (c *FullNodeStruct) StateMinerSectorSize(ctx context.Context, actor address.Address, tsk types.TipSetKey) (abi.SectorSize, error) {
return c.Internal.StateMinerFaults(ctx, actor, ts) return c.Internal.StateMinerSectorSize(ctx, actor, tsk)
} }
func (c *FullNodeStruct) StateCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.MethodCall, error) { func (c *FullNodeStruct) StateMinerFaults(ctx context.Context, actor address.Address, tsk types.TipSetKey) ([]abi.SectorNumber, error) {
return c.Internal.StateCall(ctx, msg, ts) return c.Internal.StateMinerFaults(ctx, actor, tsk)
} }
func (c *FullNodeStruct) StateReplay(ctx context.Context, ts *types.TipSet, mc cid.Cid) (*api.ReplayResults, error) { func (c *FullNodeStruct) StateCall(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (*api.MethodCall, error) {
return c.Internal.StateReplay(ctx, ts, mc) return c.Internal.StateCall(ctx, msg, tsk)
} }
func (c *FullNodeStruct) StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) { func (c *FullNodeStruct) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.ReplayResults, error) {
return c.Internal.StateGetActor(ctx, actor, ts) return c.Internal.StateReplay(ctx, tsk, mc)
} }
func (c *FullNodeStruct) StateReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*api.ActorState, error) { func (c *FullNodeStruct) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
return c.Internal.StateReadState(ctx, act, ts) return c.Internal.StateGetActor(ctx, actor, tsk)
} }
func (c *FullNodeStruct) StatePledgeCollateral(ctx context.Context, ts *types.TipSet) (types.BigInt, error) { func (c *FullNodeStruct) StateReadState(ctx context.Context, act *types.Actor, tsk types.TipSetKey) (*api.ActorState, error) {
return c.Internal.StatePledgeCollateral(ctx, ts) return c.Internal.StateReadState(ctx, act, tsk)
}
func (c *FullNodeStruct) StatePledgeCollateral(ctx context.Context, tsk types.TipSetKey) (types.BigInt, error) {
return c.Internal.StatePledgeCollateral(ctx, tsk)
} }
func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid) (*api.MsgWait, error) { func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid) (*api.MsgWait, error) {
return c.Internal.StateWaitMsg(ctx, msgc) return c.Internal.StateWaitMsg(ctx, msgc)
} }
func (c *FullNodeStruct) StateListMiners(ctx context.Context, ts *types.TipSet) ([]address.Address, error) { func (c *FullNodeStruct) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
return c.Internal.StateListMiners(ctx, ts) return c.Internal.StateListMiners(ctx, tsk)
} }
func (c *FullNodeStruct) StateListActors(ctx context.Context, ts *types.TipSet) ([]address.Address, error) { func (c *FullNodeStruct) StateListActors(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
return c.Internal.StateListActors(ctx, ts) return c.Internal.StateListActors(ctx, tsk)
} }
func (c *FullNodeStruct) StateMarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (api.MarketBalance, error) { func (c *FullNodeStruct) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
return c.Internal.StateMarketBalance(ctx, addr, ts) return c.Internal.StateMarketBalance(ctx, addr, tsk)
} }
func (c *FullNodeStruct) StateMarketParticipants(ctx context.Context, ts *types.TipSet) (map[string]api.MarketBalance, error) { func (c *FullNodeStruct) StateMarketParticipants(ctx context.Context, tsk types.TipSetKey) (map[string]api.MarketBalance, error) {
return c.Internal.StateMarketParticipants(ctx, ts) return c.Internal.StateMarketParticipants(ctx, tsk)
} }
func (c *FullNodeStruct) StateMarketDeals(ctx context.Context, ts *types.TipSet) (map[string]api.MarketDeal, error) { func (c *FullNodeStruct) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (map[string]api.MarketDeal, error) {
return c.Internal.StateMarketDeals(ctx, ts) return c.Internal.StateMarketDeals(ctx, tsk)
} }
func (c *FullNodeStruct) StateMarketStorageDeal(ctx context.Context, dealid abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) { func (c *FullNodeStruct) StateMarketStorageDeal(ctx context.Context, dealid abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
return c.Internal.StateMarketStorageDeal(ctx, dealid, ts) return c.Internal.StateMarketStorageDeal(ctx, dealid, tsk)
} }
func (c *FullNodeStruct) StateLookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) { func (c *FullNodeStruct) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
return c.Internal.StateLookupID(ctx, addr, ts) return c.Internal.StateLookupID(ctx, addr, tsk)
} }
func (c *FullNodeStruct) StateChangedActors(ctx context.Context, olnstate cid.Cid, newstate cid.Cid) (map[string]types.Actor, error) { func (c *FullNodeStruct) StateChangedActors(ctx context.Context, olnstate cid.Cid, newstate cid.Cid) (map[string]types.Actor, error) {
return c.Internal.StateChangedActors(ctx, olnstate, newstate) return c.Internal.StateChangedActors(ctx, olnstate, newstate)
} }
func (c *FullNodeStruct) StateGetReceipt(ctx context.Context, msg cid.Cid, ts *types.TipSet) (*types.MessageReceipt, error) { func (c *FullNodeStruct) StateGetReceipt(ctx context.Context, msg cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) {
return c.Internal.StateGetReceipt(ctx, msg, ts) return c.Internal.StateGetReceipt(ctx, msg, tsk)
} }
func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *types.Message, ts *types.TipSet, toht abi.ChainEpoch) ([]cid.Cid, error) { func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) {
return c.Internal.StateListMessages(ctx, match, ts, toht) return c.Internal.StateListMessages(ctx, match, tsk, toht)
} }
func (c *FullNodeStruct) StateCompute(ctx context.Context, height abi.ChainEpoch, msgs []*types.Message, ts *types.TipSet) (cid.Cid, error) { func (c *FullNodeStruct) StateCompute(ctx context.Context, height abi.ChainEpoch, msgs []*types.Message, tsk types.TipSetKey) (cid.Cid, error) {
return c.Internal.StateCompute(ctx, height, msgs, ts) return c.Internal.StateCompute(ctx, height, msgs, tsk)
} }
func (c *FullNodeStruct) MsigGetAvailableBalance(ctx context.Context, a address.Address, ts *types.TipSet) (types.BigInt, error) { func (c *FullNodeStruct) MsigGetAvailableBalance(ctx context.Context, a address.Address, tsk types.TipSetKey) (types.BigInt, error) {
return c.Internal.MsigGetAvailableBalance(ctx, a, ts) return c.Internal.MsigGetAvailableBalance(ctx, a, tsk)
} }
func (c *FullNodeStruct) MarketEnsureAvailable(ctx context.Context, addr address.Address, amt types.BigInt) error { func (c *FullNodeStruct) MarketEnsureAvailable(ctx context.Context, addr address.Address, amt types.BigInt) error {

View File

@ -23,6 +23,8 @@ func SupportedSectorSize(ssize abi.SectorSize) bool {
return false return false
} }
const SectorChallengeRatioDiv = 25
// ///// // /////
// Payments // Payments

View File

@ -21,10 +21,15 @@ func NewBadBlockCache() *BadBlockCache {
} }
} }
func (bts *BadBlockCache) Add(c cid.Cid) { func (bts *BadBlockCache) Add(c cid.Cid, reason string) {
bts.badBlocks.Add(c, nil) bts.badBlocks.Add(c, reason)
} }
func (bts *BadBlockCache) Has(c cid.Cid) bool { func (bts *BadBlockCache) Has(c cid.Cid) (string, bool) {
return bts.badBlocks.Contains(c) rval, ok := bts.badBlocks.Get(c)
if !ok {
return "", false
}
return rval.(string), true
} }

View File

@ -34,10 +34,10 @@ type heightHandler struct {
type eventApi interface { type eventApi interface {
ChainNotify(context.Context) (<-chan []*store.HeadChange, error) ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, *types.TipSet) (*types.TipSet, error) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
StateGetReceipt(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) // optional / for CalledMsg StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // optional / for CalledMsg
} }
type Events struct { type Events struct {

View File

@ -193,7 +193,7 @@ func (e *calledEvents) applyWithConfidence(ts *types.TipSet) {
continue continue
} }
rec, err := e.cs.StateGetReceipt(e.ctx, event.msg.Cid(), ts) rec, err := e.cs.StateGetReceipt(e.ctx, event.msg.Cid(), ts.Key())
if err != nil { if err != nil {
log.Error(err) log.Error(err)
return return

View File

@ -43,15 +43,15 @@ type fakeCS struct {
sub func(rev, app []*types.TipSet) sub func(rev, app []*types.TipSet)
} }
func (fcs *fakeCS) StateGetReceipt(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) { func (fcs *fakeCS) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) {
return nil, nil return nil, nil
} }
func (fcs *fakeCS) StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) { func (fcs *fakeCS) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
panic("Not Implemented") panic("Not Implemented")
} }
func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, *types.TipSet) (*types.TipSet, error) { func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) {
panic("Not Implemented") panic("Not Implemented")
} }

View File

@ -9,7 +9,7 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
type tsByHFunc func(context.Context, abi.ChainEpoch, *types.TipSet) (*types.TipSet, error) type tsByHFunc func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
// tipSetCache implements a simple ring-buffer cache to keep track of recent // tipSetCache implements a simple ring-buffer cache to keep track of recent
// tipsets // tipsets
@ -94,7 +94,7 @@ func (tsc *tipSetCache) getNonNull(height abi.ChainEpoch) (*types.TipSet, error)
func (tsc *tipSetCache) get(height abi.ChainEpoch) (*types.TipSet, error) { func (tsc *tipSetCache) get(height abi.ChainEpoch) (*types.TipSet, error) {
if tsc.len == 0 { if tsc.len == 0 {
log.Warnf("tipSetCache.get: cache is empty, requesting from storage (h=%d)", height) log.Warnf("tipSetCache.get: cache is empty, requesting from storage (h=%d)", height)
return tsc.storage(context.TODO(), height, nil) return tsc.storage(context.TODO(), height, types.EmptyTSK)
} }
headH := tsc.cache[tsc.start].Height() headH := tsc.cache[tsc.start].Height()
@ -114,7 +114,7 @@ func (tsc *tipSetCache) get(height abi.ChainEpoch) (*types.TipSet, error) {
if height < tail.Height() { if height < tail.Height() {
log.Warnf("tipSetCache.get: requested tipset not in cache, requesting from storage (h=%d; tail=%d)", height, tail.Height()) log.Warnf("tipSetCache.get: requested tipset not in cache, requesting from storage (h=%d; tail=%d)", height, tail.Height())
return tsc.storage(context.TODO(), height, tail) return tsc.storage(context.TODO(), height, tail.Key())
} }
return tsc.cache[normalModulo(tsc.start-int(headH-height), clen)], nil return tsc.cache[normalModulo(tsc.start-int(headH-height), clen)], nil

View File

@ -13,7 +13,7 @@ import (
) )
func TestTsCache(t *testing.T) { func TestTsCache(t *testing.T) {
tsc := newTSCache(50, func(context.Context, abi.ChainEpoch, *types.TipSet) (*types.TipSet, error) { tsc := newTSCache(50, func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) {
t.Fatal("storage call") t.Fatal("storage call")
return &types.TipSet{}, nil return &types.TipSet{}, nil
}) })
@ -56,7 +56,7 @@ func TestTsCache(t *testing.T) {
} }
func TestTsCacheNulls(t *testing.T) { func TestTsCacheNulls(t *testing.T) {
tsc := newTSCache(50, func(context.Context, abi.ChainEpoch, *types.TipSet) (*types.TipSet, error) { tsc := newTSCache(50, func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) {
t.Fatal("storage call") t.Fatal("storage call")
return &types.TipSet{}, nil return &types.TipSet{}, nil
}) })

View File

@ -13,7 +13,7 @@ func (e *calledEvents) CheckMsg(ctx context.Context, smsg store.ChainMsg, hnd Ca
msg := smsg.VMMessage() msg := smsg.VMMessage()
return func(ts *types.TipSet) (done bool, more bool, err error) { return func(ts *types.TipSet) (done bool, more bool, err error) {
fa, err := e.cs.StateGetActor(ctx, msg.From, ts) fa, err := e.cs.StateGetActor(ctx, msg.From, ts.Key())
if err != nil { if err != nil {
return false, true, err return false, true, err
} }
@ -23,7 +23,7 @@ func (e *calledEvents) CheckMsg(ctx context.Context, smsg store.ChainMsg, hnd Ca
return false, true, nil return false, true, nil
} }
rec, err := e.cs.StateGetReceipt(ctx, smsg.VMMessage().Cid(), ts) rec, err := e.cs.StateGetReceipt(ctx, smsg.VMMessage().Cid(), ts.Key())
if err != nil { if err != nil {
return false, true, xerrors.Errorf("getting receipt in CheckMsg: %w", err) return false, true, xerrors.Errorf("getting receipt in CheckMsg: %w", err)
} }

View File

@ -444,13 +444,13 @@ func (cg *ChainGen) YieldRepo() (repo.Repo, error) {
type MiningCheckAPI interface { type MiningCheckAPI interface {
ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error)
StateMinerPower(context.Context, address.Address, *types.TipSet) (api.MinerPower, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (api.MinerPower, error)
StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error) StateMinerWorker(context.Context, address.Address, types.TipSetKey) (address.Address, error)
StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (abi.SectorSize, error) StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error)
StateMinerProvingSet(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) StateMinerProvingSet(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error)
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error) WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error)
} }
@ -469,7 +469,11 @@ func (mca mca) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, pers
return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), personalization, int64(randEpoch), entropy) return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), personalization, int64(randEpoch), entropy)
} }
func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, ts *types.TipSet) (api.MinerPower, error) { func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (api.MinerPower, error) {
ts, err := mca.sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return api.MinerPower{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
mpow, tpow, err := stmgr.GetPower(ctx, mca.sm, ts, maddr) mpow, tpow, err := stmgr.GetPower(ctx, mca.sm, ts, maddr)
if err != nil { if err != nil {
return api.MinerPower{}, err return api.MinerPower{}, err
@ -481,15 +485,27 @@ func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, ts *t
}, err }, err
} }
func (mca mca) StateMinerWorker(ctx context.Context, maddr address.Address, ts *types.TipSet) (address.Address, error) { func (mca mca) StateMinerWorker(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (address.Address, error) {
ts, err := mca.sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return address.Undef, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetMinerWorkerRaw(ctx, mca.sm, ts.ParentState(), maddr) return stmgr.GetMinerWorkerRaw(ctx, mca.sm, ts.ParentState(), maddr)
} }
func (mca mca) StateMinerSectorSize(ctx context.Context, maddr address.Address, ts *types.TipSet) (abi.SectorSize, error) { func (mca mca) StateMinerSectorSize(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (abi.SectorSize, error) {
ts, err := mca.sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return 0, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetMinerSectorSize(ctx, mca.sm, ts, maddr) return stmgr.GetMinerSectorSize(ctx, mca.sm, ts, maddr)
} }
func (mca mca) StateMinerProvingSet(ctx context.Context, maddr address.Address, ts *types.TipSet) ([]*api.ChainSectorInfo, error) { func (mca mca) StateMinerProvingSet(ctx context.Context, maddr address.Address, tsk types.TipSetKey) ([]*api.ChainSectorInfo, error) {
ts, err := mca.sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetMinerProvingSet(ctx, mca.sm, ts, maddr) return stmgr.GetMinerProvingSet(ctx, mca.sm, ts, maddr)
} }
@ -533,7 +549,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
return nil, xerrors.Errorf("chain get randomness: %w", err) return nil, xerrors.Errorf("chain get randomness: %w", err)
} }
mworker, err := a.StateMinerWorker(ctx, miner, ts) mworker, err := a.StateMinerWorker(ctx, miner, ts.Key())
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to get miner worker: %w", err) return nil, xerrors.Errorf("failed to get miner worker: %w", err)
} }
@ -543,7 +559,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
return nil, xerrors.Errorf("failed to compute VRF: %w", err) return nil, xerrors.Errorf("failed to compute VRF: %w", err)
} }
pset, err := a.StateMinerProvingSet(ctx, miner, ts) pset, err := a.StateMinerProvingSet(ctx, miner, ts.Key())
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to load proving set for miner: %w", err) return nil, xerrors.Errorf("failed to load proving set for miner: %w", err)
} }
@ -572,12 +588,12 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
return nil, xerrors.Errorf("failed to generate electionPoSt candidates: %w", err) return nil, xerrors.Errorf("failed to generate electionPoSt candidates: %w", err)
} }
pow, err := a.StateMinerPower(ctx, miner, ts) pow, err := a.StateMinerPower(ctx, miner, ts.Key())
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to check power: %w", err) return nil, xerrors.Errorf("failed to check power: %w", err)
} }
ssize, err := a.StateMinerSectorSize(ctx, miner, ts) ssize, err := a.StateMinerSectorSize(ctx, miner, ts.Key())
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to look up miners sector size: %w", err) return nil, xerrors.Errorf("failed to look up miners sector size: %w", err)
} }

View File

@ -9,6 +9,8 @@ import (
_ "github.com/filecoin-project/lotus/lib/sigs/secp" _ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
) )
func init() { func init() {

View File

@ -96,7 +96,7 @@ func sendHeadNotifs(ctx context.Context, ps *pubsub.PubSub, topic string, chain
case notif := <-notifs: case notif := <-notifs:
n := notif[len(notif)-1] n := notif[len(notif)-1]
w, err := chain.ChainTipSetWeight(ctx, n.Val) w, err := chain.ChainTipSetWeight(ctx, n.Val.Key())
if err != nil { if err != nil {
return err return err
} }

View File

@ -22,6 +22,8 @@ import (
. "github.com/filecoin-project/lotus/chain/stmgr" . "github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
blockstore "github.com/ipfs/go-ipfs-blockstore" blockstore "github.com/ipfs/go-ipfs-blockstore"

View File

@ -1066,3 +1066,11 @@ func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight abi.ChainEpoch) vm.Ran
func (cr *chainRand) GetRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error) { func (cr *chainRand) GetRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error) {
return cr.cs.GetRandomness(ctx, cr.blks, pers, round, entropy) return cr.cs.GetRandomness(ctx, cr.blks, pers, round, entropy)
} }
func (cs *ChainStore) GetTipSetFromKey(tsk types.TipSetKey) (*types.TipSet, error) {
if tsk.IsEmpty() {
return cs.GetHeaviestTipSet(), nil
} else {
return cs.LoadTipSet(tsk)
}
}

View File

@ -4,8 +4,11 @@ import (
"context" "context"
"time" "time"
lru "github.com/hashicorp/golang-lru"
"github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
connmgr "github.com/libp2p/go-libp2p-core/connmgr" connmgr "github.com/libp2p/go-libp2p-core/connmgr"
peer "github.com/libp2p/go-libp2p-peer"
pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
@ -28,15 +31,9 @@ func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *cha
continue continue
} }
blk, err := types.DecodeBlockMsg(msg.GetData()) blk, ok := msg.ValidatorData.(*types.BlockMsg)
if err != nil { if !ok {
log.Error("got invalid block over pubsub: ", err) log.Warnf("pubsub block validator passed on wrong type: %#v", msg.ValidatorData)
continue
}
if len(blk.BlsMessages)+len(blk.SecpkMessages) > build.BlockMessageLimit {
log.Warnf("received block with too many messages over pubsub")
continue
} }
go func() { go func() {
@ -73,6 +70,89 @@ func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *cha
} }
} }
type BlockValidator struct {
peers *lru.TwoQueueCache
killThresh int
recvBlocks *blockReceiptCache
blacklist func(peer.ID)
}
func NewBlockValidator(blacklist func(peer.ID)) *BlockValidator {
p, _ := lru.New2Q(4096)
return &BlockValidator{
peers: p,
killThresh: 5,
blacklist: blacklist,
recvBlocks: newBlockReceiptCache(),
}
}
func (bv *BlockValidator) flagPeer(p peer.ID) {
v, ok := bv.peers.Get(p)
if !ok {
bv.peers.Add(p, int(1))
return
}
val := v.(int)
if val >= bv.killThresh {
bv.blacklist(p)
}
bv.peers.Add(p, v.(int)+1)
}
func (bv *BlockValidator) Validate(ctx context.Context, pid peer.ID, msg *pubsub.Message) bool {
blk, err := types.DecodeBlockMsg(msg.GetData())
if err != nil {
log.Error("got invalid block over pubsub: ", err)
bv.flagPeer(pid)
return false
}
if len(blk.BlsMessages)+len(blk.SecpkMessages) > build.BlockMessageLimit {
log.Warnf("received block with too many messages over pubsub")
bv.flagPeer(pid)
return false
}
if bv.recvBlocks.add(blk.Header.Cid()) > 0 {
// TODO: once these changes propagate to the network, we can consider
// dropping peers who send us the same block multiple times
return false
}
msg.ValidatorData = blk
return true
}
type blockReceiptCache struct {
blocks *lru.TwoQueueCache
}
func newBlockReceiptCache() *blockReceiptCache {
c, _ := lru.New2Q(8192)
return &blockReceiptCache{
blocks: c,
}
}
func (brc *blockReceiptCache) add(bcid cid.Cid) int {
val, ok := brc.blocks.Get(bcid)
if !ok {
brc.blocks.Add(bcid, int(1))
return 0
}
brc.blocks.Add(bcid, val.(int)+1)
return val.(int)
}
func HandleIncomingMessages(ctx context.Context, mpool *messagepool.MessagePool, msub *pubsub.Subscription) { func HandleIncomingMessages(ctx context.Context, mpool *messagepool.MessagePool, msub *pubsub.Subscription) {
for { for {
msg, err := msub.Next(ctx) msg, err := msub.Next(ctx)
@ -85,9 +165,9 @@ func HandleIncomingMessages(ctx context.Context, mpool *messagepool.MessagePool,
continue continue
} }
m, err := types.DecodeSignedMessage(msg.GetData()) m, ok := msg.ValidatorData.(*types.SignedMessage)
if err != nil { if !ok {
log.Errorf("got incorrectly formatted Message: %s", err) log.Errorf("message validator func passed on wrong type: %#v", msg.ValidatorData)
continue continue
} }

View File

@ -121,6 +121,10 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) bool {
} }
for _, b := range fts.Blocks { for _, b := range fts.Blocks {
if reason, ok := syncer.bad.Has(b.Cid()); ok {
log.Warnf("InformNewHead called on block marked as bad: %s (reason: %s)", b.Cid(), reason)
return false
}
if err := syncer.ValidateMsgMeta(b); err != nil { if err := syncer.ValidateMsgMeta(b); err != nil {
log.Warnf("invalid block received: %s", err) log.Warnf("invalid block received: %s", err)
return false return false
@ -450,7 +454,7 @@ func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet)
for _, b := range fts.Blocks { for _, b := range fts.Blocks {
if err := syncer.ValidateBlock(ctx, b); err != nil { if err := syncer.ValidateBlock(ctx, b); err != nil {
if isPermanent(err) { if isPermanent(err) {
syncer.bad.Add(b.Cid()) syncer.bad.Add(b.Cid(), err.Error())
} }
return xerrors.Errorf("validating block %s: %w", b.Cid(), err) return xerrors.Errorf("validating block %s: %w", b.Cid(), err)
} }
@ -870,11 +874,11 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to
) )
for _, pcid := range from.Parents().Cids() { for _, pcid := range from.Parents().Cids() {
if syncer.bad.Has(pcid) { if reason, ok := syncer.bad.Has(pcid); ok {
for _, b := range from.Cids() { for _, b := range from.Cids() {
syncer.bad.Add(b) syncer.bad.Add(b, fmt.Sprintf("linked to %s", pcid))
} }
return nil, xerrors.Errorf("chain linked to block marked previously as bad (%s, %s)", from.Cids(), pcid) return nil, xerrors.Errorf("chain linked to block marked previously as bad (%s, %s) (reason: %s)", from.Cids(), pcid, reason)
} }
} }
@ -892,12 +896,12 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to
loop: loop:
for blockSet[len(blockSet)-1].Height() > untilHeight { for blockSet[len(blockSet)-1].Height() > untilHeight {
for _, bc := range at.Cids() { for _, bc := range at.Cids() {
if syncer.bad.Has(bc) { if reason, ok := syncer.bad.Has(bc); ok {
for _, b := range acceptedBlocks { for _, b := range acceptedBlocks {
syncer.bad.Add(b) syncer.bad.Add(b, fmt.Sprintf("chain contained %s", bc))
} }
return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s)", from.Cids(), bc) return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s) (reason: %s)", from.Cids(), bc, reason)
} }
} }
@ -940,12 +944,12 @@ loop:
break loop break loop
} }
for _, bc := range b.Cids() { for _, bc := range b.Cids() {
if syncer.bad.Has(bc) { if reason, ok := syncer.bad.Has(bc); ok {
for _, b := range acceptedBlocks { for _, b := range acceptedBlocks {
syncer.bad.Add(b) syncer.bad.Add(b, fmt.Sprintf("chain contained %s", bc))
} }
return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s)", from.Cids(), bc) return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s) (reason: %s)", from.Cids(), bc, reason)
} }
} }
blockSet = append(blockSet, b) blockSet = append(blockSet, b)
@ -972,7 +976,7 @@ loop:
// TODO: we're marking this block bad in the same way that we mark invalid blocks bad. Maybe distinguish? // TODO: we're marking this block bad in the same way that we mark invalid blocks bad. Maybe distinguish?
log.Warn("adding forked chain to our bad tipset cache") log.Warn("adding forked chain to our bad tipset cache")
for _, b := range from.Blocks() { for _, b := range from.Blocks() {
syncer.bad.Add(b.Cid()) syncer.bad.Add(b.Cid(), "fork past finality")
} }
} }
return nil, xerrors.Errorf("failed to sync fork: %w", err) return nil, xerrors.Errorf("failed to sync fork: %w", err)
@ -1189,5 +1193,9 @@ func (syncer *Syncer) State() []SyncerState {
} }
func (syncer *Syncer) MarkBad(blk cid.Cid) { func (syncer *Syncer) MarkBad(blk cid.Cid) {
syncer.bad.Add(blk) syncer.bad.Add(blk, "manually marked bad")
}
func (syncer *Syncer) CheckBadBlockCache(blk cid.Cid) (string, bool) {
return syncer.bad.Has(blk)
} }

View File

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"math/big" "math/big"
"github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
@ -207,7 +206,11 @@ func IsTicketWinner(partialTicket []byte, ssizeI abi.SectorSize, snum uint64, to
} }
func ElectionPostChallengeCount(sectors uint64, faults uint64) uint64 { func ElectionPostChallengeCount(sectors uint64, faults uint64) uint64 {
return sectorbuilder.ElectionPostChallengeCount(sectors, faults) if sectors-faults == 0 {
return 0
}
// ceil(sectors / SectorChallengeRatioDiv)
return (sectors-faults-1)/build.SectorChallengeRatioDiv + 1
} }
func (t *Ticket) Equals(ot *Ticket) bool { func (t *Ticket) Equals(ot *Ticket) bool {

View File

@ -130,6 +130,9 @@ func (ts *TipSet) Cids() []cid.Cid {
} }
func (ts *TipSet) Key() TipSetKey { func (ts *TipSet) Key() TipSetKey {
if ts == nil {
return EmptyTSK
}
return NewTipSetKey(ts.cids...) return NewTipSetKey(ts.cids...)
} }

View File

@ -9,6 +9,8 @@ import (
"github.com/multiformats/go-multihash" "github.com/multiformats/go-multihash"
) )
var EmptyTSK = TipSetKey{}
// The length of a block header CID in bytes. // The length of a block header CID in bytes.
var blockHeaderCIDLen int var blockHeaderCIDLen int
@ -90,6 +92,10 @@ func (k *TipSetKey) UnmarshalJSON(b []byte) error {
return nil return nil
} }
func (k TipSetKey) IsEmpty() bool {
return len(k.value) == 0
}
func encodeKey(cids []cid.Cid) []byte { func encodeKey(cids []cid.Cid) []byte {
buffer := new(bytes.Buffer) buffer := new(bytes.Buffer)
for _, c := range cids { for _, c := range cids {

View File

@ -9,6 +9,7 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/actors/aerrors"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"

View File

@ -16,6 +16,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
) )
func TestMessageFactory(t *testing.T) { func TestMessageFactory(t *testing.T) {

View File

@ -7,6 +7,8 @@ import (
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
) )
const HalvingPeriodEpochs = 6 * 365 * 24 * 60 * 2 const HalvingPeriodEpochs = 6 * 365 * 24 * 60 * 2

View File

@ -255,7 +255,7 @@ var chainSetHeadCmd = &cli.Command{
ts, err = api.ChainGetGenesis(ctx) ts, err = api.ChainGetGenesis(ctx)
} }
if ts == nil && cctx.IsSet("epoch") { if ts == nil && cctx.IsSet("epoch") {
ts, err = api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Uint64("epoch")), nil) ts, err = api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Uint64("epoch")), types.EmptyTSK)
} }
if ts == nil { if ts == nil {
ts, err = parseTipSet(api, ctx, cctx.Args().Slice()) ts, err = parseTipSet(api, ctx, cctx.Args().Slice())
@ -268,7 +268,7 @@ var chainSetHeadCmd = &cli.Command{
return fmt.Errorf("must pass cids for tipset to set as head") return fmt.Errorf("must pass cids for tipset to set as head")
} }
if err := api.ChainSetHead(ctx, ts); err != nil { if err := api.ChainSetHead(ctx, ts.Key()); err != nil {
return err return err
} }
@ -318,7 +318,7 @@ var chainListCmd = &cli.Command{
var head *types.TipSet var head *types.TipSet
if cctx.IsSet("height") { if cctx.IsSet("height") {
head, err = api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Uint64("height")), nil) head, err = api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Uint64("height")), types.EmptyTSK)
} else { } else {
head, err = api.ChainHead(ctx) head, err = api.ChainHead(ctx)
} }
@ -451,7 +451,7 @@ var chainBisectCmd = &cli.Command{
subPath := cctx.Args().Get(2) subPath := cctx.Args().Get(2)
highest, err := api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(end), nil) highest, err := api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(end), types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
@ -465,7 +465,7 @@ var chainBisectCmd = &cli.Command{
start = end start = end
} }
midTs, err := api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(mid), highest) midTs, err := api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(mid), highest.Key())
if err != nil { if err != nil {
return err return err
} }
@ -547,7 +547,7 @@ var chainExportCmd = &cli.Command{
return err return err
} }
stream, err := api.ChainExport(ctx, ts) stream, err := api.ChainExport(ctx, ts.Key())
if err != nil { if err != nil {
return err return err
} }

View File

@ -291,7 +291,7 @@ var clientQueryAskCmd = &cli.Command{
} }
pid = p pid = p
} else { } else {
p, err := api.StateMinerPeerID(ctx, maddr, nil) p, err := api.StateMinerPeerID(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return xerrors.Errorf("failed to get peerID for miner: %w", err) return xerrors.Errorf("failed to get peerID for miner: %w", err)
} }

View File

@ -210,4 +210,5 @@ var Commands = []*cli.Command{
syncCmd, syncCmd,
versionCmd, versionCmd,
walletCmd, walletCmd,
logCmd,
} }

101
cli/log.go Normal file
View File

@ -0,0 +1,101 @@
package cli
import (
"fmt"
"golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
)
var logCmd = &cli.Command{
Name: "log",
Usage: "Manage logging",
Subcommands: []*cli.Command{
logList,
logSetLevel,
},
}
var logList = &cli.Command{
Name: "list",
Usage: "List log systems",
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
systems, err := api.LogList(ctx)
if err != nil {
return err
}
for _, system := range systems {
fmt.Println(system)
}
return nil
},
}
var logSetLevel = &cli.Command{
Name: "set-level",
Usage: "Set log level",
ArgsUsage: "<level>",
Description: `Set the log level for logging systems:
The system flag can be specified multiple times.
eg) log set-level --system chain --system blocksync debug
Available Levels:
debug
info
warn
error
Environment Variables:
GOLOG_LOG_LEVEL - Default log level for all log systems
GOLOG_LOG_FMT - Change output log format (json, nocolor)
GOLOG_FILE - Write logs to file in addition to stderr
`,
Flags: []cli.Flag{
&cli.StringSliceFlag{
Name: "system",
Usage: "limit to log system",
Value: &cli.StringSlice{},
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
if !cctx.Args().Present() {
return fmt.Errorf("level is required")
}
systems := cctx.StringSlice("system")
if len(systems) == 0 {
var err error
systems, err = api.LogList(ctx)
if err != nil {
return err
}
}
for _, system := range systems {
if err := api.LogSetLevel(ctx, system, cctx.Args().First()); err != nil {
return xerrors.Errorf("setting log level on %s: %w", system, err)
}
}
return nil
},
}

View File

@ -33,7 +33,7 @@ var mpoolPending = &cli.Command{
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
msgs, err := api.MpoolPending(ctx, nil) msgs, err := api.MpoolPending(ctx, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
@ -103,7 +103,7 @@ var mpoolStat = &cli.Command{
return xerrors.Errorf("getting chain head: %w", err) return xerrors.Errorf("getting chain head: %w", err)
} }
msgs, err := api.MpoolPending(ctx, nil) msgs, err := api.MpoolPending(ctx, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
@ -122,7 +122,7 @@ var mpoolStat = &cli.Command{
bkt.msgs[v.Message.Nonce] = v bkt.msgs[v.Message.Nonce] = v
} }
for a, bkt := range buckets { for a, bkt := range buckets {
act, err := api.StateGetActor(ctx, a, ts) act, err := api.StateGetActor(ctx, a, ts.Key())
if err != nil { if err != nil {
fmt.Printf("%s, err: %s\n", a, err) fmt.Printf("%s, err: %s\n", a, err)
continue continue

View File

@ -177,7 +177,7 @@ var msigInspectCmd = &cli.Command{
return err return err
} }
act, err := api.StateGetActor(ctx, maddr, nil) act, err := api.StateGetActor(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }

View File

@ -2,6 +2,7 @@ package cli
import ( import (
"fmt" "fmt"
"github.com/libp2p/go-libp2p-core/peer"
"sort" "sort"
"strings" "strings"
@ -18,6 +19,7 @@ var netCmd = &cli.Command{
netConnect, netConnect,
netListen, netListen,
netId, netId,
netFindPeer,
}, },
} }
@ -123,3 +125,37 @@ var netId = &cli.Command{
return nil return nil
}, },
} }
var netFindPeer = &cli.Command{
Name: "findpeer",
Usage: "Find the addresses of a given peerID",
ArgsUsage: "<peer ID>",
Action: func(cctx *cli.Context) error {
if cctx.NArg() != 1 {
fmt.Println("Usage: findpeer [peer ID]")
return nil
}
pid, err := peer.IDB58Decode(cctx.Args().First())
if err != nil {
return err
}
api, closer, err := GetAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
addrs, err := api.NetFindPeer(ctx, pid)
if err != nil {
return err
}
fmt.Println(addrs)
return nil
},
}

View File

@ -21,6 +21,7 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/miner"
"github.com/docker/go-units"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
@ -51,6 +52,68 @@ var stateCmd = &cli.Command{
stateComputeStateCmd, stateComputeStateCmd,
stateCallCmd, stateCallCmd,
stateGetDealSetCmd, stateGetDealSetCmd,
stateWaitMsgCmd,
stateMinerInfo,
},
}
var stateMinerInfo = &cli.Command{
Name: "miner-info",
Usage: "Retrieve miner information",
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
if !cctx.Args().Present() {
return fmt.Errorf("must specify miner to get information for")
}
addr, err := address.NewFromString(cctx.Args().First())
if err != nil {
return err
}
ts, err := loadTipSet(ctx, cctx, api)
if err != nil {
return err
}
act, err := api.StateGetActor(ctx, addr, ts.Key())
if err != nil {
return err
}
aso, err := api.ChainReadObj(ctx, act.Head)
if err != nil {
return err
}
var mst actors.StorageMinerActorState
if err := mst.UnmarshalCBOR(bytes.NewReader(aso)); err != nil {
return err
}
mio, err := api.ChainReadObj(ctx, mst.Info)
if err != nil {
return err
}
var mi actors.MinerInfo
if err := mi.UnmarshalCBOR(bytes.NewReader(mio)); err != nil {
return err
}
fmt.Printf("Owner:\t%s\n", mi.Owner)
fmt.Printf("Worker:\t%s\n", mi.Worker)
fmt.Printf("PeerID:\t%s\n", mi.PeerID)
fmt.Printf("SectorSize:\t%s (%d)\n", units.BytesSize(float64(mi.SectorSize)), mi.SectorSize)
return nil
}, },
} }
@ -118,7 +181,7 @@ var statePowerCmd = &cli.Command{
return err return err
} }
power, err := api.StateMinerPower(ctx, maddr, ts) power, err := api.StateMinerPower(ctx, maddr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -162,7 +225,7 @@ var stateSectorsCmd = &cli.Command{
return err return err
} }
sectors, err := api.StateMinerSectors(ctx, maddr, ts) sectors, err := api.StateMinerSectors(ctx, maddr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -201,7 +264,7 @@ var stateProvingSetCmd = &cli.Command{
return err return err
} }
sectors, err := api.StateMinerProvingSet(ctx, maddr, ts) sectors, err := api.StateMinerProvingSet(ctx, maddr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -276,7 +339,7 @@ var stateReplaySetCmd = &cli.Command{
} }
res, err := api.StateReplay(ctx, ts, mcid) res, err := api.StateReplay(ctx, ts.Key(), mcid)
if err != nil { if err != nil {
return xerrors.Errorf("replay call failed: %w", err) return xerrors.Errorf("replay call failed: %w", err)
} }
@ -310,7 +373,7 @@ var statePledgeCollateralCmd = &cli.Command{
return err return err
} }
coll, err := api.StatePledgeCollateral(ctx, ts) coll, err := api.StatePledgeCollateral(ctx, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -346,7 +409,7 @@ var stateGetDealSetCmd = &cli.Command{
return err return err
} }
deal, err := api.StateMarketStorageDeal(ctx, abi.DealID(dealid), ts) deal, err := api.StateMarketStorageDeal(ctx, abi.DealID(dealid), ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -378,7 +441,7 @@ var stateListMinersCmd = &cli.Command{
return err return err
} }
miners, err := api.StateListMiners(ctx, ts) miners, err := api.StateListMiners(ctx, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -408,7 +471,7 @@ var stateListActorsCmd = &cli.Command{
return err return err
} }
actors, err := api.StateListActors(ctx, ts) actors, err := api.StateListActors(ctx, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -447,7 +510,7 @@ var stateGetActorCmd = &cli.Command{
return err return err
} }
a, err := api.StateGetActor(ctx, addr, ts) a, err := api.StateGetActor(ctx, addr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -488,7 +551,7 @@ var stateLookupIDCmd = &cli.Command{
return err return err
} }
a, err := api.StateLookupID(ctx, addr, ts) a, err := api.StateLookupID(ctx, addr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -525,7 +588,7 @@ var stateSectorSizeCmd = &cli.Command{
return err return err
} }
ssize, err := api.StateMinerSectorSize(ctx, addr, ts) ssize, err := api.StateMinerSectorSize(ctx, addr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -561,12 +624,12 @@ var stateReadStateCmd = &cli.Command{
return err return err
} }
act, err := api.StateGetActor(ctx, addr, ts) act, err := api.StateGetActor(ctx, addr, ts.Key())
if err != nil { if err != nil {
return err return err
} }
as, err := api.StateReadState(ctx, act, ts) as, err := api.StateReadState(ctx, act, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -635,7 +698,7 @@ var stateListMessagesCmd = &cli.Command{
return err return err
} }
msgs, err := api.StateListMessages(ctx, &types.Message{To: toa, From: froma}, ts, abi.ChainEpoch(toh)) msgs, err := api.StateListMessages(ctx, &types.Message{To: toa, From: froma}, ts.Key(), abi.ChainEpoch(toh))
if err != nil { if err != nil {
return err return err
} }
@ -702,7 +765,7 @@ var stateComputeStateCmd = &cli.Command{
var msgs []*types.Message var msgs []*types.Message
if cctx.Bool("apply-mpool-messages") { if cctx.Bool("apply-mpool-messages") {
pmsgs, err := api.MpoolPending(ctx, ts) pmsgs, err := api.MpoolPending(ctx, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -717,7 +780,7 @@ var stateComputeStateCmd = &cli.Command{
} }
} }
nstate, err := api.StateCompute(ctx, h, msgs, ts) nstate, err := api.StateCompute(ctx, h, msgs, ts.Key())
if err != nil { if err != nil {
return err return err
} }
@ -727,6 +790,46 @@ var stateComputeStateCmd = &cli.Command{
}, },
} }
var stateWaitMsgCmd = &cli.Command{
Name: "wait-msg",
Usage: "Wait for a message to appear on chain",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "timeout",
Value: "10m",
},
},
Action: func(cctx *cli.Context) error {
if !cctx.Args().Present() {
return fmt.Errorf("must specify message cid to wait for")
}
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
msg, err := cid.Decode(cctx.Args().First())
if err != nil {
return err
}
mw, err := api.StateWaitMsg(ctx, msg)
if err != nil {
return err
}
fmt.Printf("message was executed in tipset: %s", mw.TipSet.Cids())
fmt.Printf("Exit Code: %d", mw.Receipt.ExitCode)
fmt.Printf("Gas Used: %s", mw.Receipt.GasUsed)
fmt.Printf("Return: %x", mw.Receipt.Return)
return nil
},
}
var stateCallCmd = &cli.Command{ var stateCallCmd = &cli.Command{
Name: "call", Name: "call",
Usage: "Invoke a method on an actor locally", Usage: "Invoke a method on an actor locally",
@ -785,7 +888,7 @@ var stateCallCmd = &cli.Command{
return fmt.Errorf("failed to parse 'value': %s", err) return fmt.Errorf("failed to parse 'value': %s", err)
} }
act, err := api.StateGetActor(ctx, toa, ts) act, err := api.StateGetActor(ctx, toa, ts.Key())
if err != nil { if err != nil {
return fmt.Errorf("failed to lookup target actor: %s", err) return fmt.Errorf("failed to lookup target actor: %s", err)
} }
@ -803,7 +906,7 @@ var stateCallCmd = &cli.Command{
GasPrice: types.NewInt(0), GasPrice: types.NewInt(0),
Method: abi.MethodNum(method), Method: abi.MethodNum(method),
Params: params, Params: params,
}, ts) }, ts.Key())
if err != nil { if err != nil {
return fmt.Errorf("state call failed: %s", err) return fmt.Errorf("state call failed: %s", err)
} }

View File

@ -21,6 +21,7 @@ var syncCmd = &cli.Command{
syncStatusCmd, syncStatusCmd,
syncWaitCmd, syncWaitCmd,
syncMarkBadCmd, syncMarkBadCmd,
syncCheckBadCmd,
}, },
} }
@ -116,6 +117,41 @@ var syncMarkBadCmd = &cli.Command{
}, },
} }
var syncCheckBadCmd = &cli.Command{
Name: "check-bad",
Usage: "check if the given block was marked bad, and for what reason",
Action: func(cctx *cli.Context) error {
napi, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
if !cctx.Args().Present() {
return fmt.Errorf("must specify block cid to check")
}
bcid, err := cid.Decode(cctx.Args().First())
if err != nil {
return fmt.Errorf("failed to decode input as a cid: %s", err)
}
reason, err := napi.SyncCheckBad(ctx, bcid)
if err != nil {
return err
}
if reason == "" {
fmt.Println("block was not marked as bad")
return nil
}
fmt.Println(reason)
return nil
},
}
func SyncWait(ctx context.Context, napi api.FullNode) error { func SyncWait(ctx context.Context, napi api.FullNode) error {
for { for {
state, err := napi.SyncState(ctx) state, err := napi.SyncState(ctx)

View File

@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"net/http" "net/http"
_ "net/http/pprof"
"os" "os"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
@ -59,6 +60,10 @@ var runCmd = &cli.Command{
Name: "front", Name: "front",
Value: "127.0.0.1:8418", Value: "127.0.0.1:8418",
}, },
&cli.IntFlag{
Name: "max-batch",
Value: 1000,
},
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
api, closer, err := lcli.GetFullNodeAPI(cctx) api, closer, err := lcli.GetFullNodeAPI(cctx)
@ -75,13 +80,15 @@ var runCmd = &cli.Command{
log.Info("Remote version: %s", v.Version) log.Info("Remote version: %s", v.Version)
maxBatch := cctx.Int("max-batch")
st, err := openStorage(cctx.String("db")) st, err := openStorage(cctx.String("db"))
if err != nil { if err != nil {
return err return err
} }
defer st.close() defer st.close()
runSyncer(ctx, api, st) runSyncer(ctx, api, st, maxBatch)
h, err := newHandler(api, st) h, err := newHandler(api, st)
if err != nil { if err != nil {

View File

@ -20,9 +20,7 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
const maxBatch = 3000 func runSyncer(ctx context.Context, api api.FullNode, st *storage, maxBatch int) {
func runSyncer(ctx context.Context, api api.FullNode, st *storage) {
notifs, err := api.ChainNotify(ctx) notifs, err := api.ChainNotify(ctx)
if err != nil { if err != nil {
panic(err) panic(err)
@ -34,7 +32,7 @@ func runSyncer(ctx context.Context, api api.FullNode, st *storage) {
case store.HCCurrent: case store.HCCurrent:
fallthrough fallthrough
case store.HCApply: case store.HCApply:
syncHead(ctx, api, st, change.Val) syncHead(ctx, api, st, change.Val, maxBatch)
case store.HCRevert: case store.HCRevert:
log.Warnf("revert todo") log.Warnf("revert todo")
} }
@ -67,9 +65,7 @@ type actorInfo struct {
state string state string
} }
func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipSet) { func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipSet, maxBatch int) {
addresses := map[address.Address]address.Address{}
actors := map[address.Address]map[types.Actor]actorInfo{}
var alk sync.Mutex var alk sync.Mutex
log.Infof("Getting synced block list") log.Infof("Getting synced block list")
@ -94,7 +90,6 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
} }
allToSync[bh.Cid()] = bh allToSync[bh.Cid()] = bh
addresses[bh.Miner] = address.Undef
if len(allToSync)%500 == 10 { if len(allToSync)%500 == 10 {
log.Infof("todo: (%d) %s @%d", len(allToSync), bh.Cid(), bh.Height) log.Infof("todo: (%d) %s @%d", len(allToSync), bh.Cid(), bh.Height)
@ -116,7 +111,9 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
} }
for len(allToSync) > 0 { for len(allToSync) > 0 {
minH := abi.ChainEpoch(math.MaxInt64) actors := map[address.Address]map[types.Actor]actorInfo{}
addresses := map[address.Address]address.Address{}
minH := abi.ChainEpoch(math.MaxUint64)
for _, header := range allToSync { for _, header := range allToSync {
if header.Height < minH { if header.Height < minH {
@ -126,8 +123,9 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
toSync := map[cid.Cid]*types.BlockHeader{} toSync := map[cid.Cid]*types.BlockHeader{}
for c, header := range allToSync { for c, header := range allToSync {
if header.Height < minH+maxBatch { if header.Height < minH+uint64(maxBatch) {
toSync[c] = header toSync[c] = header
addresses[header.Miner] = address.Undef
} }
} }
for c := range toSync { for c := range toSync {
@ -145,19 +143,19 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
if len(bh.Parents) == 0 { // genesis case if len(bh.Parents) == 0 { // genesis case
ts, err := types.NewTipSet([]*types.BlockHeader{bh}) ts, err := types.NewTipSet([]*types.BlockHeader{bh})
aadrs, err := api.StateListActors(ctx, ts) aadrs, err := api.StateListActors(ctx, ts.Key())
if err != nil { if err != nil {
log.Error(err) log.Error(err)
return return
} }
par(50, aadrs, func(addr address.Address) { par(50, aadrs, func(addr address.Address) {
act, err := api.StateGetActor(ctx, addr, ts) act, err := api.StateGetActor(ctx, addr, ts.Key())
if err != nil { if err != nil {
log.Error(err) log.Error(err)
return return
} }
ast, err := api.StateReadState(ctx, act, ts) ast, err := api.StateReadState(ctx, act, ts.Key())
if err != nil { if err != nil {
log.Error(err) log.Error(err)
return return
@ -202,7 +200,7 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
log.Error(err) log.Error(err)
return return
} }
ast, err := api.StateReadState(ctx, &act, ts) ast, err := api.StateReadState(ctx, &act, pts.Key())
if err != nil { if err != nil {
log.Error(err) log.Error(err)
return return
@ -239,7 +237,7 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
} }
par(50, kmaparr(addresses), func(addr address.Address) { par(50, kmaparr(addresses), func(addr address.Address) {
raddr, err := api.StateLookupID(ctx, addr, nil) raddr, err := api.StateLookupID(ctx, addr, types.EmptyTSK)
if err != nil { if err != nil {
log.Warn(err) log.Warn(err)
return return
@ -270,7 +268,7 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
par(50, kvmaparr(miners), func(it func() (minerKey, *minerInfo)) { par(50, kvmaparr(miners), func(it func() (minerKey, *minerInfo)) {
k, info := it() k, info := it()
sszs, err := api.StateMinerSectorCount(ctx, k.addr, nil) sszs, err := api.StateMinerSectorCount(ctx, k.addr, types.EmptyTSK)
if err != nil { if err != nil {
log.Error(err) log.Error(err)
return return
@ -359,7 +357,7 @@ func syncHead(ctx context.Context, api api.FullNode, st *storage, ts *types.TipS
log.Infof("Get deals") log.Infof("Get deals")
// TODO: incremental, gather expired // TODO: incremental, gather expired
deals, err := api.StateMarketDeals(ctx, ts) deals, err := api.StateMarketDeals(ctx, ts.Key())
if err != nil { if err != nil {
log.Error(err) log.Error(err)
return return

View File

@ -208,7 +208,8 @@ func (h *handler) mkminer(w http.ResponseWriter, r *http.Request) {
if owner.Protocol() != address.BLS { if owner.Protocol() != address.BLS {
w.WriteHeader(400) w.WriteHeader(400)
w.Write([]byte("Miner address must use BLS")) w.Write([]byte("Miner address must use BLS. A BLS address starts with the prefix 't3'."))
w.Write([]byte("Please create a BLS address by running \"lotus wallet new bls\" while connected to a Lotus node."))
return return
} }
@ -239,7 +240,7 @@ func (h *handler) mkminer(w http.ResponseWriter, r *http.Request) {
return return
} }
collateral, err := h.api.StatePledgeCollateral(r.Context(), nil) collateral, err := h.api.StatePledgeCollateral(r.Context(), types.EmptyTSK)
if err != nil { if err != nil {
w.WriteHeader(400) w.WriteHeader(400)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))

View File

@ -3,7 +3,7 @@ package main
import ( import (
"os" "os"
"github.com/coreos/go-systemd/dbus" "github.com/coreos/go-systemd/v22/dbus"
) )
func notifyHandler(n string, ch chan interface{}, sCh chan os.Signal) (string, error) { func notifyHandler(n string, ch chan interface{}, sCh chan os.Signal) (string, error) {

View File

@ -11,6 +11,9 @@ import (
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
) )

View File

@ -38,14 +38,14 @@ var infoCmd = &cli.Command{
fmt.Printf("Miner: %s\n", maddr) fmt.Printf("Miner: %s\n", maddr)
// Sector size // Sector size
sizeByte, err := api.StateMinerSectorSize(ctx, maddr, nil) sizeByte, err := api.StateMinerSectorSize(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
fmt.Printf("Sector Size: %s\n", types.SizeStr(types.NewInt(uint64(sizeByte)))) fmt.Printf("Sector Size: %s\n", types.SizeStr(types.NewInt(uint64(sizeByte))))
pow, err := api.StateMinerPower(ctx, maddr, nil) pow, err := api.StateMinerPower(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
@ -53,11 +53,11 @@ var infoCmd = &cli.Command{
percI := types.BigDiv(types.BigMul(pow.MinerPower, types.NewInt(1000000)), pow.TotalPower) percI := types.BigDiv(types.BigMul(pow.MinerPower, types.NewInt(1000000)), pow.TotalPower)
fmt.Printf("Power: %s / %s (%0.4f%%)\n", types.SizeStr(pow.MinerPower), types.SizeStr(pow.TotalPower), float64(percI.Int64())/10000) fmt.Printf("Power: %s / %s (%0.4f%%)\n", types.SizeStr(pow.MinerPower), types.SizeStr(pow.TotalPower), float64(percI.Int64())/10000)
secCounts, err := api.StateMinerSectorCount(ctx, maddr, nil) secCounts, err := api.StateMinerSectorCount(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
faults, err := api.StateMinerFaults(ctx, maddr, nil) faults, err := api.StateMinerFaults(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
@ -88,7 +88,7 @@ var infoCmd = &cli.Command{
fmt.Printf("\tCommit: %d\n", wstat.CommitWait) fmt.Printf("\tCommit: %d\n", wstat.CommitWait)
fmt.Printf("\tUnseal: %d\n", wstat.UnsealWait) fmt.Printf("\tUnseal: %d\n", wstat.UnsealWait)
ps, err := api.StateMinerPostState(ctx, maddr, nil) ps, err := api.StateMinerPostState(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }

View File

@ -35,6 +35,7 @@ import (
lcli "github.com/filecoin-project/lotus/cli" lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/lotus/node/config"
"github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/modules"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/node/repo"
@ -78,6 +79,10 @@ var initCmd = &cli.Command{
Name: "pre-sealed-sectors", Name: "pre-sealed-sectors",
Usage: "specify set of presealed sectors for starting as a genesis miner", Usage: "specify set of presealed sectors for starting as a genesis miner",
}, },
&cli.StringFlag{
Name: "pre-sealed-metadata",
Usage: "specify the metadata file for the presealed sectors",
},
&cli.BoolFlag{ &cli.BoolFlag{
Name: "nosync", Name: "nosync",
Usage: "don't check full-node sync status", Usage: "don't check full-node sync status",
@ -221,13 +226,13 @@ var initCmd = &cli.Command{
}, },
} }
func migratePreSealMeta(ctx context.Context, api lapi.FullNode, presealDir string, maddr address.Address, mds dtypes.MetadataDS) error { func migratePreSealMeta(ctx context.Context, api lapi.FullNode, metadata string, maddr address.Address, mds dtypes.MetadataDS) error {
presealDir, err := homedir.Expand(presealDir) metadata, err := homedir.Expand(metadata)
if err != nil { if err != nil {
return xerrors.Errorf("expanding preseal dir: %w", err) return xerrors.Errorf("expanding preseal dir: %w", err)
} }
b, err := ioutil.ReadFile(filepath.Join(presealDir, "pre-seal-"+maddr.String()+".json")) b, err := ioutil.ReadFile(metadata)
if err != nil { if err != nil {
return xerrors.Errorf("reading preseal metadata: %w", err) return xerrors.Errorf("reading preseal metadata: %w", err)
} }
@ -307,7 +312,7 @@ func findMarketDealID(ctx context.Context, api lapi.FullNode, deal actors.Storag
// TODO: find a better way // TODO: find a better way
// (this is only used by genesis miners) // (this is only used by genesis miners)
deals, err := api.StateMarketDeals(ctx, nil) deals, err := api.StateMarketDeals(ctx, types.EmptyTSK)
if err != nil { if err != nil {
return 0, xerrors.Errorf("getting market deals: %w", err) return 0, xerrors.Errorf("getting market deals: %w", err)
} }
@ -358,7 +363,22 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode,
return err return err
} }
sbcfg, err := modules.SectorBuilderConfig(sectorbuilder.SimplePath(lr.Path()), 2, false, false)(mds, api) c, err := lr.Config()
if err != nil {
return err
}
cfg, ok := c.(*config.StorageMiner)
if !ok {
return xerrors.Errorf("invalid config from repo, got: %T", c)
}
scfg := sectorbuilder.SimplePath(lr.Path())
if len(cfg.SectorBuilder.Storage) > 0 {
scfg = cfg.SectorBuilder.Storage
}
sbcfg, err := modules.SectorBuilderConfig(scfg, 2, false, false)(mds, api)
if err != nil { if err != nil {
return xerrors.Errorf("getting genesis miner sector builder config: %w", err) return xerrors.Errorf("getting genesis miner sector builder config: %w", err)
} }
@ -385,20 +405,20 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode,
} }
} }
if pssb := cctx.String("pre-sealed-sectors"); pssb != "" { return nil
pssb, err := homedir.Expand(pssb) }
if err != nil {
return err
}
log.Infof("Importing pre-sealed sector metadata for %s", a) if pssb := cctx.String("pre-sealed-metadata"); pssb != "" {
pssb, err := homedir.Expand(pssb)
if err := migratePreSealMeta(ctx, api, pssb, a, mds); err != nil { if err != nil {
return xerrors.Errorf("migrating presealed sector metadata: %w", err) return err
}
} }
return nil log.Infof("Importing pre-sealed sector metadata for %s", a)
if err := migratePreSealMeta(ctx, api, pssb, a, mds); err != nil {
return xerrors.Errorf("migrating presealed sector metadata: %w", err)
}
} }
if err := configureStorageMiner(ctx, api, a, peerid); err != nil { if err := configureStorageMiner(ctx, api, a, peerid); err != nil {
@ -450,7 +470,7 @@ func makeHostKey(lr repo.LockedRepo) (crypto.PrivKey, error) {
} }
func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address.Address, peerid peer.ID) error { func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address.Address, peerid peer.ID) error {
waddr, err := api.StateMinerWorker(ctx, addr, nil) waddr, err := api.StateMinerWorker(ctx, addr, types.EmptyTSK)
if err != nil { if err != nil {
return xerrors.Errorf("getWorkerAddr returned bad address: %w", err) return xerrors.Errorf("getWorkerAddr returned bad address: %w", err)
} }
@ -514,7 +534,7 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID,
return address.Undef, err return address.Undef, err
} }
collateral, err := api.StatePledgeCollateral(ctx, nil) collateral, err := api.StatePledgeCollateral(ctx, types.EmptyTSK)
if err != nil { if err != nil {
return address.Undef, err return address.Undef, err
} }

View File

@ -2,6 +2,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/filecoin-project/lotus/chain/types"
"os" "os"
"sort" "sort"
"strconv" "strconv"
@ -130,7 +131,7 @@ var sectorsListCmd = &cli.Command{
return err return err
} }
pset, err := fullApi.StateMinerProvingSet(ctx, maddr, nil) pset, err := fullApi.StateMinerProvingSet(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
@ -139,7 +140,7 @@ var sectorsListCmd = &cli.Command{
provingIDs[info.ID] = struct{}{} provingIDs[info.ID] = struct{}{}
} }
sset, err := fullApi.StateMinerSectors(ctx, maddr, nil) sset, err := fullApi.StateMinerSectors(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }

View File

@ -16,7 +16,10 @@ import (
paramfetch "github.com/filecoin-project/go-paramfetch" paramfetch "github.com/filecoin-project/go-paramfetch"
"github.com/filecoin-project/go-sectorbuilder" "github.com/filecoin-project/go-sectorbuilder"
blockstore "github.com/ipfs/go-ipfs-blockstore" blockstore "github.com/ipfs/go-ipfs-blockstore"
"github.com/mitchellh/go-homedir"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
@ -95,7 +98,15 @@ var DaemonCmd = &cli.Command{
} }
ctx := context.Background() ctx := context.Background()
log.Infof("lotus repo: %s", cctx.String("repo")) {
dir, err := homedir.Expand(cctx.String("repo"))
if err != nil {
log.Warnw("could not expand repo location", "error", err)
} else {
log.Infof("lotus repo: %s", dir)
}
}
r, err := repo.NewFS(cctx.String("repo")) r, err := repo.NewFS(cctx.String("repo"))
if err != nil { if err != nil {
return xerrors.Errorf("opening fs repo: %w", err) return xerrors.Errorf("opening fs repo: %w", err)
@ -173,6 +184,17 @@ var DaemonCmd = &cli.Command{
} }
} }
// Add lotus version info to prometheus metrics
var lotusInfoMetric = promauto.NewGaugeVec(prometheus.GaugeOpts{
Name: "lotus_info",
Help: "Lotus version information.",
}, []string{"version"})
// Setting to 1 lets us multiply it with other stats to add the version labels
lotusInfoMetric.With(prometheus.Labels{
"version": build.UserVersion,
}).Set(1)
endpoint, err := r.APIEndpoint() endpoint, err := r.APIEndpoint()
if err != nil { if err != nil {
return xerrors.Errorf("getting api endpoint: %w", err) return xerrors.Errorf("getting api endpoint: %w", err)

View File

@ -30,7 +30,7 @@ func init() {
if err != nil { if err != nil {
return err return err
} }
pending, err := api.MpoolPending(ctx, head) pending, err := api.MpoolPending(ctx, head.Key())
if err != nil { if err != nil {
return err return err
} }
@ -47,7 +47,7 @@ func init() {
addr, _ := address.NewIDAddress(1000) addr, _ := address.NewIDAddress(1000)
var ticket *types.Ticket var ticket *types.Ticket
{ {
w, err := api.StateMinerWorker(ctx, addr, nil) w, err := api.StateMinerWorker(ctx, addr, head.Key())
if err != nil { if err != nil {
return xerrors.Errorf("StateMinerWorker: %w", err) return xerrors.Errorf("StateMinerWorker: %w", err)
} }
@ -82,7 +82,7 @@ func init() {
if err != nil { if err != nil {
return xerrors.Errorf("chain get randomness: %w", err) return xerrors.Errorf("chain get randomness: %w", err)
} }
mworker, err := api.StateMinerWorker(ctx, addr, head) mworker, err := api.StateMinerWorker(ctx, addr, head.Key())
if err != nil { if err != nil {
return xerrors.Errorf("failed to get miner worker: %w", err) return xerrors.Errorf("failed to get miner worker: %w", err)
} }
@ -96,7 +96,7 @@ func init() {
uts := head.MinTimestamp() + uint64(build.BlockDelay) uts := head.MinTimestamp() + uint64(build.BlockDelay)
nheight := head.Height() + 1 nheight := head.Height() + 1
blk, err := api.MinerCreateBlock(ctx, addr, head, ticket, epostp, msgs, nheight, uts) blk, err := api.MinerCreateBlock(ctx, addr, head.Key(), ticket, epostp, msgs, nheight, uts)
if err != nil { if err != nil {
return xerrors.Errorf("creating block: %w", err) return xerrors.Errorf("creating block: %w", err)
} }

View File

@ -3,13 +3,14 @@ package main
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"github.com/filecoin-project/lotus/api/apistruct"
"net/http" "net/http"
_ "net/http/pprof" _ "net/http/pprof"
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/lib/auth" "github.com/filecoin-project/lotus/lib/auth"
"github.com/filecoin-project/lotus/lib/jsonrpc" "github.com/filecoin-project/lotus/lib/jsonrpc"
@ -21,6 +22,8 @@ import (
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr-net" manet "github.com/multiformats/go-multiaddr-net"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/prometheus/client_golang/prometheus/promhttp"
) )
var log = logging.Logger("main") var log = logging.Logger("main")
@ -43,6 +46,8 @@ func serveRPC(a api.FullNode, stop node.StopFunc, addr multiaddr.Multiaddr) erro
http.Handle("/rest/v0/import", importAH) http.Handle("/rest/v0/import", importAH)
http.Handle("/metrics", promhttp.Handler())
lst, err := manet.Listen(addr) lst, err := manet.Listen(addr)
if err != nil { if err != nil {
return xerrors.Errorf("could not listen: %w", err) return xerrors.Errorf("could not listen: %w", err)

View File

@ -160,6 +160,13 @@
} }
] ]
}, },
{
"title": "FAQs",
"slug": "en+faqs",
"github": "en/faqs.md",
"value": null,
"posts": []
},
{ {
"title": "Glossary", "title": "Glossary",
"slug": "en+glossary", "slug": "en+glossary",

134
documentation/en/faqs.md Normal file
View File

@ -0,0 +1,134 @@
# Frequently Asked Questions
Here are some FAQs concerning the Lotus implementation and participation in
Testnet.
For questions concerning the broader Filecoin project, please
go [here](https://filecoin.io/faqs/).
## Introduction to Lotus
### What is Lotus?
Lotus is an implementation of the **Filecoin Distributed Storage Network**, written in Go.
It is designed to be modular and interoperable with any other implementation of the Filecoin Protocol.
More information about Lotus can be found [here](https://lotu.sh/).
### What are the components of Lotus?
Lotus is composed of two separate pieces that can talk to each other:
The Lotus Node can sync the blockchain, validating all blocks, transfers, and deals
along the way. It can also facilitate the creation of new storage deals. If you are not
interested in providing your own storage to the network, and do not want to produce blocks
yourself, then the Lotus Node is all you need!
The Lotus Storage Miner does everything you need for the registration of storage, and the
production of new blocks. The Lotus Storage Miner communicates with the network
by talking to a Lotus Node over the JSON-RPC API.
## Setting up a Lotus Node
### How do I set up a Lotus Node?
Follow the instructions found [here](https://docs.lotu.sh/en+getting-started).
### Where can I get the latest version of Lotus?
Download the binary tagged as the `Latest Release` from the
[Lotus Github repo](https://github.com/filecoin-project/lotus/releases).
### What operating systems can Lotus run on?
Lotus can build and run on most Linux and MacOS systems with at least
8GB of RAM. Windows is not yet supported.
### How can I update to the latest version of Lotus?
To update Lotus, follow the instructions [here](https://lotu.sh/en+updating-lotus).
### How do I prepare a fresh installation of Lotus?
Stop the Lotus daemon, and delete all related files, including sealed and chain data by
running `rm ~/.lotus ~/.lotusstorage`.
Then, install Lotus afresh by following the instructions
found [here](https://docs.lotu.sh/en+getting-started).
## Interacting with a Lotus Node
### How can I communicate with a Lotus Node?
Lotus Nodes have a command-line interface, as well as a JSON-RPC API.
### What are the commands I can send using the command-line interface?
The command-line interface is self-documenting, try running `lotus --help` from the `lotus` home
directory for more.
### How can I send a request over the JSON-RPC API?
Information on how to send a `cURL` request to the JSON-RPC API can be found
[here](https://lotu.sh/en+api). A JavaScript client is under development.
### What are the requests I can send over the JSON-RPC API?
Please have a look at the
[source code](https://github.com/filecoin-project/lotus/blob/master/api/api_common.go)
for a list of methods supported by the JSON-RPC API.
## The Test Network
### What is Testnet?
Testnet is a live network of Lotus Nodes run by the
community for testing purposes.
It has 2 PiB of storage (and growing!) dedicated to it.
### Is FIL on the Testnet worth anything?
Nothing at all! Real-world incentives may be provided in a future phase of Testnet, but this is
yet to be confirmed.
### Will there be future phases of Testnet?
Yes, there will be at least one more phase of Testnet. We plan on introducing interoperable
[go-filecoin nodes](https://github.com/filecoin-project/go-filecoin#filecoin-go-filecoin)
in a future phase.
### How can I see the status of Testnet?
The [dashboard](https://stats.testnet.filecoin.io/) displays the status of the network as
well as a ton
of other metrics you might find interesting.
## Mining with a Lotus Node on Testnet
### How do I get started mining with Lotus?
Follow the instructions found [here](https://lotu.sh/en+mining).
### What are the minimum hardware requirements?
An example test configuration, and minimum hardware requirements can be found
[here](https://lotu.sh/en+hardware-mining).
Note that these might NOT be the minimum requirements for mining on Mainnet.
### What are some GPUs that have been tested?
A list of benchmarked GPUs can be found [here](https://lotu.sh/en+hardware-mining#benchmarked-gpus-7393).
## Advanced questions
### Is there a Docker image for lotus?
Community-contributed Docker and Docker Compose examples are available
[here](https://github.com/filecoin-project/lotus/tree/master/tools/dockers/docker-examples).
### How can I run two miners on the same machine?
You can do so by changing the storage path variable for the second miner, e.g.,
`LOTUS_STORAGE_PATH=~/.lotusstorage2`. You will also need to make sure that no ports collide.
### How do I setup my own local devnet?
Follow the instructions found [here](https://lotu.sh/en+setup-local-dev-net).

View File

@ -36,7 +36,7 @@ In order to connect to the network, you need to be connected to at least 1 peer.
## Chain sync ## Chain sync
While the daemon is running, the next requirement is to sync the chain. Run the command below to start the chain sync progress. To see current chain height, visit the [network stats page](http://stats.testnet.filecoin.io/). While the daemon is running, the next requirement is to sync the chain. Run the command below to start the chain sync progress. To see current chain height, visit the [network stats page](https://stats.testnet.filecoin.io/).
```sh ```sh
lotus sync wait lotus sync wait
@ -50,9 +50,11 @@ lotus sync wait
Initialize a new wallet: Initialize a new wallet:
```sh ```sh
lotus wallet new lotus wallet new
``` ```
Sometimes your operating system may limit file name length to under 150 characters. You need to use a file system that supports long filenames.
Here is an example of the response: Here is an example of the response:
```sh ```sh

View File

@ -34,7 +34,7 @@ Then, in another console, import the genesis miner key:
Set up the genesis miner: Set up the genesis miner:
```sh ```sh
./lotus-storage-miner init --genesis-miner --actor=t01000 --sector-size=1024 --pre-sealed-sectors=~/.genesis-sectors --nosync ./lotus-storage-miner init --genesis-miner --actor=t01000 --sector-size=1024 --pre-sealed-sectors=~/.genesis-sectors --pre-sealed-metadata=~/.genesis-sectors/pre-seal-t0101.json --nosync
``` ```
Now, finally, start up the miner: Now, finally, start up the miner:

View File

@ -14,12 +14,18 @@ IPFS_GATEWAY="https://proof-parameters.s3.cn-south-1.jdcloud-oss.com/ipfs/"
## Get started ## Get started
Please ensure that at least one **BLS address** in your wallet exists with the following command: Please ensure that at least one **BLS address** (starts with `t3`) in your wallet exists with the following command:
```sh ```sh
lotus wallet list lotus wallet list
``` ```
If you do not have a bls address, create a new bls wallet:
```sh
lotus wallet new bls
```
With your wallet address: With your wallet address:
- Visit the [faucet](https://lotus-faucet.kittyhawk.wtf/miner.html) - Visit the [faucet](https://lotus-faucet.kittyhawk.wtf/miner.html)

View File

@ -53,6 +53,15 @@ func main() {
os.Exit(1) os.Exit(1)
} }
err = gen.WriteTupleEncodersToFile("./node/hello/cbor_gen.go", "hello",
hello.HelloMessage{},
hello.LatencyMessage{},
)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = gen.WriteTupleEncodersToFile("./chain/blocksync/cbor_gen.go", "blocksync", err = gen.WriteTupleEncodersToFile("./chain/blocksync/cbor_gen.go", "blocksync",
blocksync.BlockSyncRequest{}, blocksync.BlockSyncRequest{},
blocksync.BlockSyncResponse{}, blocksync.BlockSyncResponse{},
@ -83,12 +92,4 @@ func main() {
fmt.Printf("%+v\n", err) fmt.Printf("%+v\n", err)
os.Exit(1) os.Exit(1)
} }
err = gen.WriteMapEncodersToFile("./node/hello/cbor_gen.go", "hello",
hello.Message{},
)
if err != nil {
fmt.Printf("%+v\n", err)
os.Exit(1)
}
} }

9
go.mod
View File

@ -8,7 +8,7 @@ require (
github.com/GeertJohan/go.rice v1.0.0 github.com/GeertJohan/go.rice v1.0.0
github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/coreos/go-systemd v0.0.0-00010101000000-000000000000 github.com/coreos/go-systemd/v22 v22.0.0
github.com/docker/go-units v0.4.0 github.com/docker/go-units v0.4.0
github.com/filecoin-project/chain-validation v0.0.3 github.com/filecoin-project/chain-validation v0.0.3
github.com/filecoin-project/filecoin-ffi v0.0.0-20191219131535-bb699517a590 github.com/filecoin-project/filecoin-ffi v0.0.0-20191219131535-bb699517a590
@ -30,7 +30,7 @@ require (
github.com/gorilla/mux v1.7.3 github.com/gorilla/mux v1.7.3
github.com/gorilla/websocket v1.4.1 github.com/gorilla/websocket v1.4.1
github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/go-multierror v1.0.0
github.com/hashicorp/golang-lru v0.5.3 github.com/hashicorp/golang-lru v0.5.4
github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e
github.com/ipfs/go-bitswap v0.1.8 github.com/ipfs/go-bitswap v0.1.8
github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-block-format v0.0.2
@ -67,7 +67,7 @@ require (
github.com/libp2p/go-libp2p-mplex v0.2.1 github.com/libp2p/go-libp2p-mplex v0.2.1
github.com/libp2p/go-libp2p-peer v0.2.0 github.com/libp2p/go-libp2p-peer v0.2.0
github.com/libp2p/go-libp2p-peerstore v0.1.4 github.com/libp2p/go-libp2p-peerstore v0.1.4
github.com/libp2p/go-libp2p-pubsub v0.2.3 github.com/libp2p/go-libp2p-pubsub v0.2.6
github.com/libp2p/go-libp2p-quic-transport v0.1.1 github.com/libp2p/go-libp2p-quic-transport v0.1.1
github.com/libp2p/go-libp2p-record v0.1.1 github.com/libp2p/go-libp2p-record v0.1.1
github.com/libp2p/go-libp2p-routing-helpers v0.1.0 github.com/libp2p/go-libp2p-routing-helpers v0.1.0
@ -85,6 +85,7 @@ require (
github.com/multiformats/go-multihash v0.0.13 github.com/multiformats/go-multihash v0.0.13
github.com/multiformats/go-varint v0.0.5 github.com/multiformats/go-varint v0.0.5
github.com/opentracing/opentracing-go v1.1.0 github.com/opentracing/opentracing-go v1.1.0
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829
github.com/prometheus/common v0.4.0 github.com/prometheus/common v0.4.0
github.com/stretchr/testify v1.4.0 github.com/stretchr/testify v1.4.0
github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba
@ -113,5 +114,3 @@ require (
replace github.com/golangci/golangci-lint => github.com/golangci/golangci-lint v1.18.0 replace github.com/golangci/golangci-lint => github.com/golangci/golangci-lint v1.18.0
replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi
replace github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 v22.0.0

29
go.sum
View File

@ -33,6 +33,7 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs= github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
@ -113,8 +114,6 @@ github.com/filecoin-project/go-data-transfer v0.0.0-20191219005021-4accf56bd2ce
github.com/filecoin-project/go-data-transfer v0.0.0-20191219005021-4accf56bd2ce/go.mod h1:b14UWxhxVCAjrQUYvVGrQRRsjAh79wXYejw9RbUcAww= github.com/filecoin-project/go-data-transfer v0.0.0-20191219005021-4accf56bd2ce/go.mod h1:b14UWxhxVCAjrQUYvVGrQRRsjAh79wXYejw9RbUcAww=
github.com/filecoin-project/go-fil-commcid v0.0.0-20200208005934-2b8bd03caca5 h1:yvQJCW9mmi9zy+51xA01Ea2X7/dL7r8eKDPuGUjRmbo= github.com/filecoin-project/go-fil-commcid v0.0.0-20200208005934-2b8bd03caca5 h1:yvQJCW9mmi9zy+51xA01Ea2X7/dL7r8eKDPuGUjRmbo=
github.com/filecoin-project/go-fil-commcid v0.0.0-20200208005934-2b8bd03caca5/go.mod h1:JbkIgFF/Z9BDlvrJO1FuKkaWsH673/UdFaiVS6uIHlA= github.com/filecoin-project/go-fil-commcid v0.0.0-20200208005934-2b8bd03caca5/go.mod h1:JbkIgFF/Z9BDlvrJO1FuKkaWsH673/UdFaiVS6uIHlA=
github.com/filecoin-project/go-fil-markets v0.0.0-20200220181918-bfd030852a59 h1:AULXvl86fSjh1gS3V/xo2YEWntAOSe3HGAHO0+S2h8k=
github.com/filecoin-project/go-fil-markets v0.0.0-20200220181918-bfd030852a59/go.mod h1:ftsiBbjLjNLAZ52FVDigkdCp73ltdcvAzAXav6drSLA=
github.com/filecoin-project/go-fil-markets v0.0.0-20200223154807-f7afd8e927f9 h1:uFS5r3K3AgIuR7cGBYY8k+vgwn/UXhin9NR2yCXVe7o= github.com/filecoin-project/go-fil-markets v0.0.0-20200223154807-f7afd8e927f9 h1:uFS5r3K3AgIuR7cGBYY8k+vgwn/UXhin9NR2yCXVe7o=
github.com/filecoin-project/go-fil-markets v0.0.0-20200223154807-f7afd8e927f9/go.mod h1:ftsiBbjLjNLAZ52FVDigkdCp73ltdcvAzAXav6drSLA= github.com/filecoin-project/go-fil-markets v0.0.0-20200223154807-f7afd8e927f9/go.mod h1:ftsiBbjLjNLAZ52FVDigkdCp73ltdcvAzAXav6drSLA=
github.com/filecoin-project/go-padreader v0.0.0-20200210211231-548257017ca6 h1:92PET+sx1Hb4W/8CgFwGuxaKbttwY+UNspYZTvXY0vs= github.com/filecoin-project/go-padreader v0.0.0-20200210211231-548257017ca6 h1:92PET+sx1Hb4W/8CgFwGuxaKbttwY+UNspYZTvXY0vs=
@ -129,12 +128,6 @@ github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZO
github.com/filecoin-project/specs-actors v0.0.0-20200210130641-2d1fbd8672cf h1:fbxBG12yrxilPFV1EG2lYqpUyAlRZWkvtqjk2svSeXY= github.com/filecoin-project/specs-actors v0.0.0-20200210130641-2d1fbd8672cf h1:fbxBG12yrxilPFV1EG2lYqpUyAlRZWkvtqjk2svSeXY=
github.com/filecoin-project/specs-actors v0.0.0-20200210130641-2d1fbd8672cf/go.mod h1:xtDZUB6pe4Pksa/bAJbJ693OilaC5Wbot9jMhLm3cZA= github.com/filecoin-project/specs-actors v0.0.0-20200210130641-2d1fbd8672cf/go.mod h1:xtDZUB6pe4Pksa/bAJbJ693OilaC5Wbot9jMhLm3cZA=
github.com/filecoin-project/specs-actors v0.0.0-20200220011005-b2a2fbf40362/go.mod h1:xtDZUB6pe4Pksa/bAJbJ693OilaC5Wbot9jMhLm3cZA= github.com/filecoin-project/specs-actors v0.0.0-20200220011005-b2a2fbf40362/go.mod h1:xtDZUB6pe4Pksa/bAJbJ693OilaC5Wbot9jMhLm3cZA=
github.com/filecoin-project/specs-actors v0.0.0-20200221171119-030c8eaad3ba h1:KXxG0UblgNdQeAxdQZNXdECYV4FCJC/noXrIjvElO/0=
github.com/filecoin-project/specs-actors v0.0.0-20200221171119-030c8eaad3ba/go.mod h1:0HAWYrvajFHDgRaKbF0rl+IybVLZL5z4gQ8koCMPhoU=
github.com/filecoin-project/specs-actors v0.0.0-20200223193531-f9e06ceb423b h1:E19WAsPkbYgle7f5RwTutpc+Ijzk/PXN+V66BaCfQuk=
github.com/filecoin-project/specs-actors v0.0.0-20200223193531-f9e06ceb423b/go.mod h1:0HAWYrvajFHDgRaKbF0rl+IybVLZL5z4gQ8koCMPhoU=
github.com/filecoin-project/specs-actors v0.0.0-20200223194434-40d9fd965c67 h1:vpjeC/VS2TyqRCgjJ0ehhIHPaWUqJiKqLC2TAEJuOw0=
github.com/filecoin-project/specs-actors v0.0.0-20200223194434-40d9fd965c67/go.mod h1:0HAWYrvajFHDgRaKbF0rl+IybVLZL5z4gQ8koCMPhoU=
github.com/filecoin-project/specs-actors v0.0.0-20200223194852-39976038b18d h1:vukVHqbLQnXc+ZfhK+Cor3kaQx9SQbSZISqSeGjhYcE= github.com/filecoin-project/specs-actors v0.0.0-20200223194852-39976038b18d h1:vukVHqbLQnXc+ZfhK+Cor3kaQx9SQbSZISqSeGjhYcE=
github.com/filecoin-project/specs-actors v0.0.0-20200223194852-39976038b18d/go.mod h1:0HAWYrvajFHDgRaKbF0rl+IybVLZL5z4gQ8koCMPhoU= github.com/filecoin-project/specs-actors v0.0.0-20200223194852-39976038b18d/go.mod h1:0HAWYrvajFHDgRaKbF0rl+IybVLZL5z4gQ8koCMPhoU=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
@ -205,6 +198,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@ -397,6 +392,8 @@ github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UG
github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s= github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s=
github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8=
github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM= github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM=
github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM=
github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs=
github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs=
github.com/libp2p/go-libp2p v0.0.30/go.mod h1:XWT8FGHlhptAv1+3V/+J5mEpzyui/5bvFsNuWYs611A= github.com/libp2p/go-libp2p v0.0.30/go.mod h1:XWT8FGHlhptAv1+3V/+J5mEpzyui/5bvFsNuWYs611A=
github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM= github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM=
@ -432,6 +429,8 @@ github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZV
github.com/libp2p/go-libp2p-core v0.2.4 h1:Et6ykkTwI6PU44tr8qUF9k43vP0aduMNniShAbUJJw8= github.com/libp2p/go-libp2p-core v0.2.4 h1:Et6ykkTwI6PU44tr8qUF9k43vP0aduMNniShAbUJJw8=
github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g= github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g=
github.com/libp2p/go-libp2p-core v0.3.0 h1:F7PqduvrztDtFsAa/bcheQ3azmNo+Nq7m8hQY5GiUW8= github.com/libp2p/go-libp2p-core v0.3.0 h1:F7PqduvrztDtFsAa/bcheQ3azmNo+Nq7m8hQY5GiUW8=
github.com/libp2p/go-libp2p-core v0.3.0 h1:F7PqduvrztDtFsAa/bcheQ3azmNo+Nq7m8hQY5GiUW8=
github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw=
github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw=
github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE= github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE=
github.com/libp2p/go-libp2p-crypto v0.0.2/go.mod h1:eETI5OUfBnvARGOHrJz2eWNyTUxEGZnBxMcbUjfIj4I= github.com/libp2p/go-libp2p-crypto v0.0.2/go.mod h1:eETI5OUfBnvARGOHrJz2eWNyTUxEGZnBxMcbUjfIj4I=
@ -486,8 +485,8 @@ github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVd
github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s=
github.com/libp2p/go-libp2p-protocol v0.1.0 h1:HdqhEyhg0ToCaxgMhnOmUO8snQtt/kQlcjVk3UoJU3c= github.com/libp2p/go-libp2p-protocol v0.1.0 h1:HdqhEyhg0ToCaxgMhnOmUO8snQtt/kQlcjVk3UoJU3c=
github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk=
github.com/libp2p/go-libp2p-pubsub v0.2.3 h1:qJRnRnM7Z4xnHb4i6EBb3DKQXRPgtFWlKP4AmfJudLQ= github.com/libp2p/go-libp2p-pubsub v0.2.6 h1:ypZaukCFrtD8cNeeb9nnWG4MD2Y1T0p22aQ+f7FKJig=
github.com/libp2p/go-libp2p-pubsub v0.2.3/go.mod h1:Jscj3fk23R5mCrOwb625xjVs5ZEyTZcx/OlTwMDqU+g= github.com/libp2p/go-libp2p-pubsub v0.2.6/go.mod h1:5jEp7R3ItQ0pgcEMrPZYE9DQTg/H3CTc7Mu1j2G4Y5o=
github.com/libp2p/go-libp2p-quic-transport v0.1.1 h1:MFMJzvsxIEDEVKzO89BnB/FgvMj9WI4GDGUW2ArDPUA= github.com/libp2p/go-libp2p-quic-transport v0.1.1 h1:MFMJzvsxIEDEVKzO89BnB/FgvMj9WI4GDGUW2ArDPUA=
github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU= github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU=
github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q= github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q=
@ -593,6 +592,7 @@ github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.1.12 h1:WMhc1ik4LNkTg8U9l3hI1LvxKmIL+f1+WV/SZtCbDDA= github.com/miekg/dns v1.1.12 h1:WMhc1ik4LNkTg8U9l3hI1LvxKmIL+f1+WV/SZtCbDDA=
@ -650,6 +650,8 @@ github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wS
github.com/multiformats/go-multistream v0.0.4/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.0.4/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg=
github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ= github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ=
github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg=
github.com/multiformats/go-multistream v0.1.1 h1:JlAdpIFhBhGRLxe9W6Om0w++Gd6KMWoFPZL/dEnm9nI=
github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38=
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.2 h1:6sUvyh2YHpJCb8RZ6eYzj6iJQ4+chWYmyIHxszqlPTA= github.com/multiformats/go-varint v0.0.2 h1:6sUvyh2YHpJCb8RZ6eYzj6iJQ4+chWYmyIHxszqlPTA=
github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
@ -692,14 +694,17 @@ github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1/go.mod h1:uIp+gprXx
github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a h1:hjZfReYVLbqFkAtr2us7vdy04YWz3LVAirzP7reh8+M= github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a h1:hjZfReYVLbqFkAtr2us7vdy04YWz3LVAirzP7reh8+M=
github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk= github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
@ -767,9 +772,9 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20191216205031-b047b6acb3c0/go.mod h1:x
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 h1:WXhVOwj2USAXB5oMDwRl3piOux2XMV9TANaYxXHdkoE= github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 h1:WXhVOwj2USAXB5oMDwRl3piOux2XMV9TANaYxXHdkoE=
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI=
github.com/whyrusleeping/cbor-gen v0.0.0-20200206220010-03c9665e2a66 h1:LolR9FiEfQNn5U031bAhn/46po2JgWHKadYbcWFIJ+0= github.com/whyrusleeping/cbor-gen v0.0.0-20200206220010-03c9665e2a66 h1:LolR9FiEfQNn5U031bAhn/46po2JgWHKadYbcWFIJ+0=
github.com/whyrusleeping/cbor-gen v0.0.0-20200206220010-03c9665e2a66 h1:LolR9FiEfQNn5U031bAhn/46po2JgWHKadYbcWFIJ+0=
github.com/whyrusleeping/cbor-gen v0.0.0-20200206220010-03c9665e2a66/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI=
github.com/whyrusleeping/cbor-gen v0.0.0-20200206220010-03c9665e2a66/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= github.com/whyrusleeping/cbor-gen v0.0.0-20200206220010-03c9665e2a66/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI=
github.com/whyrusleeping/cbor-gen v0.0.0-20200213013405-80352c7ae952 h1:YGoOfwBeeb6A8t3eSe2nmPtMsyYPa6WzBmTbSPLRNK8=
github.com/whyrusleeping/cbor-gen v0.0.0-20200213013405-80352c7ae952/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI=
github.com/whyrusleeping/cbor-gen v0.0.0-20200222160900-51052a1e8191 h1:TeuxLwKwQy612jEhfVhGJTqLsM2EwMi1eJE052ug+NY= github.com/whyrusleeping/cbor-gen v0.0.0-20200222160900-51052a1e8191 h1:TeuxLwKwQy612jEhfVhGJTqLsM2EwMi1eJE052ug+NY=
github.com/whyrusleeping/cbor-gen v0.0.0-20200222160900-51052a1e8191/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= github.com/whyrusleeping/cbor-gen v0.0.0-20200222160900-51052a1e8191/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI=
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E=

View File

@ -10,6 +10,7 @@ import (
"reflect" "reflect"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
@ -18,11 +19,15 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
) )
var log = logging.Logger("rpc") const (
methodRetryFrequency = time.Second * 3
)
var ( var (
errorType = reflect.TypeOf(new(error)).Elem() errorType = reflect.TypeOf(new(error)).Elem()
contextType = reflect.TypeOf(new(context.Context)).Elem() contextType = reflect.TypeOf(new(context.Context)).Elem()
log = logging.Logger("rpc")
) )
// ErrClient is an error which occurred on the client side the library // ErrClient is an error which occurred on the client side the library
@ -78,12 +83,21 @@ type client struct {
// NewMergeClient is like NewClient, but allows to specify multiple structs // NewMergeClient is like NewClient, but allows to specify multiple structs
// to be filled in the same namespace, using one connection // to be filled in the same namespace, using one connection
func NewMergeClient(addr string, namespace string, outs []interface{}, requestHeader http.Header) (ClientCloser, error) { func NewMergeClient(addr string, namespace string, outs []interface{}, requestHeader http.Header, opts ...Option) (ClientCloser, error) {
conn, _, err := websocket.DefaultDialer.Dial(addr, requestHeader) connFactory := func() (*websocket.Conn, error) {
conn, _, err := websocket.DefaultDialer.Dial(addr, requestHeader)
return conn, err
}
conn, err := connFactory()
if err != nil { if err != nil {
return nil, err return nil, err
} }
var config Config
for _, o := range opts {
o(&config)
}
c := client{ c := client{
namespace: namespace, namespace: namespace,
} }
@ -95,11 +109,13 @@ func NewMergeClient(addr string, namespace string, outs []interface{}, requestHe
handlers := map[string]rpcHandler{} handlers := map[string]rpcHandler{}
go (&wsConn{ go (&wsConn{
conn: conn, conn: conn,
handler: handlers, connFactory: connFactory,
requests: c.requests, reconnectInterval: config.ReconnectInterval,
stop: stop, handler: handlers,
exiting: exiting, requests: c.requests,
stop: stop,
exiting: exiting,
}).handleWsConn(context.TODO()) }).handleWsConn(context.TODO())
for _, handler := range outs { for _, handler := range outs {
@ -269,6 +285,8 @@ type rpcFunc struct {
hasCtx int hasCtx int
retCh bool retCh bool
retry bool
} }
func (fn *rpcFunc) processResponse(resp clientResponse, rval reflect.Value) []reflect.Value { func (fn *rpcFunc) processResponse(resp clientResponse, rval reflect.Value) []reflect.Value {
@ -344,27 +362,38 @@ func (fn *rpcFunc) handleRpcCall(args []reflect.Value) (results []reflect.Value)
} }
} }
resp, err := fn.client.sendRequest(ctx, req, chCtor) var resp clientResponse
if err != nil { var err error
return fn.processError(fmt.Errorf("sendRequest failed: %w", err)) // keep retrying if got a forced closed websocket conn and calling method
} // has retry annotation
for {
if resp.ID != *req.ID { resp, err = fn.client.sendRequest(ctx, req, chCtor)
return fn.processError(xerrors.New("request and response id didn't match")) if err != nil {
} return fn.processError(fmt.Errorf("sendRequest failed: %w", err))
if fn.valOut != -1 && !fn.retCh {
val := reflect.New(fn.ftyp.Out(fn.valOut))
if resp.Result != nil {
log.Debugw("rpc result", "type", fn.ftyp.Out(fn.valOut))
if err := json.Unmarshal(resp.Result, val.Interface()); err != nil {
log.Warnw("unmarshaling failed", "message", string(resp.Result))
return fn.processError(xerrors.Errorf("unmarshaling result: %w", err))
}
} }
retVal = func() reflect.Value { return val.Elem() } if resp.ID != *req.ID {
return fn.processError(xerrors.New("request and response id didn't match"))
}
if fn.valOut != -1 && !fn.retCh {
val := reflect.New(fn.ftyp.Out(fn.valOut))
if resp.Result != nil {
log.Debugw("rpc result", "type", fn.ftyp.Out(fn.valOut))
if err := json.Unmarshal(resp.Result, val.Interface()); err != nil {
log.Warnw("unmarshaling failed", "message", string(resp.Result))
return fn.processError(xerrors.Errorf("unmarshaling result: %w", err))
}
}
retVal = func() reflect.Value { return val.Elem() }
}
retry := resp.Error != nil && resp.Error.Code == 2 && fn.retry
if !retry {
break
}
time.Sleep(methodRetryFrequency)
} }
return fn.processResponse(resp, retVal()) return fn.processResponse(resp, retVal())
@ -380,6 +409,7 @@ func (c *client) makeRpcFunc(f reflect.StructField) (reflect.Value, error) {
client: c, client: c,
ftyp: ftyp, ftyp: ftyp,
name: f.Name, name: f.Name,
retry: f.Tag.Get("retry") == "true",
} }
fun.valOut, fun.errOut, fun.nout = processFuncOut(ftyp) fun.valOut, fun.errOut, fun.nout = processFuncOut(ftyp)

19
lib/jsonrpc/options.go Normal file
View File

@ -0,0 +1,19 @@
package jsonrpc
import "time"
type Config struct {
ReconnectInterval time.Duration
}
var defaultConfig = Config{
ReconnectInterval: time.Second * 5,
}
type Option func(c *Config)
func WithReconnectInterval(d time.Duration) func(c *Config) {
return func(c *Config) {
c.ReconnectInterval = d
}
}

View File

@ -9,6 +9,7 @@ import (
"reflect" "reflect"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -42,11 +43,13 @@ type outChanReg struct {
type wsConn struct { type wsConn struct {
// outside params // outside params
conn *websocket.Conn conn *websocket.Conn
handler handlers connFactory func() (*websocket.Conn, error)
requests <-chan clientRequest reconnectInterval time.Duration
stop <-chan struct{} handler handlers
exiting chan struct{} requests <-chan clientRequest
stop <-chan struct{}
exiting chan struct{}
// incoming messages // incoming messages
incoming chan io.Reader incoming chan io.Reader
@ -419,6 +422,35 @@ func (c *wsConn) handleFrame(ctx context.Context, frame frame) {
} }
} }
func (c *wsConn) closeInFlight() {
for id, req := range c.inflight {
req.ready <- clientResponse{
Jsonrpc: "2.0",
ID: id,
Error: &respError{
Message: "handler: websocket connection closed",
Code: 2,
},
}
c.handlingLk.Lock()
for _, cancel := range c.handling {
cancel()
}
c.handlingLk.Unlock()
}
c.inflight = map[int64]clientRequest{}
c.handling = map[int64]context.CancelFunc{}
}
func (c *wsConn) closeChans() {
for chid := range c.chanHandlers {
hnd := c.chanHandlers[chid]
delete(c.chanHandlers, chid)
hnd(nil, false)
}
}
func (c *wsConn) handleWsConn(ctx context.Context) { func (c *wsConn) handleWsConn(ctx context.Context) {
c.incoming = make(chan io.Reader) c.incoming = make(chan io.Reader)
c.inflight = map[int64]clientRequest{} c.inflight = map[int64]clientRequest{}
@ -432,27 +464,10 @@ func (c *wsConn) handleWsConn(ctx context.Context) {
// on close, make sure to return from all pending calls, and cancel context // on close, make sure to return from all pending calls, and cancel context
// on all calls we handle // on all calls we handle
defer func() { defer c.closeInFlight()
for id, req := range c.inflight {
req.ready <- clientResponse{
Jsonrpc: "2.0",
ID: id,
Error: &respError{
Message: "handler: websocket connection closed",
},
}
c.handlingLk.Lock()
for _, cancel := range c.handling {
cancel()
}
c.handlingLk.Unlock()
}
}()
// wait for the first message // wait for the first message
go c.nextMessage() go c.nextMessage()
for { for {
select { select {
case r, ok := <-c.incoming: case r, ok := <-c.incoming:
@ -460,6 +475,28 @@ func (c *wsConn) handleWsConn(ctx context.Context) {
if c.incomingErr != nil { if c.incomingErr != nil {
if !websocket.IsCloseError(c.incomingErr, websocket.CloseNormalClosure) { if !websocket.IsCloseError(c.incomingErr, websocket.CloseNormalClosure) {
log.Debugw("websocket error", "error", c.incomingErr) log.Debugw("websocket error", "error", c.incomingErr)
// connection dropped unexpectedly, do our best to recover it
c.closeInFlight()
c.closeChans()
c.incoming = make(chan io.Reader) // listen again for responses
go func() {
var conn *websocket.Conn
for conn == nil {
time.Sleep(c.reconnectInterval)
var err error
if conn, err = c.connFactory(); err != nil {
log.Debugw("websocket connection retried failed", "error", err)
}
}
c.writeLk.Lock()
c.conn = conn
c.incomingErr = nil
c.writeLk.Unlock()
go c.nextMessage()
}()
continue
} }
} }
return // remote closed return // remote closed
@ -477,9 +514,23 @@ func (c *wsConn) handleWsConn(ctx context.Context) {
c.handleFrame(ctx, frame) c.handleFrame(ctx, frame)
go c.nextMessage() go c.nextMessage()
case req := <-c.requests: case req := <-c.requests:
c.writeLk.Lock()
if req.req.ID != nil { if req.req.ID != nil {
if c.incomingErr != nil { // No conn?, immediate fail
req.ready <- clientResponse{
Jsonrpc: "2.0",
ID: *req.req.ID,
Error: &respError{
Message: "handler: websocket connection closed",
Code: 2,
},
}
c.writeLk.Unlock()
break
}
c.inflight[*req.req.ID] = req c.inflight[*req.req.ID] = req
} }
c.writeLk.Unlock()
c.sendRequest(req.req) c.sendRequest(req.req)
case <-c.stop: case <-c.stop:
c.writeLk.Lock() c.writeLk.Lock()

View File

@ -167,7 +167,8 @@ func (api *api) SpawnStorage(fullNodeRepo string) (nodeInfo, error) {
initArgs := []string{"init", "--nosync"} initArgs := []string{"init", "--nosync"}
if fullNodeRepo == api.running[1].meta.Repo { if fullNodeRepo == api.running[1].meta.Repo {
initArgs = []string{"init", "--actor=t01000", "--genesis-miner", "--pre-sealed-sectors=" + filepath.Join(fullNodeRepo, "preseal")} presealPrefix := filepath.Join(fullNodeRepo, "preseal")
initArgs = []string{"init", "--actor=t01000", "--genesis-miner", "--pre-sealed-sectors=" + presealPrefix, "--pre-sealed-metadata=" + filepath.Join(presealPrefix, "pre-seal-t0101.json")}
} }
id := atomic.AddInt32(&api.cmds, 1) id := atomic.AddInt32(&api.cmds, 1)

View File

@ -63,7 +63,7 @@ func (n *ClientNodeAdapter) ListStorageProviders(ctx context.Context) ([]*storag
return nil, err return nil, err
} }
addresses, err := n.StateListMiners(ctx, ts) addresses, err := n.StateListMiners(ctx, ts.Key())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -71,17 +71,17 @@ func (n *ClientNodeAdapter) ListStorageProviders(ctx context.Context) ([]*storag
var out []*storagemarket.StorageProviderInfo var out []*storagemarket.StorageProviderInfo
for _, addr := range addresses { for _, addr := range addresses {
workerAddr, err := n.StateMinerWorker(ctx, addr, ts) workerAddr, err := n.StateMinerWorker(ctx, addr, ts.Key())
if err != nil { if err != nil {
return nil, err return nil, err
} }
sectorSize, err := n.StateMinerSectorSize(ctx, addr, ts) sectorSize, err := n.StateMinerSectorSize(ctx, addr, ts.Key())
if err != nil { if err != nil {
return nil, err return nil, err
} }
peerId, err := n.StateMinerPeerID(ctx, addr, ts) peerId, err := n.StateMinerPeerID(ctx, addr, ts.Key())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -98,7 +98,7 @@ func (n *ClientNodeAdapter) VerifySignature(sig crypto.Signature, addr address.A
} }
func (n *ClientNodeAdapter) ListClientDeals(ctx context.Context, addr address.Address) ([]storagemarket.StorageDeal, error) { func (n *ClientNodeAdapter) ListClientDeals(ctx context.Context, addr address.Address) ([]storagemarket.StorageDeal, error) {
allDeals, err := n.StateMarketDeals(ctx, nil) allDeals, err := n.StateMarketDeals(ctx, types.EmptyTSK)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -151,7 +151,7 @@ func (n *ClientNodeAdapter) EnsureFunds(ctx context.Context, addr address.Addres
} }
func (n *ClientNodeAdapter) GetBalance(ctx context.Context, addr address.Address) (storagemarket.Balance, error) { func (n *ClientNodeAdapter) GetBalance(ctx context.Context, addr address.Address) (storagemarket.Balance, error) {
bal, err := n.StateMarketBalance(ctx, addr, nil) bal, err := n.StateMarketBalance(ctx, addr, types.EmptyTSK)
if err != nil { if err != nil {
return storagemarket.Balance{}, err return storagemarket.Balance{}, err
} }

View File

@ -53,7 +53,7 @@ func NewProviderNodeAdapter(dag dtypes.StagingDAG, secb *sectorblocks.SectorBloc
func (n *ProviderNodeAdapter) PublishDeals(ctx context.Context, deal storagemarket.MinerDeal) (storagemarket.DealID, cid.Cid, error) { func (n *ProviderNodeAdapter) PublishDeals(ctx context.Context, deal storagemarket.MinerDeal) (storagemarket.DealID, cid.Cid, error) {
log.Info("publishing deal") log.Info("publishing deal")
worker, err := n.StateMinerWorker(ctx, deal.Proposal.Provider, nil) worker, err := n.StateMinerWorker(ctx, deal.Proposal.Provider, types.EmptyTSK)
if err != nil { if err != nil {
return 0, cid.Undef, err return 0, cid.Undef, err
} }
@ -114,7 +114,7 @@ func (n *ProviderNodeAdapter) VerifySignature(sig crypto.Signature, addr address
} }
func (n *ProviderNodeAdapter) ListProviderDeals(ctx context.Context, addr address.Address) ([]storagemarket.StorageDeal, error) { func (n *ProviderNodeAdapter) ListProviderDeals(ctx context.Context, addr address.Address) ([]storagemarket.StorageDeal, error) {
allDeals, err := n.StateMarketDeals(ctx, nil) allDeals, err := n.StateMarketDeals(ctx, types.EmptyTSK)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -132,7 +132,7 @@ func (n *ProviderNodeAdapter) ListProviderDeals(ctx context.Context, addr addres
} }
func (n *ProviderNodeAdapter) GetMinerWorker(ctx context.Context, miner address.Address) (address.Address, error) { func (n *ProviderNodeAdapter) GetMinerWorker(ctx context.Context, miner address.Address) (address.Address, error) {
addr, err := n.StateMinerWorker(ctx, miner, nil) addr, err := n.StateMinerWorker(ctx, miner, types.EmptyTSK)
return addr, err return addr, err
} }
@ -180,7 +180,7 @@ func (n *ProviderNodeAdapter) AddFunds(ctx context.Context, addr address.Address
} }
func (n *ProviderNodeAdapter) GetBalance(ctx context.Context, addr address.Address) (storagemarket.Balance, error) { func (n *ProviderNodeAdapter) GetBalance(ctx context.Context, addr address.Address) (storagemarket.Balance, error) {
bal, err := n.StateMarketBalance(ctx, addr, nil) bal, err := n.StateMarketBalance(ctx, addr, types.EmptyTSK)
if err != nil { if err != nil {
return storagemarket.Balance{}, err return storagemarket.Balance{}, err
} }
@ -220,7 +220,7 @@ func (n *ProviderNodeAdapter) LocatePieceForDealWithinSector(ctx context.Context
func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider address.Address, dealID uint64, cb storagemarket.DealSectorCommittedCallback) error { func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider address.Address, dealID uint64, cb storagemarket.DealSectorCommittedCallback) error {
checkFunc := func(ts *types.TipSet) (done bool, more bool, err error) { checkFunc := func(ts *types.TipSet) (done bool, more bool, err error) {
sd, err := n.StateMarketStorageDeal(ctx, abi.DealID(dealID), ts) sd, err := n.StateMarketStorageDeal(ctx, abi.DealID(dealID), ts.Key())
if err != nil { if err != nil {
// TODO: This may be fine for some errors // TODO: This may be fine for some errors
@ -247,7 +247,7 @@ func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provide
return false, nil return false, nil
} }
sd, err := n.StateMarketStorageDeal(ctx, abi.DealID(dealID), ts) sd, err := n.StateMarketStorageDeal(ctx, abi.DealID(dealID), ts.Key())
if err != nil { if err != nil {
return false, xerrors.Errorf("failed to look up deal on chain: %w", err) return false, xerrors.Errorf("failed to look up deal on chain: %w", err)
} }

View File

@ -259,11 +259,11 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error)
return m.lastWork, nil return m.lastWork, nil
} }
btsw, err := m.api.ChainTipSetWeight(ctx, bts) btsw, err := m.api.ChainTipSetWeight(ctx, bts.Key())
if err != nil { if err != nil {
return nil, err return nil, err
} }
ltsw, err := m.api.ChainTipSetWeight(ctx, m.lastWork.ts) ltsw, err := m.api.ChainTipSetWeight(ctx, m.lastWork.ts.Key())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -278,7 +278,7 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error)
} }
func (m *Miner) hasPower(ctx context.Context, addr address.Address, ts *types.TipSet) (bool, error) { func (m *Miner) hasPower(ctx context.Context, addr address.Address, ts *types.TipSet) (bool, error) {
power, err := m.api.StateMinerPower(ctx, addr, ts) power, err := m.api.StateMinerPower(ctx, addr, ts.Key())
if err != nil { if err != nil {
return false, err return false, err
} }
@ -318,7 +318,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
} }
// get pending messages early, // get pending messages early,
pending, err := m.api.MpoolPending(context.TODO(), base.ts) pending, err := m.api.MpoolPending(context.TODO(), base.ts.Key())
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to get pending messages: %w", err) return nil, xerrors.Errorf("failed to get pending messages: %w", err)
} }
@ -343,7 +343,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
} }
func (m *Miner) computeTicket(ctx context.Context, addr address.Address, base *MiningBase) (*types.Ticket, error) { func (m *Miner) computeTicket(ctx context.Context, addr address.Address, base *MiningBase) (*types.Ticket, error) {
w, err := m.api.StateMinerWorker(ctx, addr, nil) w, err := m.api.StateMinerWorker(ctx, addr, types.EmptyTSK)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -379,10 +379,10 @@ func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *type
nheight := base.ts.Height() + base.nullRounds + 1 nheight := base.ts.Height() + base.nullRounds + 1
// why even return this? that api call could just submit it for us // why even return this? that api call could just submit it for us
return m.api.MinerCreateBlock(context.TODO(), addr, base.ts, ticket, proof, msgs, nheight, uint64(uts)) return m.api.MinerCreateBlock(context.TODO(), addr, base.ts.Key(), ticket, proof, msgs, nheight, uint64(uts))
} }
type ActorLookup func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) type ActorLookup func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error)
func countFrom(msgs []*types.SignedMessage, from address.Address) (out int) { func countFrom(msgs []*types.SignedMessage, from address.Address) (out int) {
for _, msg := range msgs { for _, msg := range msgs {
@ -409,7 +409,7 @@ func SelectMessages(ctx context.Context, al ActorLookup, ts *types.TipSet, msgs
from := msg.Message.From from := msg.Message.From
if _, ok := inclNonces[from]; !ok { if _, ok := inclNonces[from]; !ok {
act, err := al(ctx, from, ts) act, err := al(ctx, from, ts.Key())
if err != nil { if err != nil {
log.Warnf("failed to check message sender balance, skipping message: %+v", err) log.Warnf("failed to check message sender balance, skipping message: %+v", err)
continue continue

View File

@ -33,7 +33,7 @@ func TestMessageFiltering(t *testing.T) {
}, },
} }
af := func(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, error) { af := func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error) {
return actors[addr], nil return actors[addr], nil
} }

View File

@ -92,6 +92,7 @@ const (
RunHelloKey RunHelloKey
RunBlockSyncKey RunBlockSyncKey
RunChainGraphsync
RunPeerMgrKey RunPeerMgrKey
HandleIncomingBlocksKey HandleIncomingBlocksKey
@ -159,7 +160,7 @@ func libp2p() Option {
Override(AddrsFactoryKey, lp2p.AddrsFactory(nil, nil)), Override(AddrsFactoryKey, lp2p.AddrsFactory(nil, nil)),
Override(SmuxTransportKey, lp2p.SmuxTransport(true)), Override(SmuxTransportKey, lp2p.SmuxTransport(true)),
Override(RelayKey, lp2p.Relay(true, false)), Override(RelayKey, lp2p.Relay(true, false)),
Override(SecurityKey, lp2p.Security(true, false)), Override(SecurityKey, lp2p.Security(true, true)),
Override(BaseRoutingKey, lp2p.BaseRouting), Override(BaseRoutingKey, lp2p.BaseRouting),
Override(new(routing.Routing), lp2p.Routing), Override(new(routing.Routing), lp2p.Routing),
@ -228,6 +229,7 @@ func Online() Option {
Override(RunHelloKey, modules.RunHello), Override(RunHelloKey, modules.RunHello),
Override(RunBlockSyncKey, modules.RunBlockSync), Override(RunBlockSyncKey, modules.RunBlockSync),
Override(RunChainGraphsync, modules.ChainGraphsync),
Override(RunPeerMgrKey, modules.RunPeerMgr), Override(RunPeerMgrKey, modules.RunPeerMgr),
Override(HandleIncomingBlocksKey, modules.HandleIncomingBlocks), Override(HandleIncomingBlocksKey, modules.HandleIncomingBlocks),

View File

@ -6,34 +6,23 @@ import (
"fmt" "fmt"
"io" "io"
cid "github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors" xerrors "golang.org/x/xerrors"
) )
var _ = xerrors.Errorf var _ = xerrors.Errorf
func (t *Message) MarshalCBOR(w io.Writer) error { func (t *HelloMessage) MarshalCBOR(w io.Writer) error {
if t == nil { if t == nil {
_, err := w.Write(cbg.CborNull) _, err := w.Write(cbg.CborNull)
return err return err
} }
if _, err := w.Write([]byte{165}); err != nil { if _, err := w.Write([]byte{132}); err != nil {
return err return err
} }
// t.HeaviestTipSet ([]cid.Cid) (slice) // t.HeaviestTipSet ([]cid.Cid) (slice)
if len("HeaviestTipSet") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"HeaviestTipSet\" was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len("HeaviestTipSet")))); err != nil {
return err
}
if _, err := w.Write([]byte("HeaviestTipSet")); err != nil {
return err
}
if len(t.HeaviestTipSet) > cbg.MaxLength { if len(t.HeaviestTipSet) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.HeaviestTipSet was too long") return xerrors.Errorf("Slice value in field t.HeaviestTipSet was too long")
} }
@ -47,50 +36,110 @@ func (t *Message) MarshalCBOR(w io.Writer) error {
} }
} }
// t.HeaviestTipSetWeight (big.Int) (struct) // t.HeaviestTipSetHeight (uint64) (uint64)
if len("HeaviestTipSetWeight") > cbg.MaxLength { if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.HeaviestTipSetHeight))); err != nil {
return xerrors.Errorf("Value in field \"HeaviestTipSetWeight\" was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len("HeaviestTipSetWeight")))); err != nil {
return err
}
if _, err := w.Write([]byte("HeaviestTipSetWeight")); err != nil {
return err return err
} }
// t.HeaviestTipSetWeight (types.BigInt) (struct)
if err := t.HeaviestTipSetWeight.MarshalCBOR(w); err != nil { if err := t.HeaviestTipSetWeight.MarshalCBOR(w); err != nil {
return err return err
} }
// t.GenesisHash (cid.Cid) (struct) // t.GenesisHash (cid.Cid) (struct)
if len("GenesisHash") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"GenesisHash\" was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len("GenesisHash")))); err != nil {
return err
}
if _, err := w.Write([]byte("GenesisHash")); err != nil {
return err
}
if err := cbg.WriteCid(w, t.GenesisHash); err != nil { if err := cbg.WriteCid(w, t.GenesisHash); err != nil {
return xerrors.Errorf("failed to write cid field t.GenesisHash: %w", err) return xerrors.Errorf("failed to write cid field t.GenesisHash: %w", err)
} }
return nil
}
func (t *HelloMessage) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 4 {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.HeaviestTipSet ([]cid.Cid) (slice)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > cbg.MaxLength {
return fmt.Errorf("t.HeaviestTipSet: array too large (%d)", extra)
}
if maj != cbg.MajArray {
return fmt.Errorf("expected cbor array")
}
if extra > 0 {
t.HeaviestTipSet = make([]cid.Cid, extra)
}
for i := 0; i < int(extra); i++ {
c, err := cbg.ReadCid(br)
if err != nil {
return xerrors.Errorf("reading cid field t.HeaviestTipSet failed: %w", err)
}
t.HeaviestTipSet[i] = c
}
// t.HeaviestTipSetHeight (uint64) (uint64)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.HeaviestTipSetHeight = uint64(extra)
// t.HeaviestTipSetWeight (types.BigInt) (struct)
{
if err := t.HeaviestTipSetWeight.UnmarshalCBOR(br); err != nil {
return err
}
}
// t.GenesisHash (cid.Cid) (struct)
{
c, err := cbg.ReadCid(br)
if err != nil {
return xerrors.Errorf("failed to read cid field t.GenesisHash: %w", err)
}
t.GenesisHash = c
}
return nil
}
func (t *LatencyMessage) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{130}); err != nil {
return err
}
// t.TArrial (int64) (int64) // t.TArrial (int64) (int64)
if len("TArrial") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"TArrial\" was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len("TArrial")))); err != nil {
return err
}
if _, err := w.Write([]byte("TArrial")); err != nil {
return err
}
if t.TArrial >= 0 { if t.TArrial >= 0 {
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.TArrial))); err != nil { if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.TArrial))); err != nil {
return err return err
@ -102,17 +151,6 @@ func (t *Message) MarshalCBOR(w io.Writer) error {
} }
// t.TSent (int64) (int64) // t.TSent (int64) (int64)
if len("TSent") > cbg.MaxLength {
return xerrors.Errorf("Value in field \"TSent\" was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len("TSent")))); err != nil {
return err
}
if _, err := w.Write([]byte("TSent")); err != nil {
return err
}
if t.TSent >= 0 { if t.TSent >= 0 {
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.TSent))); err != nil { if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.TSent))); err != nil {
return err return err
@ -125,143 +163,70 @@ func (t *Message) MarshalCBOR(w io.Writer) error {
return nil return nil
} }
func (t *Message) UnmarshalCBOR(r io.Reader) error { func (t *LatencyMessage) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r) br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br) maj, extra, err := cbg.CborReadHeader(br)
if err != nil { if err != nil {
return err return err
} }
if maj != cbg.MajMap { if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type map") return fmt.Errorf("cbor input should be of type array")
} }
if extra > cbg.MaxLength { if extra != 2 {
return fmt.Errorf("Message: map struct too large (%d)", extra) return fmt.Errorf("cbor input had wrong number of fields")
} }
var name string // t.TArrial (int64) (int64)
n := extra {
maj, extra, err := cbg.CborReadHeader(br)
for i := uint64(0); i < n; i++ { var extraI int64
if err != nil {
{ return err
sval, err := cbg.ReadString(br)
if err != nil {
return err
}
name = string(sval)
} }
switch maj {
switch name { case cbg.MajUnsignedInt:
// t.HeaviestTipSet ([]cid.Cid) (slice) extraI = int64(extra)
case "HeaviestTipSet": if extraI < 0 {
return fmt.Errorf("int64 positive overflow")
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
} }
case cbg.MajNegativeInt:
if extra > cbg.MaxLength { extraI = int64(extra)
return fmt.Errorf("t.HeaviestTipSet: array too large (%d)", extra) if extraI < 0 {
return fmt.Errorf("int64 negative oveflow")
} }
extraI = -1 - extraI
if maj != cbg.MajArray {
return fmt.Errorf("expected cbor array")
}
if extra > 0 {
t.HeaviestTipSet = make([]cid.Cid, extra)
}
for i := 0; i < int(extra); i++ {
c, err := cbg.ReadCid(br)
if err != nil {
return xerrors.Errorf("reading cid field t.HeaviestTipSet failed: %w", err)
}
t.HeaviestTipSet[i] = c
}
// t.HeaviestTipSetWeight (big.Int) (struct)
case "HeaviestTipSetWeight":
{
if err := t.HeaviestTipSetWeight.UnmarshalCBOR(br); err != nil {
return err
}
}
// t.GenesisHash (cid.Cid) (struct)
case "GenesisHash":
{
c, err := cbg.ReadCid(br)
if err != nil {
return xerrors.Errorf("failed to read cid field t.GenesisHash: %w", err)
}
t.GenesisHash = c
}
// t.TArrial (int64) (int64)
case "TArrial":
{
maj, extra, err := cbg.CborReadHeader(br)
var extraI int64
if err != nil {
return err
}
switch maj {
case cbg.MajUnsignedInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 positive overflow")
}
case cbg.MajNegativeInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 negative oveflow")
}
extraI = -1 - extraI
default:
return fmt.Errorf("wrong type for int64 field: %d", maj)
}
t.TArrial = int64(extraI)
}
// t.TSent (int64) (int64)
case "TSent":
{
maj, extra, err := cbg.CborReadHeader(br)
var extraI int64
if err != nil {
return err
}
switch maj {
case cbg.MajUnsignedInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 positive overflow")
}
case cbg.MajNegativeInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 negative oveflow")
}
extraI = -1 - extraI
default:
return fmt.Errorf("wrong type for int64 field: %d", maj)
}
t.TSent = int64(extraI)
}
default: default:
return fmt.Errorf("unknown struct field %d: '%s'", i, name) return fmt.Errorf("wrong type for int64 field: %d", maj)
} }
}
t.TArrial = int64(extraI)
}
// t.TSent (int64) (int64)
{
maj, extra, err := cbg.CborReadHeader(br)
var extraI int64
if err != nil {
return err
}
switch maj {
case cbg.MajUnsignedInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 positive overflow")
}
case cbg.MajNegativeInt:
extraI = int64(extra)
if extraI < 0 {
return fmt.Errorf("int64 negative oveflow")
}
extraI = -1 - extraI
default:
return fmt.Errorf("wrong type for int64 field: %d", maj)
}
t.TSent = int64(extraI)
}
return nil return nil
} }

View File

@ -12,7 +12,7 @@ import (
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
protocol "github.com/libp2p/go-libp2p-core/protocol" protocol "github.com/libp2p/go-libp2p-core/protocol"
"github.com/filecoin-project/go-cbor-util" cborutil "github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -23,11 +23,13 @@ const ProtocolID = "/fil/hello/1.0.0"
var log = logging.Logger("hello") var log = logging.Logger("hello")
type Message struct { type HelloMessage struct {
HeaviestTipSet []cid.Cid HeaviestTipSet []cid.Cid
HeaviestTipSetHeight uint64
HeaviestTipSetWeight big.Int HeaviestTipSetWeight big.Int
GenesisHash cid.Cid GenesisHash cid.Cid
}
type LatencyMessage struct {
TArrial int64 TArrial int64
TSent int64 TSent int64
} }
@ -57,7 +59,7 @@ func NewHelloService(h host.Host, cs *store.ChainStore, syncer *chain.Syncer, pm
func (hs *Service) HandleStream(s inet.Stream) { func (hs *Service) HandleStream(s inet.Stream) {
var hmsg Message var hmsg HelloMessage
if err := cborutil.ReadCborRPC(s, &hmsg); err != nil { if err := cborutil.ReadCborRPC(s, &hmsg); err != nil {
log.Infow("failed to read hello message, diconnecting", "error", err) log.Infow("failed to read hello message, diconnecting", "error", err)
s.Conn().Close() s.Conn().Close()
@ -79,7 +81,7 @@ func (hs *Service) HandleStream(s inet.Stream) {
defer s.Close() defer s.Close()
sent := time.Now() sent := time.Now()
msg := &Message{ msg := &LatencyMessage{
TArrial: arrived.UnixNano(), TArrial: arrived.UnixNano(),
TSent: sent.UnixNano(), TSent: sent.UnixNano(),
} }
@ -124,8 +126,9 @@ func (hs *Service) SayHello(ctx context.Context, pid peer.ID) error {
return err return err
} }
hmsg := &Message{ hmsg := &HelloMessage{
HeaviestTipSet: hts.Cids(), HeaviestTipSet: hts.Cids(),
HeaviestTipSetHeight: hts.Height(),
HeaviestTipSetWeight: weight, HeaviestTipSetWeight: weight,
GenesisHash: gen.Cid(), GenesisHash: gen.Cid(),
} }
@ -139,10 +142,12 @@ func (hs *Service) SayHello(ctx context.Context, pid peer.ID) error {
go func() { go func() {
defer s.Close() defer s.Close()
hmsg = &Message{} lmsg := &LatencyMessage{}
s.SetReadDeadline(time.Now().Add(10 * time.Second)) s.SetReadDeadline(time.Now().Add(10 * time.Second))
err := cborutil.ReadCborRPC(s, hmsg) err := cborutil.ReadCborRPC(s, lmsg)
ok := err == nil if err != nil {
log.Infow("reading latency message", "error", err)
}
t3 := time.Now() t3 := time.Now()
lat := t3.Sub(t0) lat := t3.Sub(t0)
@ -151,10 +156,10 @@ func (hs *Service) SayHello(ctx context.Context, pid peer.ID) error {
hs.pmgr.SetPeerLatency(pid, lat) hs.pmgr.SetPeerLatency(pid, lat)
} }
if ok { if err == nil {
if hmsg.TArrial != 0 && hmsg.TSent != 0 { if lmsg.TArrial != 0 && lmsg.TSent != 0 {
t1 := time.Unix(0, hmsg.TArrial) t1 := time.Unix(0, lmsg.TArrial)
t2 := time.Unix(0, hmsg.TSent) t2 := time.Unix(0, lmsg.TSent)
offset := t0.Sub(t1) + t3.Sub(t2) offset := t0.Sub(t1) + t3.Sub(t2)
offset /= 2 offset /= 2
log.Infow("time offset", "offset", offset.Seconds(), "peerid", pid.String()) log.Infow("time offset", "offset", offset.Seconds(), "peerid", pid.String())

View File

@ -67,12 +67,12 @@ func (a *API) ClientStartDeal(ctx context.Context, data cid.Cid, addr address.Ad
return nil, xerrors.Errorf("provided address doesn't exist in wallet") return nil, xerrors.Errorf("provided address doesn't exist in wallet")
} }
pid, err := a.StateMinerPeerID(ctx, miner, nil) pid, err := a.StateMinerPeerID(ctx, miner, types.EmptyTSK)
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed getting peer ID: %w", err) return nil, xerrors.Errorf("failed getting peer ID: %w", err)
} }
mw, err := a.StateMinerWorker(ctx, miner, nil) mw, err := a.StateMinerWorker(ctx, miner, types.EmptyTSK)
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed getting miner worker: %w", err) return nil, xerrors.Errorf("failed getting miner worker: %w", err)
} }
@ -279,7 +279,7 @@ func (a *API) ClientListImports(ctx context.Context) ([]api.Import, error) {
func (a *API) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, path string) error { func (a *API) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, path string) error {
if order.MinerPeerID == "" { if order.MinerPeerID == "" {
pid, err := a.StateMinerPeerID(ctx, order.Miner, nil) pid, err := a.StateMinerPeerID(ctx, order.Miner, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }

View File

@ -2,6 +2,9 @@ package impl
import ( import (
"context" "context"
"github.com/filecoin-project/lotus/node/modules/lp2p"
logging "github.com/ipfs/go-log/v2"
"github.com/gbrlsnchs/jwt/v3" "github.com/gbrlsnchs/jwt/v3"
"github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/host"
@ -21,6 +24,7 @@ type CommonAPI struct {
APISecret *dtypes.APIAlg APISecret *dtypes.APIAlg
Host host.Host Host host.Host
Router lp2p.BaseIpfsRouting
} }
type jwtPayload struct { type jwtPayload struct {
@ -79,6 +83,10 @@ func (a *CommonAPI) NetDisconnect(ctx context.Context, p peer.ID) error {
return a.Host.Network().ClosePeer(p) return a.Host.Network().ClosePeer(p)
} }
func (a *CommonAPI) NetFindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) {
return a.Router.FindPeer(ctx, p)
}
func (a *CommonAPI) ID(context.Context) (peer.ID, error) { func (a *CommonAPI) ID(context.Context) (peer.ID, error) {
return a.Host.ID(), nil return a.Host.ID(), nil
} }
@ -92,4 +100,12 @@ func (a *CommonAPI) Version(context.Context) (api.Version, error) {
}, nil }, nil
} }
func (a *CommonAPI) LogList(context.Context) ([]string, error) {
return logging.GetSubsystems(), nil
}
func (a *CommonAPI) LogSetLevel(ctx context.Context, subsystem, level string) error {
return logging.SetLogLevel(subsystem, level)
}
var _ api.Common = &CommonAPI{} var _ api.Common = &CommonAPI{}

View File

@ -164,7 +164,11 @@ func (a *ChainAPI) ChainGetParentReceipts(ctx context.Context, bcid cid.Cid) ([]
return out, nil return out, nil
} }
func (a *ChainAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, ts *types.TipSet) (*types.TipSet, error) { func (a *ChainAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return a.Chain.GetTipsetByHeight(ctx, h, ts) return a.Chain.GetTipsetByHeight(ctx, h, ts)
} }
@ -181,7 +185,11 @@ func (a *ChainAPI) ChainHasObj(ctx context.Context, obj cid.Cid) (bool, error) {
return a.Chain.Blockstore().Has(obj) return a.Chain.Blockstore().Has(obj)
} }
func (a *ChainAPI) ChainSetHead(ctx context.Context, ts *types.TipSet) error { func (a *ChainAPI) ChainSetHead(ctx context.Context, tsk types.TipSetKey) error {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return a.Chain.SetHead(ts) return a.Chain.SetHead(ts)
} }
@ -194,7 +202,11 @@ func (a *ChainAPI) ChainGetGenesis(ctx context.Context) (*types.TipSet, error) {
return types.NewTipSet([]*types.BlockHeader{genb}) return types.NewTipSet([]*types.BlockHeader{genb})
} }
func (a *ChainAPI) ChainTipSetWeight(ctx context.Context, ts *types.TipSet) (types.BigInt, error) { func (a *ChainAPI) ChainTipSetWeight(ctx context.Context, tsk types.TipSetKey) (types.BigInt, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return types.EmptyInt, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return a.Chain.Weight(ctx, ts) return a.Chain.Weight(ctx, ts)
} }
@ -327,7 +339,11 @@ func (a *ChainAPI) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Mess
return cm.VMMessage(), nil return cm.VMMessage(), nil
} }
func (a *ChainAPI) ChainExport(ctx context.Context, ts *types.TipSet) (<-chan []byte, error) { func (a *ChainAPI) ChainExport(ctx context.Context, tsk types.TipSetKey) (<-chan []byte, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
r, w := io.Pipe() r, w := io.Pipe()
out := make(chan []byte) out := make(chan []byte)
go func() { go func() {

View File

@ -24,7 +24,11 @@ type MpoolAPI struct {
Mpool *messagepool.MessagePool Mpool *messagepool.MessagePool
} }
func (a *MpoolAPI) MpoolPending(ctx context.Context, ts *types.TipSet) ([]*types.SignedMessage, error) { func (a *MpoolAPI) MpoolPending(ctx context.Context, tsk types.TipSetKey) ([]*types.SignedMessage, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
pending, mpts := a.Mpool.Pending() pending, mpts := a.Mpool.Pending()
haveCids := map[cid.Cid]struct{}{} haveCids := map[cid.Cid]struct{}{}

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"github.com/prometheus/common/log"
"strconv" "strconv"
"github.com/filecoin-project/go-amt-ipld/v2" "github.com/filecoin-project/go-amt-ipld/v2"
@ -45,15 +46,27 @@ type StateAPI struct {
Chain *store.ChainStore Chain *store.ChainStore
} }
func (a *StateAPI) StateMinerSectors(ctx context.Context, addr address.Address, ts *types.TipSet) ([]*api.ChainSectorInfo, error) { func (a *StateAPI) StateMinerSectors(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.ChainSectorInfo, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetMinerSectorSet(ctx, a.StateManager, ts, addr) return stmgr.GetMinerSectorSet(ctx, a.StateManager, ts, addr)
} }
func (a *StateAPI) StateMinerProvingSet(ctx context.Context, addr address.Address, ts *types.TipSet) ([]*api.ChainSectorInfo, error) { func (a *StateAPI) StateMinerProvingSet(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.ChainSectorInfo, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetMinerProvingSet(ctx, a.StateManager, ts, addr) return stmgr.GetMinerProvingSet(ctx, a.StateManager, ts, addr)
} }
func (a *StateAPI) StateMinerPower(ctx context.Context, maddr address.Address, ts *types.TipSet) (api.MinerPower, error) { func (a *StateAPI) StateMinerPower(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (api.MinerPower, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return api.MinerPower{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
mpow, tpow, err := stmgr.GetPower(ctx, a.StateManager, ts, maddr) mpow, tpow, err := stmgr.GetPower(ctx, a.StateManager, ts, maddr)
if err != nil { if err != nil {
return api.MinerPower{}, err return api.MinerPower{}, err
@ -75,28 +88,53 @@ func (a *StateAPI) StateMinerPower(ctx context.Context, maddr address.Address, t
}, nil }, nil
} }
func (a *StateAPI) StateMinerWorker(ctx context.Context, m address.Address, ts *types.TipSet) (address.Address, error) { func (a *StateAPI) StateMinerWorker(ctx context.Context, m address.Address, tsk types.TipSetKey) (address.Address, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return address.Undef, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetMinerWorker(ctx, a.StateManager, ts, m) return stmgr.GetMinerWorker(ctx, a.StateManager, ts, m)
} }
func (a *StateAPI) StateMinerPeerID(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) { func (a *StateAPI) StateMinerPeerID(ctx context.Context, m address.Address, tsk types.TipSetKey) (peer.ID, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return "", xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetMinerPeerID(ctx, a.StateManager, ts, m) return stmgr.GetMinerPeerID(ctx, a.StateManager, ts, m)
} }
func (a *StateAPI) StateMinerPostState(ctx context.Context, actor address.Address, ts *types.TipSet) (*miner.PoStState, error) { func (a *StateAPI) StateMinerPostState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*miner.PoStState, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetMinerPostState(ctx, a.StateManager, ts, actor) return stmgr.GetMinerPostState(ctx, a.StateManager, ts, actor)
} }
func (a *StateAPI) StateMinerSectorSize(ctx context.Context, actor address.Address, ts *types.TipSet) (abi.SectorSize, error) { func (a *StateAPI) StateMinerSectorSize(ctx context.Context, actor address.Address, tsk types.TipSetKey) (abi.SectorSize, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return 0, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetMinerSectorSize(ctx, a.StateManager, ts, actor) return stmgr.GetMinerSectorSize(ctx, a.StateManager, ts, actor)
} }
func (a *StateAPI) StateMinerFaults(ctx context.Context, addr address.Address, ts *types.TipSet) ([]abi.SectorNumber, error) { func (a *StateAPI) StateMinerFaults(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]abi.SectorNumber, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetMinerFaults(ctx, a.StateManager, ts, addr) return stmgr.GetMinerFaults(ctx, a.StateManager, ts, addr)
} }
func (a *StateAPI) StatePledgeCollateral(ctx context.Context, ts *types.TipSet) (types.BigInt, error) { func (a *StateAPI) StatePledgeCollateral(ctx context.Context, tsk types.TipSetKey) (types.BigInt, error) {
/*param, err := actors.SerializeParams(&actors.PledgeCollateralParams{Size: types.NewInt(0)}) /*ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return types.EmptyInt, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
param, err := actors.SerializeParams(&actors.PledgeCollateralParams{Size: types.NewInt(0)})
if err != nil { if err != nil {
return types.NewInt(0), err return types.NewInt(0), err
} }
@ -117,14 +155,23 @@ func (a *StateAPI) StatePledgeCollateral(ctx context.Context, ts *types.TipSet)
} }
return types.BigFromBytes(ret.Return), nil*/ return types.BigFromBytes(ret.Return), nil*/
log.Error("TODO StatePledgeCollateral")
return big.Zero(), nil return big.Zero(), nil
} }
func (a *StateAPI) StateCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.MethodCall, error) { func (a *StateAPI) StateCall(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (*api.MethodCall, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return a.StateManager.Call(ctx, msg, ts) return a.StateManager.Call(ctx, msg, ts)
} }
func (a *StateAPI) StateReplay(ctx context.Context, ts *types.TipSet, mc cid.Cid) (*api.ReplayResults, error) { func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.ReplayResults, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
m, r, err := a.StateManager.Replay(ctx, ts, mc) m, r, err := a.StateManager.Replay(ctx, ts, mc)
if err != nil { if err != nil {
return nil, err return nil, err
@ -157,7 +204,11 @@ func (a *StateAPI) stateForTs(ctx context.Context, ts *types.TipSet) (*state.Sta
return state.LoadStateTree(cst, st) return state.LoadStateTree(cst, st)
} }
func (a *StateAPI) StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) { func (a *StateAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
state, err := a.stateForTs(ctx, ts) state, err := a.stateForTs(ctx, ts)
if err != nil { if err != nil {
return nil, xerrors.Errorf("computing tipset state failed: %w", err) return nil, xerrors.Errorf("computing tipset state failed: %w", err)
@ -166,7 +217,11 @@ func (a *StateAPI) StateGetActor(ctx context.Context, actor address.Address, ts
return state.GetActor(actor) return state.GetActor(actor)
} }
func (a *StateAPI) StateLookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) { func (a *StateAPI) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return address.Undef, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
state, err := a.stateForTs(ctx, ts) state, err := a.stateForTs(ctx, ts)
if err != nil { if err != nil {
return address.Undef, err return address.Undef, err
@ -175,7 +230,11 @@ func (a *StateAPI) StateLookupID(ctx context.Context, addr address.Address, ts *
return state.LookupID(addr) return state.LookupID(addr)
} }
func (a *StateAPI) StateReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*api.ActorState, error) { func (a *StateAPI) StateReadState(ctx context.Context, act *types.Actor, tsk types.TipSetKey) (*api.ActorState, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
state, err := a.stateForTs(ctx, ts) state, err := a.stateForTs(ctx, ts)
if err != nil { if err != nil {
return nil, err return nil, err
@ -198,7 +257,11 @@ func (a *StateAPI) StateReadState(ctx context.Context, act *types.Actor, ts *typ
} }
// This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner // This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) { func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parentsTSK types.TipSetKey, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
parents, err := a.Chain.GetTipSetFromKey(parentsTSK)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", parentsTSK, err)
}
fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, ticket, proof, msgs, height, ts) fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, ticket, proof, msgs, height, ts)
if err != nil { if err != nil {
return nil, err return nil, err
@ -230,26 +293,46 @@ func (a *StateAPI) StateWaitMsg(ctx context.Context, msg cid.Cid) (*api.MsgWait,
}, nil }, nil
} }
func (a *StateAPI) StateGetReceipt(ctx context.Context, msg cid.Cid, ts *types.TipSet) (*types.MessageReceipt, error) { func (a *StateAPI) StateGetReceipt(ctx context.Context, msg cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return a.StateManager.GetReceipt(ctx, msg, ts) return a.StateManager.GetReceipt(ctx, msg, ts)
} }
func (a *StateAPI) StateListMiners(ctx context.Context, ts *types.TipSet) ([]address.Address, error) { func (a *StateAPI) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.ListMinerActors(ctx, a.StateManager, ts) return stmgr.ListMinerActors(ctx, a.StateManager, ts)
} }
func (a *StateAPI) StateListActors(ctx context.Context, ts *types.TipSet) ([]address.Address, error) { func (a *StateAPI) StateListActors(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return a.StateManager.ListAllActors(ctx, ts) return a.StateManager.ListAllActors(ctx, ts)
} }
func (a *StateAPI) StateMarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (api.MarketBalance, error) { func (a *StateAPI) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return api.MarketBalance{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return a.StateManager.MarketBalance(ctx, addr, ts) return a.StateManager.MarketBalance(ctx, addr, ts)
} }
func (a *StateAPI) StateMarketParticipants(ctx context.Context, ts *types.TipSet) (map[string]api.MarketBalance, error) { func (a *StateAPI) StateMarketParticipants(ctx context.Context, tsk types.TipSetKey) (map[string]api.MarketBalance, error) {
out := map[string]api.MarketBalance{} out := map[string]api.MarketBalance{}
var state actors.StorageMarketState var state actors.StorageMarketState
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
if _, err := a.StateManager.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil { if _, err := a.StateManager.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil {
return nil, err return nil, err
} }
@ -291,10 +374,14 @@ func (a *StateAPI) StateMarketParticipants(ctx context.Context, ts *types.TipSet
return out, nil return out, nil
} }
func (a *StateAPI) StateMarketDeals(ctx context.Context, ts *types.TipSet) (map[string]api.MarketDeal, error) { func (a *StateAPI) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (map[string]api.MarketDeal, error) {
out := map[string]api.MarketDeal{} out := map[string]api.MarketDeal{}
var state actors.StorageMarketState var state actors.StorageMarketState
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
if _, err := a.StateManager.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil { if _, err := a.StateManager.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil {
return nil, err return nil, err
} }
@ -331,7 +418,11 @@ func (a *StateAPI) StateMarketDeals(ctx context.Context, ts *types.TipSet) (map[
return out, nil return out, nil
} }
func (a *StateAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) { func (a *StateAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetStorageDeal(ctx, a.StateManager, dealId, ts) return stmgr.GetStorageDeal(ctx, a.StateManager, dealId, ts)
} }
@ -386,11 +477,19 @@ func (a *StateAPI) StateChangedActors(ctx context.Context, old cid.Cid, new cid.
return out, nil return out, nil
} }
func (a *StateAPI) StateMinerSectorCount(ctx context.Context, addr address.Address, ts *types.TipSet) (api.MinerSectors, error) { func (a *StateAPI) StateMinerSectorCount(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MinerSectors, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return api.MinerSectors{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.SectorSetSizes(ctx, a.StateManager, addr, ts) return stmgr.SectorSetSizes(ctx, a.StateManager, addr, ts)
} }
func (a *StateAPI) StateListMessages(ctx context.Context, match *types.Message, ts *types.TipSet, toheight abi.ChainEpoch) ([]cid.Cid, error) { func (a *StateAPI) StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toheight abi.ChainEpoch) ([]cid.Cid, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
if ts == nil { if ts == nil {
ts = a.Chain.GetHeaviestTipSet() ts = a.Chain.GetHeaviestTipSet()
} }
@ -439,13 +538,18 @@ func (a *StateAPI) StateListMessages(ctx context.Context, match *types.Message,
return out, nil return out, nil
} }
func (a *StateAPI) StateCompute(ctx context.Context, height abi.ChainEpoch, msgs []*types.Message, ts *types.TipSet) (cid.Cid, error) { func (a *StateAPI) StateCompute(ctx context.Context, height abi.ChainEpoch, msgs []*types.Message, tsk types.TipSetKey) (cid.Cid, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return cid.Undef, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.ComputeState(ctx, a.StateManager, height, msgs, ts) return stmgr.ComputeState(ctx, a.StateManager, height, msgs, ts)
} }
func (a *StateAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (types.BigInt, error) { func (a *StateAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
if ts == nil { ts, err := a.Chain.GetTipSetFromKey(tsk)
ts = a.Chain.GetHeaviestTipSet() if err != nil {
return types.EmptyInt, xerrors.Errorf("loading tipset %s: %w", tsk, err)
} }
var st samsig.State var st samsig.State

View File

@ -88,3 +88,12 @@ func (a *SyncAPI) SyncMarkBad(ctx context.Context, bcid cid.Cid) error {
a.Syncer.MarkBad(bcid) a.Syncer.MarkBad(bcid)
return nil return nil
} }
func (a *SyncAPI) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) {
reason, ok := a.Syncer.CheckBadBlockCache(bcid)
if !ok {
return "", nil
}
return reason, nil
}

View File

@ -3,6 +3,7 @@ package impl
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"github.com/filecoin-project/lotus/chain/types"
"io" "io"
"mime" "mime"
"net/http" "net/http"
@ -170,7 +171,7 @@ func (sm *StorageMinerAPI) ActorAddress(context.Context) (address.Address, error
} }
func (sm *StorageMinerAPI) ActorSectorSize(ctx context.Context, addr address.Address) (abi.SectorSize, error) { func (sm *StorageMinerAPI) ActorSectorSize(ctx context.Context, addr address.Address) (abi.SectorSize, error) {
return sm.Full.StateMinerSectorSize(ctx, addr, nil) return sm.Full.StateMinerSectorSize(ctx, addr, types.EmptyTSK)
} }
func (sm *StorageMinerAPI) PledgeSector(ctx context.Context) error { func (sm *StorageMinerAPI) PledgeSector(ctx context.Context) error {

View File

@ -10,6 +10,10 @@ import (
"github.com/ipfs/go-blockservice" "github.com/ipfs/go-blockservice"
"github.com/ipfs/go-car" "github.com/ipfs/go-car"
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
graphsync "github.com/ipfs/go-graphsync/impl"
"github.com/ipfs/go-graphsync/ipldbridge"
gsnet "github.com/ipfs/go-graphsync/network"
"github.com/ipfs/go-graphsync/storeutil"
blockstore "github.com/ipfs/go-ipfs-blockstore" blockstore "github.com/ipfs/go-ipfs-blockstore"
"github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/routing" "github.com/libp2p/go-libp2p-core/routing"
@ -74,6 +78,15 @@ func ChainBlockservice(bs dtypes.ChainBlockstore, rem dtypes.ChainExchange) dtyp
return blockservice.New(bs, rem) return blockservice.New(bs, rem)
} }
func ChainGraphsync(mctx helpers.MetricsCtx, lc fx.Lifecycle, ibs dtypes.ChainGCBlockstore, h host.Host) dtypes.ClientGraphsync {
graphsyncNetwork := gsnet.NewFromLibp2pHost(h)
ipldBridge := ipldbridge.NewIPLDBridge()
loader := storeutil.LoaderForBlockstore(ibs)
gs := graphsync.New(helpers.LifecycleCtx(mctx, lc), graphsyncNetwork, ipldBridge, loader, nil)
return gs
}
func ChainStore(lc fx.Lifecycle, bs dtypes.ChainBlockstore, ds dtypes.MetadataDS, syscalls runtime.Syscalls) *store.ChainStore { func ChainStore(lc fx.Lifecycle, bs dtypes.ChainBlockstore, ds dtypes.MetadataDS, syscalls runtime.Syscalls) *store.ChainStore {
chain := store.NewChainStore(bs, ds, syscalls) chain := store.NewChainStore(bs, ds, syscalls)

View File

@ -3,10 +3,12 @@ package modules
import ( import (
"context" "context"
"crypto/rand" "crypto/rand"
"github.com/filecoin-project/lotus/api/apistruct" "errors"
"io" "io"
"io/ioutil" "io/ioutil"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/addrutil" "github.com/filecoin-project/lotus/lib/addrutil"
@ -38,7 +40,8 @@ type jwtPayload struct {
func APISecret(keystore types.KeyStore, lr repo.LockedRepo) (*dtypes.APIAlg, error) { func APISecret(keystore types.KeyStore, lr repo.LockedRepo) (*dtypes.APIAlg, error) {
key, err := keystore.Get(JWTSecretName) key, err := keystore.Get(JWTSecretName)
if err != nil {
if errors.Is(err, types.ErrKeyInfoNotFound) {
log.Warn("Generating new API secret") log.Warn("Generating new API secret")
sk, err := ioutil.ReadAll(io.LimitReader(rand.Reader, 32)) sk, err := ioutil.ReadAll(io.LimitReader(rand.Reader, 32))
@ -68,6 +71,8 @@ func APISecret(keystore types.KeyStore, lr repo.LockedRepo) (*dtypes.APIAlg, err
if err := lr.SetAPIToken(cliToken); err != nil { if err := lr.SetAPIToken(cliToken); err != nil {
return nil, err return nil, err
} }
} else if err != nil {
return nil, xerrors.Errorf("could not get JWT Token: %w", err)
} }
return (*dtypes.APIAlg)(jwt.NewHS256(key.PrivateKey)), nil return (*dtypes.APIAlg)(jwt.NewHS256(key.PrivateKey)), nil

View File

@ -24,6 +24,7 @@ type ChainGCLocker blockstore.GCLocker
type ChainGCBlockstore blockstore.GCBlockstore type ChainGCBlockstore blockstore.GCBlockstore
type ChainExchange exchange.Interface type ChainExchange exchange.Interface
type ChainBlockService bserv.BlockService type ChainBlockService bserv.BlockService
type ChainGraphsync graphsync.GraphExchange
type ClientFilestore *filestore.Filestore type ClientFilestore *filestore.Filestore
type ClientBlockstore blockstore.Blockstore type ClientBlockstore blockstore.Blockstore

View File

@ -47,7 +47,8 @@ func Host(mctx helpers.MetricsCtx, lc fx.Lifecycle, params P2PHostIn) (RawHost,
libp2p.Peerstore(params.Peerstore), libp2p.Peerstore(params.Peerstore),
libp2p.NoListenAddrs, libp2p.NoListenAddrs,
libp2p.Ping(true), libp2p.Ping(true),
libp2p.UserAgent("lotus-" + build.UserVersion)} libp2p.UserAgent("lotus-" + build.UserVersion),
}
for _, o := range params.Opts { for _, o := range params.Opts {
opts = append(opts, o...) opts = append(opts, o...)
} }

View File

@ -15,7 +15,7 @@ func Security(enabled, preferTLS bool) interface{} {
if !enabled { if !enabled {
return func() (opts Libp2pOpts) { return func() (opts Libp2pOpts) {
// TODO: shouldn't this be Errorf to guarantee visibility? // TODO: shouldn't this be Errorf to guarantee visibility?
log.Warnf(`Your IPFS node has been configured to run WITHOUT ENCRYPTED CONNECTIONS. log.Warnf(`Your lotus node has been configured to run WITHOUT ENCRYPTED CONNECTIONS.
You will not be able to connect to any nodes configured to use encrypted connections`) You will not be able to connect to any nodes configured to use encrypted connections`)
opts.Opts = append(opts.Opts, libp2p.NoSecurity) opts.Opts = append(opts.Opts, libp2p.NoSecurity)
return opts return opts

View File

@ -5,6 +5,7 @@ import (
"github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/host"
inet "github.com/libp2p/go-libp2p-core/network" inet "github.com/libp2p/go-libp2p-core/network"
peer "github.com/libp2p/go-libp2p-peer"
pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub "github.com/libp2p/go-libp2p-pubsub"
"go.uber.org/fx" "go.uber.org/fx"
@ -15,12 +16,16 @@ import (
"github.com/filecoin-project/lotus/chain/blocksync" "github.com/filecoin-project/lotus/chain/blocksync"
"github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/lotus/chain/sub" "github.com/filecoin-project/lotus/chain/sub"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/peermgr" "github.com/filecoin-project/lotus/lib/peermgr"
"github.com/filecoin-project/lotus/node/hello" "github.com/filecoin-project/lotus/node/hello"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/modules/helpers" "github.com/filecoin-project/lotus/node/modules/helpers"
) )
const BlocksTopic = "/fil/blocks"
const MessagesTopic = "/fil/messages"
func RunHello(mctx helpers.MetricsCtx, lc fx.Lifecycle, h host.Host, svc *hello.Service) { func RunHello(mctx helpers.MetricsCtx, lc fx.Lifecycle, h host.Host, svc *hello.Service) {
h.SetStreamHandler(hello.ProtocolID, svc.HandleStream) h.SetStreamHandler(hello.ProtocolID, svc.HandleStream)
@ -45,25 +50,49 @@ func RunBlockSync(h host.Host, svc *blocksync.BlockSyncService) {
h.SetStreamHandler(blocksync.BlockSyncProtocolID, svc.HandleStream) h.SetStreamHandler(blocksync.BlockSyncProtocolID, svc.HandleStream)
} }
func HandleIncomingBlocks(mctx helpers.MetricsCtx, lc fx.Lifecycle, pubsub *pubsub.PubSub, s *chain.Syncer, h host.Host) { func HandleIncomingBlocks(mctx helpers.MetricsCtx, lc fx.Lifecycle, ps *pubsub.PubSub, s *chain.Syncer, h host.Host) {
ctx := helpers.LifecycleCtx(mctx, lc) ctx := helpers.LifecycleCtx(mctx, lc)
blocksub, err := pubsub.Subscribe("/fil/blocks") blocksub, err := ps.Subscribe(BlocksTopic)
if err != nil { if err != nil {
panic(err) panic(err)
} }
v := sub.NewBlockValidator(func(p peer.ID) {
ps.BlacklistPeer(p)
h.ConnManager().TagPeer(p, "badblock", -1000)
})
if err := ps.RegisterTopicValidator(BlocksTopic, v.Validate); err != nil {
panic(err)
}
go sub.HandleIncomingBlocks(ctx, blocksub, s, h.ConnManager()) go sub.HandleIncomingBlocks(ctx, blocksub, s, h.ConnManager())
} }
func HandleIncomingMessages(mctx helpers.MetricsCtx, lc fx.Lifecycle, pubsub *pubsub.PubSub, mpool *messagepool.MessagePool) { func HandleIncomingMessages(mctx helpers.MetricsCtx, lc fx.Lifecycle, ps *pubsub.PubSub, mpool *messagepool.MessagePool) {
ctx := helpers.LifecycleCtx(mctx, lc) ctx := helpers.LifecycleCtx(mctx, lc)
msgsub, err := pubsub.Subscribe("/fil/messages") msgsub, err := ps.Subscribe(MessagesTopic)
if err != nil { if err != nil {
panic(err) panic(err)
} }
v := func(ctx context.Context, pid peer.ID, msg *pubsub.Message) bool {
m, err := types.DecodeSignedMessage(msg.GetData())
if err != nil {
log.Errorf("got incorrectly formatted Message: %s", err)
return false
}
msg.ValidatorData = m
return true
}
if err := ps.RegisterTopicValidator(MessagesTopic, v); err != nil {
panic(err)
}
go sub.HandleIncomingMessages(ctx, mpool, msgsub) go sub.HandleIncomingMessages(ctx, mpool, msgsub)
} }

View File

@ -2,6 +2,7 @@ package modules
import ( import (
"context" "context"
"github.com/filecoin-project/lotus/chain/types"
"math" "math"
"reflect" "reflect"
@ -74,7 +75,7 @@ func SectorBuilderConfig(storage []fs.PathConfig, threads uint, noprecommit, noc
return nil, err return nil, err
} }
ssize, err := api.StateMinerSectorSize(context.TODO(), minerAddr, nil) ssize, err := api.StateMinerSectorSize(context.TODO(), minerAddr, types.EmptyTSK)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -113,7 +114,7 @@ func StorageMiner(mctx helpers.MetricsCtx, lc fx.Lifecycle, api api.FullNode, h
ctx := helpers.LifecycleCtx(mctx, lc) ctx := helpers.LifecycleCtx(mctx, lc)
worker, err := api.StateMinerWorker(ctx, maddr, nil) worker, err := api.StateMinerWorker(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -346,7 +346,7 @@ func (fsr *fsLockedRepo) Get(name string) (types.KeyInfo, error) {
} }
if fstat.Mode()&0077 != 0 { if fstat.Mode()&0077 != 0 {
return types.KeyInfo{}, xerrors.Errorf(kstrPermissionMsg, name, err) return types.KeyInfo{}, xerrors.Errorf(kstrPermissionMsg, name, fstat.Mode())
} }
file, err := os.Open(keyPath) file, err := os.Open(keyPath)

52
scripts/build-bundle.sh Executable file
View File

@ -0,0 +1,52 @@
#!/usr/bin/env bash
set -ex
ARCHS=(
"darwin"
"linux"
)
REQUIRED=(
"ipfs"
"sha512sum"
)
for REQUIRE in "${REQUIRED[@]}"
do
command -v "${REQUIRE}" >/dev/null 2>&1 || echo >&2 "'${REQUIRE}' must be installed"
done
mkdir bundle
pushd bundle
BINARIES=(
"lotus"
"lotus-storage-miner"
"lotus-seal-worker"
)
export IPFS_PATH=`mktemp -d`
ipfs init
ipfs daemon &
PID="$!"
trap "kill -9 ${PID}" EXIT
sleep 30
for ARCH in "${ARCHS[@]}"
do
mkdir -p "${ARCH}/lotus"
pushd "${ARCH}"
for BINARY in "${BINARIES[@]}"
do
cp "../../${ARCH}/${BINARY}" "lotus/"
chmod +x "lotus/${BINARY}"
done
tar -zcvf "../lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz" lotus
popd
rm -rf "${ARCH}"
sha512sum "lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz" | cut -d" " -f1 > "lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz.sha512"
ipfs add "lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz" | cut -d" " -f2 > "lotus_${CIRCLE_TAG}_${ARCH}-amd64.tar.gz.cid"
done
popd

View File

@ -4,4 +4,4 @@ set -o xtrace
export TRUST_PARAMS=1 export TRUST_PARAMS=1
go run -tags=debug ./cmd/lotus-storage-miner init --actor=t0101 --genesis-miner --pre-sealed-sectors=~/.genesis-sectors go run -tags=debug ./cmd/lotus-storage-miner init --actor=t0101 --genesis-miner --pre-sealed-sectors=~/.genesis-sectors --pre-sealed-metadata=~/.genesis-sectors/pre-seal-t0101.json

View File

@ -86,12 +86,12 @@ mdt0111=$(mktemp -d)
mdt0222=$(mktemp -d) mdt0222=$(mktemp -d)
mdt0333=$(mktemp -d) mdt0333=$(mktemp -d)
env LOTUS_PATH="${ldt0111}" LOTUS_STORAGE_PATH="${mdt0111}" ./lotus-storage-miner init --genesis-miner --actor=t0111 --pre-sealed-sectors="${sdt0111}" --nosync=true --sector-size="${SECTOR_SIZE}" || true env LOTUS_PATH="${ldt0111}" LOTUS_STORAGE_PATH="${mdt0111}" ./lotus-storage-miner init --genesis-miner --actor=t0111 --pre-sealed-sectors="${sdt0111}" --pre-sealed-metadata="${sdt0111}/pre-seal-t0111.json" --nosync=true --sector-size="${SECTOR_SIZE}" || true
env LOTUS_PATH="${ldt0111}" LOTUS_STORAGE_PATH="${mdt0111}" ./lotus-storage-miner run --nosync & env LOTUS_PATH="${ldt0111}" LOTUS_STORAGE_PATH="${mdt0111}" ./lotus-storage-miner run --nosync &
mpid=$! mpid=$!
env LOTUS_PATH="${ldt0222}" LOTUS_STORAGE_PATH="${mdt0222}" ./lotus-storage-miner init --actor=t0222 --pre-sealed-sectors="${sdt0222}" --nosync=true --sector-size="${SECTOR_SIZE}" || true env LOTUS_PATH="${ldt0222}" LOTUS_STORAGE_PATH="${mdt0222}" ./lotus-storage-miner init --actor=t0222 --pre-sealed-sectors="${sdt0222}" --pre-sealed-metadata="${sdt0222}/pre-seal-t0222.json" --nosync=true --sector-size="${SECTOR_SIZE}" || true
env LOTUS_PATH="${ldt0333}" LOTUS_STORAGE_PATH="${mdt0333}" ./lotus-storage-miner init --actor=t0333 --pre-sealed-sectors="${sdt0333}" --nosync=true --sector-size="${SECTOR_SIZE}" || true env LOTUS_PATH="${ldt0333}" LOTUS_STORAGE_PATH="${mdt0333}" ./lotus-storage-miner init --actor=t0333 --pre-sealed-sectors="${sdt0333}" --pre-sealed-metadata="${sdt0333}/pre-seal-t0333.json" --nosync=true --sector-size="${SECTOR_SIZE}" || true
kill $mpid kill $mpid
wait $mpid wait $mpid

94
scripts/publish-release.sh Executable file
View File

@ -0,0 +1,94 @@
#!/usr/bin/env bash
set -e
pushd bundle
# make sure we have a token set, api requests won't work otherwise
if [ -z "${GITHUB_TOKEN}" ]; then
echo "\${GITHUB_TOKEN} not set, publish failed"
exit 1
fi
REQUIRED=(
"jq"
"curl"
)
for REQUIRE in "${REQUIRED[@]}"
do
command -v "${REQUIRE}" >/dev/null 2>&1 || echo >&2 "'${REQUIRE}' must be installed"
done
#see if the release already exists by tag
RELEASE_RESPONSE=`
curl \
--header "Authorization: token ${GITHUB_TOKEN}" \
"https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/releases/tags/${CIRCLE_TAG}"
`
RELEASE_ID=`echo "${RELEASE_RESPONSE}" | jq '.id'`
if [ "${RELEASE_ID}" = "null" ]; then
echo "creating release"
RELEASE_DATA="{
\"tag_name\": \"${CIRCLE_TAG}\",
\"target_commitish\": \"${CIRCLE_SHA1}\",
\"name\": \"${CIRCLE_TAG}\",
\"body\": \"\",
\"prerelease\": false
}"
# create it if it doesn't exist yet
RELEASE_RESPONSE=`
curl \
--request POST \
--header "Authorization: token ${GITHUB_TOKEN}" \
--header "Content-Type: application/json" \
--data "${RELEASE_DATA}" \
"https://api.github.com/repos/$CIRCLE_PROJECT_USERNAME/${CIRCLE_PROJECT_REPONAME}/releases"
`
else
echo "release already exists"
fi
RELEASE_UPLOAD_URL=`echo "${RELEASE_RESPONSE}" | jq -r '.upload_url' | cut -d'{' -f1`
bundles=(
"lotus_${CIRCLE_TAG}_linux-amd64.tar.gz"
"lotus_${CIRCLE_TAG}_linux-amd64.tar.gz.cid"
"lotus_${CIRCLE_TAG}_linux-amd64.tar.gz.sha512"
"lotus_${CIRCLE_TAG}_darwin-amd64.tar.gz"
"lotus_${CIRCLE_TAG}_darwin-amd64.tar.gz.cid"
"lotus_${CIRCLE_TAG}_darwin-amd64.tar.gz.sha512"
)
for RELEASE_FILE in "${bundles[@]}"
do
echo "Uploading release bundle: ${RELEASE_FILE}"
curl \
--request POST \
--header "Authorization: token ${GITHUB_TOKEN}" \
--header "Content-Type: application/octet-stream" \
--data-binary "@${RELEASE_FILE}" \
"$RELEASE_UPLOAD_URL?name=$(basename "${RELEASE_FILE}")"
echo "Release bundle uploaded: ${RELEASE_FILE}"
done
popd
miscellaneous=(
"README.md"
"LICENSE-MIT"
"LICENSE-APACHE"
)
for MISC in "${miscellaneous[@]}"
do
echo "Uploading release bundle: ${MISC}"
curl \
--request POST \
--header "Authorization: token ${GITHUB_TOKEN}" \
--header "Content-Type: application/octet-stream" \
--data-binary "@${MISC}" \
"$RELEASE_UPLOAD_URL?name=$(basename "${MISC}")"
echo "Release bundle uploaded: ${MISC}"
done

View File

@ -97,7 +97,7 @@ func (s *FPoStScheduler) checkFaults(ctx context.Context, ssi sectorbuilder.Sort
declaredFaults := map[abi.SectorNumber]struct{}{} declaredFaults := map[abi.SectorNumber]struct{}{}
{ {
chainFaults, err := s.api.StateMinerFaults(ctx, s.actor, nil) chainFaults, err := s.api.StateMinerFaults(ctx, s.actor, types.EmptyTSK)
if err != nil { if err != nil {
return nil, xerrors.Errorf("checking on-chain faults: %w", err) return nil, xerrors.Errorf("checking on-chain faults: %w", err)
} }
@ -210,7 +210,7 @@ func (s *FPoStScheduler) runPost(ctx context.Context, eps abi.ChainEpoch, ts *ty
} }
func (s *FPoStScheduler) sortedSectorInfo(ctx context.Context, ts *types.TipSet) (sectorbuilder.SortedPublicSectorInfo, error) { func (s *FPoStScheduler) sortedSectorInfo(ctx context.Context, ts *types.TipSet) (sectorbuilder.SortedPublicSectorInfo, error) {
sset, err := s.api.StateMinerProvingSet(ctx, s.actor, ts) sset, err := s.api.StateMinerProvingSet(ctx, s.actor, ts.Key())
if err != nil { if err != nil {
return sectorbuilder.SortedPublicSectorInfo{}, xerrors.Errorf("failed to get proving set for miner (tsH: %d): %w", ts.Height(), err) return sectorbuilder.SortedPublicSectorInfo{}, xerrors.Errorf("failed to get proving set for miner (tsH: %d): %w", ts.Height(), err)
} }

View File

@ -163,7 +163,7 @@ func (s *FPoStScheduler) abortActivePoSt() {
} }
func (s *FPoStScheduler) shouldFallbackPost(ctx context.Context, ts *types.TipSet) (abi.ChainEpoch, bool, error) { func (s *FPoStScheduler) shouldFallbackPost(ctx context.Context, ts *types.TipSet) (abi.ChainEpoch, bool, error) {
ps, err := s.api.StateMinerPostState(ctx, s.actor, ts) ps, err := s.api.StateMinerPostState(ctx, s.actor, ts.Key())
if err != nil { if err != nil {
return 0, false, xerrors.Errorf("getting ElectionPeriodStart: %w", err) return 0, false, xerrors.Errorf("getting ElectionPeriodStart: %w", err)
} }

View File

@ -43,24 +43,24 @@ type Miner struct {
type storageMinerApi interface { type storageMinerApi interface {
// Call a read only method on actors (no interaction with the chain required) // Call a read only method on actors (no interaction with the chain required)
StateCall(context.Context, *types.Message, *types.TipSet) (*api.MethodCall, error) StateCall(context.Context, *types.Message, types.TipSetKey) (*api.MethodCall, error)
StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error) StateMinerWorker(context.Context, address.Address, types.TipSetKey) (address.Address, error)
StateMinerPostState(ctx context.Context, actor address.Address, ts *types.TipSet) (*miner.PoStState, error) StateMinerPostState(ctx context.Context, actor address.Address, ts types.TipSetKey) (*miner.PoStState, error)
StateMinerSectors(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) StateMinerSectors(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error)
StateMinerProvingSet(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) StateMinerProvingSet(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error)
StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (abi.SectorSize, error) StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error)
StateWaitMsg(context.Context, cid.Cid) (*api.MsgWait, error) // TODO: removeme eventually StateWaitMsg(context.Context, cid.Cid) (*api.MsgWait, error) // TODO: removeme eventually
StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
StateGetReceipt(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateMarketStorageDeal(context.Context, abi.DealID, *types.TipSet) (*api.MarketDeal, error) StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error)
StateMinerFaults(context.Context, address.Address, *types.TipSet) ([]abi.SectorNumber, error) StateMinerFaults(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error)
MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error) MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error)
ChainHead(context.Context) (*types.TipSet, error) ChainHead(context.Context) (types.TipSetKey, error)
ChainNotify(context.Context) (<-chan []*store.HeadChange, error) ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error)
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, *types.TipSet) (*types.TipSet, error) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
ChainReadObj(context.Context, cid.Cid) ([]byte, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error)
ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHasObj(context.Context, cid.Cid) (bool, error)

View File

@ -49,7 +49,7 @@ func checkPieces(ctx context.Context, si SectorInfo, api sealingApi) error {
} }
continue continue
} }
deal, err := api.StateMarketStorageDeal(ctx, *piece.DealID, nil) deal, err := api.StateMarketStorageDeal(ctx, *piece.DealID, types.EmptyTSK)
if err != nil { if err != nil {
return &ErrApi{xerrors.Errorf("getting deal %d for piece %d: %w", piece.DealID, i, err)} return &ErrApi{xerrors.Errorf("getting deal %d for piece %d: %w", piece.DealID, i, err)}
} }
@ -83,7 +83,7 @@ func checkSeal(ctx context.Context, maddr address.Address, si SectorInfo, api se
return &ErrApi{xerrors.Errorf("getting chain head: %w", err)} return &ErrApi{xerrors.Errorf("getting chain head: %w", err)}
} }
ssize, err := api.StateMinerSectorSize(ctx, maddr, head) ssize, err := api.StateMinerSectorSize(ctx, maddr, head.Key())
if err != nil { if err != nil {
return &ErrApi{err} return &ErrApi{err}
} }
@ -105,7 +105,7 @@ func checkSeal(ctx context.Context, maddr address.Address, si SectorInfo, api se
Method: builtin.MethodsMarket.ComputeDataCommitment, Method: builtin.MethodsMarket.ComputeDataCommitment,
Params: ccparams, Params: ccparams,
} }
r, err := api.StateCall(ctx, ccmt, nil) r, err := api.StateCall(ctx, ccmt, types.EmptyTSK)
if err != nil { if err != nil {
return &ErrApi{xerrors.Errorf("calling ComputeDataCommitment: %w", err)} return &ErrApi{xerrors.Errorf("calling ComputeDataCommitment: %w", err)}
} }

View File

@ -32,23 +32,23 @@ type TicketFn func(context.Context) (*sectorbuilder.SealTicket, error)
type sealingApi interface { // TODO: trim down type sealingApi interface { // TODO: trim down
// Call a read only method on actors (no interaction with the chain required) // Call a read only method on actors (no interaction with the chain required)
StateCall(context.Context, *types.Message, *types.TipSet) (*api.MethodCall, error) StateCall(context.Context, *types.Message, types.TipSetKey) (*api.MethodCall, error)
StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error) StateMinerWorker(context.Context, address.Address, types.TipSetKey) (address.Address, error)
StateMinerPostState(ctx context.Context, actor address.Address, ts *types.TipSet) (*miner.PoStState, error) StateMinerPostState(ctx context.Context, actor address.Address, ts types.TipSetKey) (*miner.PoStState, error)
StateMinerSectors(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) StateMinerSectors(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error)
StateMinerProvingSet(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) StateMinerProvingSet(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error)
StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (abi.SectorSize, error) StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error)
StateWaitMsg(context.Context, cid.Cid) (*api.MsgWait, error) // TODO: removeme eventually StateWaitMsg(context.Context, cid.Cid) (*api.MsgWait, error) // TODO: removeme eventually
StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
StateGetReceipt(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateMarketStorageDeal(context.Context, abi.DealID, *types.TipSet) (*api.MarketDeal, error) StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error)
MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error) MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error)
ChainHead(context.Context) (*types.TipSet, error) ChainHead(context.Context) (types.TipSetKey, error)
ChainNotify(context.Context) (<-chan []*store.HeadChange, error) ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error)
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, *types.TipSet) (*types.TipSet, error) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
ChainReadObj(context.Context, cid.Cid) ([]byte, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error)
ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHasObj(context.Context, cid.Cid) (bool, error)

View File

@ -13,6 +13,7 @@ import (
"github.com/filecoin-project/lotus/api/apibstore" "github.com/filecoin-project/lotus/api/apibstore"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/statemachine" "github.com/filecoin-project/lotus/lib/statemachine"
) )
@ -33,7 +34,7 @@ func failedCooldown(ctx statemachine.Context, sector SectorInfo) error {
} }
func (m *Sealing) checkPreCommitted(ctx statemachine.Context, sector SectorInfo) (*miner.SectorPreCommitOnChainInfo, bool) { func (m *Sealing) checkPreCommitted(ctx statemachine.Context, sector SectorInfo) (*miner.SectorPreCommitOnChainInfo, bool) {
act, err := m.api.StateGetActor(ctx.Context(), m.maddr, nil) act, err := m.api.StateGetActor(ctx.Context(), m.maddr, types.EmptyTSK)
if err != nil { if err != nil {
log.Errorf("handleSealFailed(%d): temp error: %+v", sector.SectorID, err) log.Errorf("handleSealFailed(%d): temp error: %+v", sector.SectorID, err)
return nil, true return nil, true

View File

@ -137,7 +137,7 @@ func RecordTipsetPoints(ctx context.Context, api api.FullNode, pl *PointList, ti
} }
func RecordTipsetStatePoints(ctx context.Context, api api.FullNode, pl *PointList, tipset *types.TipSet) error { func RecordTipsetStatePoints(ctx context.Context, api api.FullNode, pl *PointList, tipset *types.TipSet) error {
pc, err := api.StatePledgeCollateral(ctx, tipset) pc, err := api.StatePledgeCollateral(ctx, tipset.Key())
if err != nil { if err != nil {
return err return err
} }
@ -159,7 +159,7 @@ func RecordTipsetStatePoints(ctx context.Context, api api.FullNode, pl *PointLis
p = NewPoint("network.balance", netBalFilFloat) p = NewPoint("network.balance", netBalFilFloat)
pl.AddPoint(p) pl.AddPoint(p)
power, err := api.StateMinerPower(ctx, address.Address{}, tipset) power, err := api.StateMinerPower(ctx, address.Address{}, tipset.Key())
if err != nil { if err != nil {
return err return err
} }
@ -167,9 +167,9 @@ func RecordTipsetStatePoints(ctx context.Context, api api.FullNode, pl *PointLis
p = NewPoint("chain.power", power.TotalPower.Int64()) p = NewPoint("chain.power", power.TotalPower.Int64())
pl.AddPoint(p) pl.AddPoint(p)
miners, err := api.StateListMiners(ctx, tipset) miners, err := api.StateListMiners(ctx, tipset.Key())
for _, miner := range miners { for _, miner := range miners {
power, err := api.StateMinerPower(ctx, miner, tipset) power, err := api.StateMinerPower(ctx, miner, tipset.Key())
if err != nil { if err != nil {
return err return err
} }
@ -218,7 +218,7 @@ func RecordTipsetMessagesPoints(ctx context.Context, api api.FullNode, pl *Point
p = NewPoint("chain.message_size", len(bs)) p = NewPoint("chain.message_size", len(bs))
pl.AddPoint(p) pl.AddPoint(p)
actor, err := api.StateGetActor(ctx, msg.Message.To, tipset) actor, err := api.StateGetActor(ctx, msg.Message.To, tipset.Key())
if err != nil { if err != nil {
return err return err
} }