Compare commits

..
237 changed files with 4582 additions and 5544 deletions
+33 -18
View File
@@ -1,6 +1,6 @@
version: 2.1 version: 2.1
orbs: orbs:
go: gotest/tools@0.0.13 go: gotest/tools@0.0.9
executors: executors:
golang: golang:
@@ -79,6 +79,7 @@ jobs:
steps: steps:
- install-deps - install-deps
- prepare - prepare
- go/mod-download
- go/mod-tidy-check - go/mod-tidy-check
build-all: build-all:
@@ -86,8 +87,12 @@ jobs:
steps: steps:
- install-deps - install-deps
- prepare - prepare
- go/mod-download
- run: sudo apt-get update - run: sudo apt-get update
- run: sudo apt-get install npm - run: sudo apt-get install npm
- restore_cache:
name: restore go mod cache
key: v1-go-deps-{{ arch }}-{{ checksum "/home/circleci/project/go.mod" }}
- run: - run:
command: make buildall command: make buildall
- store_artifacts: - store_artifacts:
@@ -107,6 +112,10 @@ jobs:
steps: steps:
- install-deps - install-deps
- prepare - prepare
- go/mod-download
- restore_cache:
name: restore go mod cache
key: v1-go-deps-{{ arch }}-{{ checksum "/home/circleci/project/go.mod" }}
- run: - run:
command: make debug command: make debug
@@ -125,9 +134,6 @@ jobs:
type: string type: string
default: "./..." default: "./..."
description: Import paths of packages to be tested. description: Import paths of packages to be tested.
winpost-test:
type: string
default: "0"
test-suite-name: test-suite-name:
type: string type: string
default: unit default: unit
@@ -150,6 +156,10 @@ jobs:
steps: steps:
- install-deps - install-deps
- prepare - prepare
- go/mod-download
- restore_cache:
name: restore go mod cache
key: v1-go-deps-{{ arch }}-{{ checksum "/home/circleci/project/go.mod" }}
- run: - run:
command: make deps lotus command: make deps lotus
no_output_timeout: 30m no_output_timeout: 30m
@@ -161,7 +171,6 @@ jobs:
environment: environment:
GOTESTSUM_JUNITFILE: /tmp/test-reports/<< parameters.test-suite-name >>/junit.xml GOTESTSUM_JUNITFILE: /tmp/test-reports/<< parameters.test-suite-name >>/junit.xml
GOTESTSUM_FORMAT: << parameters.gotestsum-format >> GOTESTSUM_FORMAT: << parameters.gotestsum-format >>
LOTUS_TEST_WINDOW_POST: << parameters.winpost-test >>
command: | command: |
mkdir -p /tmp/test-reports/<< parameters.test-suite-name >> mkdir -p /tmp/test-reports/<< parameters.test-suite-name >>
gotestsum -- \ gotestsum -- \
@@ -180,11 +189,16 @@ jobs:
shell: /bin/bash -eo pipefail shell: /bin/bash -eo pipefail
command: | command: |
bash <(curl -s https://codecov.io/bash) bash <(curl -s https://codecov.io/bash)
- save_cache:
name: save go mod cache
key: v1-go-deps-{{ arch }}-{{ checksum "/home/circleci/project/go.mod" }}
paths:
- "~/go/pkg"
- "~/go/src/github.com"
- "~/go/src/golang.org"
test-short: test-short:
<<: *test <<: *test
test-window-post:
<<: *test
build-macos: build-macos:
description: build darwin lotus binary description: build darwin lotus binary
@@ -211,12 +225,14 @@ jobs:
- run: - run:
name: Install jq name: Install jq
command: | command: |
curl --location https://github.com/stedolan/jq/releases/download/jq-1.6/jq-osx-amd64 --output /usr/local/bin/jq mkdir $HOME/.bin
chmod +x /usr/local/bin/jq curl --location https://github.com/stedolan/jq/releases/download/jq-1.6/jq-osx-amd64 --output $HOME/.bin/jq
chmod +x $HOME/.bin/jq
- restore_cache: - restore_cache:
name: restore cargo cache name: restore go mod and 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" }}
- install-deps - install-deps
- go/mod-download
- run: - run:
command: make build command: make build
no_output_timeout: 30m no_output_timeout: 30m
@@ -243,6 +259,7 @@ jobs:
steps: steps:
- install-deps - install-deps
- prepare - prepare
- go/mod-download
- run: - run:
command: "! go fmt ./... 2>&1 | read" command: "! go fmt ./... 2>&1 | read"
@@ -255,7 +272,7 @@ jobs:
default: golang default: golang
golangci-lint-version: golangci-lint-version:
type: string type: string
default: 1.27.0 default: 1.23.8
concurrency: concurrency:
type: string type: string
default: '2' default: '2'
@@ -271,6 +288,7 @@ jobs:
steps: steps:
- install-deps - install-deps
- prepare - prepare
- go/mod-download
- run: - run:
command: make deps command: make deps
no_output_timeout: 30m no_output_timeout: 30m
@@ -280,7 +298,7 @@ jobs:
- run: - run:
name: Lint name: Lint
command: | command: |
$HOME/.local/bin/golangci-lint run -v --timeout 2m \ $HOME/.local/bin/golangci-lint run -v \
--concurrency << parameters.concurrency >> << parameters.args >> --concurrency << parameters.concurrency >> << parameters.args >>
lint-changes: lint-changes:
<<: *lint <<: *lint
@@ -314,14 +332,11 @@ workflows:
ci: ci:
jobs: jobs:
- lint-changes: - lint-changes:
args: "--new-from-rev origin/next" args: "--new-from-rev origin/master"
- mod-tidy-check
- gofmt
- test: - test:
codecov-upload: true codecov-upload: true
- test-window-post: - mod-tidy-check
go-test-flags: "-run=TestWindowedPost" - gofmt
winpost-test: "1"
- test-short: - test-short:
go-test-flags: "--timeout 10m --short" go-test-flags: "--timeout 10m --short"
filters: filters:
-34
View File
@@ -1,34 +0,0 @@
---
name: Sealing Issues
about: Create a report for help with sealing (commit) failures.
title: ''
labels: 'sealing'
assignees: ''
---
Please provide all the information requested here to help us troubleshoot "commit failed" issues.
If the information requested is missing, we will probably have to just ask you to provide it anyway,
before we can help debug.
**Describe the problem**
A brief description of the problem you encountered while proving (sealing) a sector.
Including what commands you ran, and a description of your setup, is very helpful.
**Sectors list**
The output of `./lotus-storage-miner sectors list`.
**Sectors status**
The output of `./lotus-storage-miner sectors status --log <sectorId>` for the failed sector(s).
**Lotus storage miner logs**
Please go through the logs of your storage miner, and include screenshots of any error-like messages you find.
**Version**
The output of `./lotus --version`.
+1 -15
View File
@@ -22,27 +22,13 @@ issues:
- "func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this" - "func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this"
- "Potential file inclusion via variable" - "Potential file inclusion via variable"
- "should have( a package)? comment" - "should have( a package)? comment"
- "Error return value of `logging.SetLogLevel` is not checked"
exclude-use-default: false exclude-use-default: false
exclude-rules: exclude-rules:
- path: lotuspond
linters:
- errcheck
- path: node/modules/lp2p - path: node/modules/lp2p
linters: linters:
- golint - golint
- path: ".*_test.go"
- path: build/params_.*\.go
linters:
- golint
- path: api/apistruct/struct.go
linters:
- golint
- path: .*_test.go
linters: linters:
- gosec - gosec
+2 -15
View File
@@ -17,7 +17,7 @@ MODULES:=
CLEAN:= CLEAN:=
BINS:= BINS:=
ldflags=-X=github.com/filecoin-project/lotus/build.CurrentCommit=+git.$(subst -,.,$(shell git describe --always --match=NeVeRmAtCh --dirty 2>/dev/null || git rev-parse --short HEAD 2>/dev/null)) ldflags=-X=github.com/filecoin-project/lotus/build.CurrentCommit='+git$(subst -,.,$(shell git describe --always --match=NeVeRmAtCh --dirty 2>/dev/null || git rev-parse --short HEAD 2>/dev/null))'
ifneq ($(strip $(LDFLAGS)),) ifneq ($(strip $(LDFLAGS)),)
ldflags+=-extldflags=$(LDFLAGS) ldflags+=-extldflags=$(LDFLAGS)
endif endif
@@ -103,19 +103,6 @@ install:
install -C ./lotus-storage-miner /usr/local/bin/lotus-storage-miner install -C ./lotus-storage-miner /usr/local/bin/lotus-storage-miner
install -C ./lotus-seal-worker /usr/local/bin/lotus-seal-worker install -C ./lotus-seal-worker /usr/local/bin/lotus-seal-worker
install-services: install
mkdir -p /usr/local/lib/systemd/system
install -C -m 0644 ./scripts/lotus-daemon.service /usr/local/lib/systemd/system/lotus-daemon.service
install -C -m 0644 ./scripts/lotus-miner.service /usr/local/lib/systemd/system/lotus-miner.service
systemctl daemon-reload
@echo
@echo "lotus and lotus-miner services installed. Don't forget to 'systemctl enable lotus|lotus-miner' for it to be enabled on startup."
clean-services:
rm -f /usr/local/lib/systemd/system/lotus-daemon.service
rm -f /usr/local/lib/systemd/system/lotus-miner.service
systemctl daemon-reload
# TOOLS # TOOLS
lotus-seed: $(BUILD_DEPS) lotus-seed: $(BUILD_DEPS)
@@ -132,7 +119,7 @@ benchmarks:
@curl -X POST 'http://benchmark.kittyhawk.wtf/benchmark' -d '@bench.json' -u "${benchmark_http_cred}" @curl -X POST 'http://benchmark.kittyhawk.wtf/benchmark' -d '@bench.json' -u "${benchmark_http_cred}"
.PHONY: benchmarks .PHONY: benchmarks
pond: 2k pond: build
go build -o pond ./lotuspond go build -o pond ./lotuspond
(cd lotuspond/front && npm i && CI=false npm run build) (cd lotuspond/front && npm i && CI=false npm run build)
.PHONY: pond .PHONY: pond
+5 -10
View File
@@ -4,18 +4,17 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/filecoin-project/lotus/build"
"github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/build"
) )
type Permission = string
type Common interface { type Common interface {
// Auth // Auth
AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) AuthVerify(ctx context.Context, token string) ([]Permission, error)
AuthNew(ctx context.Context, perms []auth.Permission) ([]byte, error) AuthNew(ctx context.Context, perms []Permission) ([]byte, error)
// network // network
@@ -25,7 +24,6 @@ type Common interface {
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) NetFindPeer(context.Context, peer.ID) (peer.AddrInfo, error)
NetPubsubScores(context.Context) ([]PubsubScore, 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)
@@ -35,9 +33,6 @@ type Common interface {
LogList(context.Context) ([]string, error) LogList(context.Context) ([]string, error)
LogSetLevel(context.Context, string, string) error LogSetLevel(context.Context, string, string) error
// trigger graceful shutdown
Shutdown(context.Context) error
} }
// Version provides various build-time information // Version provides various build-time information
+10 -48
View File
@@ -28,18 +28,13 @@ type FullNode interface {
// TODO: TipSetKeys // TODO: TipSetKeys
// MethodGroup: Chain // chain
// The Chain method group contains methods for interacting with the
// blockchain, but that do not require any form of state computation
// ChainNotify returns channel with chain head updates // ChainNotify returns channel with chain head updates
// First message is guaranteed to be of len == 1, and type == 'current' // First message is guaranteed to be of len == 1, and type == 'current'
ChainNotify(context.Context) (<-chan []*HeadChange, error) ChainNotify(context.Context) (<-chan []*HeadChange, error)
// ChainHead returns the current head of the chain
ChainHead(context.Context) (*types.TipSet, error) ChainHead(context.Context) (*types.TipSet, error)
// ChainGetRandomness is used to sample the chain for randomness
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)
// ChainGetBlock returns the block specified by the given CID
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error) ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error)
ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error) ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error) ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
@@ -57,23 +52,14 @@ type FullNode interface {
ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*HeadChange, error) ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*HeadChange, error)
ChainExport(context.Context, types.TipSetKey) (<-chan []byte, error) ChainExport(context.Context, types.TipSetKey) (<-chan []byte, error)
// MethodGroup: Sync // syncer
// The Sync method group contains methods for interacting with and
// observing the lotus sync service
// SyncState returns the current status of the lotus sync system
SyncState(context.Context) (*SyncState, error) SyncState(context.Context) (*SyncState, error)
// SyncSubmitBlock can be used to submit a newly created block to the
// network through this node
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) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error)
// MethodGroup: Mpool // messages
// The Mpool methods are for interacting with the message pool. The message pool
// manages all incoming and outgoing 'messages' going over the network.
MpoolPending(context.Context, types.TipSetKey) ([]*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
@@ -81,14 +67,16 @@ type FullNode interface {
MpoolSub(context.Context) (<-chan MpoolUpdate, error) MpoolSub(context.Context) (<-chan MpoolUpdate, error)
MpoolEstimateGasPrice(context.Context, uint64, address.Address, int64, types.TipSetKey) (types.BigInt, error) MpoolEstimateGasPrice(context.Context, uint64, address.Address, int64, types.TipSetKey) (types.BigInt, error)
// MethodGroup: Miner // FullNodeStruct
// miner
MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*MiningBaseInfo, error) MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*MiningBaseInfo, error)
MinerCreateBlock(context.Context, *BlockTemplate) (*types.BlockMsg, error) MinerCreateBlock(context.Context, *BlockTemplate) (*types.BlockMsg, error)
// // UX ? // // UX ?
// MethodGroup: Wallet // wallet
WalletNew(context.Context, crypto.SigType) (address.Address, error) WalletNew(context.Context, crypto.SigType) (address.Address, error)
WalletHas(context.Context, address.Address) (bool, error) WalletHas(context.Context, address.Address) (bool, error)
@@ -101,24 +89,17 @@ type FullNode interface {
WalletSetDefault(context.Context, address.Address) error WalletSetDefault(context.Context, address.Address) error
WalletExport(context.Context, address.Address) (*types.KeyInfo, error) WalletExport(context.Context, address.Address) (*types.KeyInfo, error)
WalletImport(context.Context, *types.KeyInfo) (address.Address, error) WalletImport(context.Context, *types.KeyInfo) (address.Address, error)
WalletDelete(context.Context, address.Address) error
// Other // Other
// MethodGroup: Client
// The Client methods all have to do with interacting with the storage and
// retrieval markets as a client
// ClientImport imports file under the specified path into filestore // ClientImport imports file under the specified path into filestore
ClientImport(ctx context.Context, ref FileRef) (cid.Cid, error) ClientImport(ctx context.Context, ref FileRef) (cid.Cid, error)
// ClientStartDeal proposes a deal with a miner
ClientStartDeal(ctx context.Context, params *StartDealParams) (*cid.Cid, error) ClientStartDeal(ctx context.Context, params *StartDealParams) (*cid.Cid, error)
// ClientGetDeal info returns the latest information about a given deal
ClientGetDealInfo(context.Context, cid.Cid) (*DealInfo, error) ClientGetDealInfo(context.Context, cid.Cid) (*DealInfo, error)
ClientListDeals(ctx context.Context) ([]DealInfo, error) ClientListDeals(ctx context.Context) ([]DealInfo, error)
ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error) ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error)
ClientFindData(ctx context.Context, root cid.Cid) ([]QueryOffer, error) ClientFindData(ctx context.Context, root cid.Cid) ([]QueryOffer, error)
ClientRetrieve(ctx context.Context, order RetrievalOrder, ref *FileRef) error ClientRetrieve(ctx context.Context, order RetrievalOrder, ref FileRef) error
ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error)
ClientCalcCommP(ctx context.Context, inpath string, miner address.Address) (*CommPRet, error) ClientCalcCommP(ctx context.Context, inpath string, miner address.Address) (*CommPRet, error)
ClientGenCar(ctx context.Context, ref FileRef, outpath string) error ClientGenCar(ctx context.Context, ref FileRef, outpath string) error
@@ -131,9 +112,6 @@ type FullNode interface {
//ClientListAsks() []Ask //ClientListAsks() []Ask
// MethodGroup: State
// The State methods are used to query, inspect, and interact with chain state
// if tipset is nil, we'll use heaviest // if tipset is nil, we'll use heaviest
StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error) StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error)
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error) StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error)
@@ -148,16 +126,12 @@ type FullNode interface {
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error)
StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error)
StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) (*miner.Deadlines, error) StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) (*miner.Deadlines, error)
StateMinerFaults(context.Context, address.Address, types.TipSetKey) (*abi.BitField, error) StateMinerFaults(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error)
// Returns all non-expired Faults that occur within lookback epochs of the given tipset
StateAllMinerFaults(ctx context.Context, lookback abi.ChainEpoch, ts types.TipSetKey) ([]*Fault, error)
StateMinerRecoveries(context.Context, address.Address, types.TipSetKey) (*abi.BitField, error)
StateMinerInitialPledgeCollateral(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (types.BigInt, error) StateMinerInitialPledgeCollateral(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (types.BigInt, error)
StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
StateSectorPreCommitInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) StateSectorPreCommitInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error)
StateSectorGetInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error)
StatePledgeCollateral(context.Context, types.TipSetKey) (types.BigInt, error) StatePledgeCollateral(context.Context, types.TipSetKey) (types.BigInt, error)
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error) StateWaitMsg(context.Context, cid.Cid) (*MsgLookup, error)
StateSearchMsg(context.Context, cid.Cid) (*MsgLookup, error) StateSearchMsg(context.Context, cid.Cid) (*MsgLookup, error)
StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error) StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error)
StateListActors(context.Context, types.TipSetKey) ([]address.Address, error) StateListActors(context.Context, types.TipSetKey) ([]address.Address, error)
@@ -172,10 +146,6 @@ type FullNode interface {
StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error) StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error)
StateCompute(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*ComputeStateOutput, error) StateCompute(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*ComputeStateOutput, error)
// MethodGroup: Msig
// The Msig methods are used to interact with multisig wallets on the
// filecoin network
MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
MsigCreate(context.Context, int64, []address.Address, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) MsigCreate(context.Context, int64, []address.Address, types.BigInt, address.Address, types.BigInt) (cid.Cid, error)
MsigPropose(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) MsigPropose(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
@@ -185,9 +155,6 @@ type FullNode interface {
MarketEnsureAvailable(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error) MarketEnsureAvailable(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error)
// MarketFreeBalance // MarketFreeBalance
// MethodGroup: Paych
// The Paych methods are for interacting with and managing payment channels
PaychGet(ctx context.Context, from, to address.Address, ensureFunds types.BigInt) (*ChannelInfo, error) PaychGet(ctx context.Context, from, to address.Address, ensureFunds types.BigInt) (*ChannelInfo, error)
PaychList(context.Context) ([]address.Address, error) PaychList(context.Context) ([]address.Address, error)
PaychStatus(context.Context, address.Address) (*PaychStatus, error) PaychStatus(context.Context, address.Address) (*PaychStatus, error)
@@ -457,8 +424,3 @@ const (
MsigApprove MsigProposeResponse = iota MsigApprove MsigProposeResponse = iota
MsigCancel MsigCancel
) )
type Fault struct {
Miner address.Address
Epoch abi.ChainEpoch
}
+2 -1
View File
@@ -8,10 +8,11 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/sector-storage/stores" "github.com/filecoin-project/sector-storage/stores"
"github.com/filecoin-project/sector-storage/storiface" "github.com/filecoin-project/sector-storage/storiface"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/lotus/chain/types"
) )
// StorageMiner is a low-level interface to the Filecoin network storage miner node // StorageMiner is a low-level interface to the Filecoin network storage miner node
+2 -11
View File
@@ -2,9 +2,6 @@ package api
import ( import (
"context" "context"
"io"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/sector-storage/sealtasks" "github.com/filecoin-project/sector-storage/sealtasks"
"github.com/filecoin-project/sector-storage/stores" "github.com/filecoin-project/sector-storage/stores"
@@ -15,7 +12,7 @@ import (
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
) )
type WorkerAPI interface { type WorkerApi interface {
Version(context.Context) (build.Version, error) Version(context.Context) (build.Version, error)
// TODO: Info() (name, ...) ? // TODO: Info() (name, ...) ?
@@ -24,13 +21,7 @@ type WorkerAPI interface {
Info(context.Context) (storiface.WorkerInfo, error) Info(context.Context) (storiface.WorkerInfo, error)
storage.Sealer storage.Sealer
Fetch(context.Context, abi.SectorID, stores.SectorFileType, bool) error
MoveStorage(ctx context.Context, sector abi.SectorID) error
UnsealPiece(context.Context, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) error
ReadPiece(context.Context, io.Writer, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) error
Fetch(context.Context, abi.SectorID, stores.SectorFileType, stores.PathType, stores.AcquireMode) error
Closing(context.Context) (<-chan struct{}, error) Closing(context.Context) (<-chan struct{}, error)
} }
+86 -13
View File
@@ -1,38 +1,111 @@
package apistruct package apistruct
import ( import (
"github.com/filecoin-project/go-jsonrpc/auth" "context"
"reflect"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
) )
type permKey int
var permCtxKey permKey
const ( const (
// When changing these, update docs/API.md too // When changing these, update docs/API.md too
PermRead auth.Permission = "read" // default PermRead api.Permission = "read" // default
PermWrite auth.Permission = "write" PermWrite api.Permission = "write"
PermSign auth.Permission = "sign" // Use wallet keys for signing PermSign api.Permission = "sign" // Use wallet keys for signing
PermAdmin auth.Permission = "admin" // Manage permissions PermAdmin api.Permission = "admin" // Manage permissions
) )
var AllPermissions = []auth.Permission{PermRead, PermWrite, PermSign, PermAdmin} var AllPermissions = []api.Permission{PermRead, PermWrite, PermSign, PermAdmin}
var DefaultPerms = []auth.Permission{PermRead} var defaultPerms = []api.Permission{PermRead}
func WithPerm(ctx context.Context, perms []api.Permission) context.Context {
return context.WithValue(ctx, permCtxKey, perms)
}
func PermissionedStorMinerAPI(a api.StorageMiner) api.StorageMiner { func PermissionedStorMinerAPI(a api.StorageMiner) api.StorageMiner {
var out StorageMinerStruct var out StorageMinerStruct
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal) permissionedAny(a, &out.Internal)
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.CommonStruct.Internal) permissionedAny(a, &out.CommonStruct.Internal)
return &out return &out
} }
func PermissionedFullAPI(a api.FullNode) api.FullNode { func PermissionedFullAPI(a api.FullNode) api.FullNode {
var out FullNodeStruct var out FullNodeStruct
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal) permissionedAny(a, &out.Internal)
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.CommonStruct.Internal) permissionedAny(a, &out.CommonStruct.Internal)
return &out return &out
} }
func PermissionedWorkerAPI(a api.WorkerAPI) api.WorkerAPI { func PermissionedWorkerAPI(a api.WorkerApi) api.WorkerApi {
var out WorkerStruct var out WorkerStruct
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal) permissionedAny(a, &out.Internal)
return &out return &out
} }
func HasPerm(ctx context.Context, perm api.Permission) bool {
callerPerms, ok := ctx.Value(permCtxKey).([]api.Permission)
if !ok {
callerPerms = defaultPerms
}
for _, callerPerm := range callerPerms {
if callerPerm == perm {
return true
}
}
return false
}
func permissionedAny(in interface{}, out interface{}) {
rint := reflect.ValueOf(out).Elem()
ra := reflect.ValueOf(in)
for f := 0; f < rint.NumField(); f++ {
field := rint.Type().Field(f)
requiredPerm := api.Permission(field.Tag.Get("perm"))
if requiredPerm == "" {
panic("missing 'perm' tag on " + field.Name) // ok
}
// Validate perm tag
ok := false
for _, perm := range AllPermissions {
if requiredPerm == perm {
ok = true
break
}
}
if !ok {
panic("unknown 'perm' tag on " + field.Name) // ok
}
fn := ra.MethodByName(field.Name)
rint.Field(f).Set(reflect.MakeFunc(field.Type, func(args []reflect.Value) (results []reflect.Value) {
ctx := args[0].Interface().(context.Context)
if HasPerm(ctx, requiredPerm) {
return fn.Call(args)
}
err := xerrors.Errorf("missing permission to invoke '%s' (need '%s')", field.Name, requiredPerm)
rerr := reflect.ValueOf(&err).Elem()
if field.Type.NumOut() == 2 {
return []reflect.Value{
reflect.Zero(field.Type.Out(0)),
rerr,
}
} else {
return []reflect.Value{rerr}
}
}))
}
}
+30 -84
View File
@@ -2,7 +2,6 @@ package apistruct
import ( import (
"context" "context"
"io"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/network"
@@ -10,8 +9,6 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/sector-storage/sealtasks" "github.com/filecoin-project/sector-storage/sealtasks"
"github.com/filecoin-project/sector-storage/stores" "github.com/filecoin-project/sector-storage/stores"
"github.com/filecoin-project/sector-storage/storiface" "github.com/filecoin-project/sector-storage/storiface"
@@ -33,8 +30,8 @@ var _ = AllPermissions
type CommonStruct struct { type CommonStruct struct {
Internal struct { Internal struct {
AuthVerify func(ctx context.Context, token string) ([]auth.Permission, error) `perm:"read"` AuthVerify func(ctx context.Context, token string) ([]api.Permission, error) `perm:"read"`
AuthNew func(ctx context.Context, perms []auth.Permission) ([]byte, error) `perm:"admin"` AuthNew func(ctx context.Context, perms []api.Permission) ([]byte, error) `perm:"admin"`
NetConnectedness func(context.Context, peer.ID) (network.Connectedness, error) `perm:"read"` NetConnectedness func(context.Context, peer.ID) (network.Connectedness, error) `perm:"read"`
NetPeers func(context.Context) ([]peer.AddrInfo, error) `perm:"read"` NetPeers func(context.Context) ([]peer.AddrInfo, error) `perm:"read"`
@@ -42,15 +39,12 @@ type CommonStruct struct {
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"` NetFindPeer func(context.Context, peer.ID) (peer.AddrInfo, error) `perm:"read"`
NetPubsubScores func(context.Context) ([]api.PubsubScore, 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"` LogList func(context.Context) ([]string, error) `perm:"write"`
LogSetLevel func(context.Context, string, string) error `perm:"write"` LogSetLevel func(context.Context, string, string) error `perm:"write"`
Shutdown func(context.Context) error `perm:"admin"`
} }
} }
@@ -106,7 +100,6 @@ type FullNodeStruct struct {
WalletSetDefault func(context.Context, address.Address) error `perm:"admin"` WalletSetDefault func(context.Context, address.Address) error `perm:"admin"`
WalletExport func(context.Context, address.Address) (*types.KeyInfo, error) `perm:"admin"` WalletExport func(context.Context, address.Address) (*types.KeyInfo, error) `perm:"admin"`
WalletImport func(context.Context, *types.KeyInfo) (address.Address, error) `perm:"admin"` WalletImport func(context.Context, *types.KeyInfo) (address.Address, error) `perm:"admin"`
WalletDelete func(context.Context, address.Address) error `perm:"write"`
ClientImport func(ctx context.Context, ref api.FileRef) (cid.Cid, error) `perm:"admin"` ClientImport func(ctx context.Context, ref api.FileRef) (cid.Cid, error) `perm:"admin"`
ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"` ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"`
@@ -115,7 +108,7 @@ type FullNodeStruct struct {
ClientStartDeal func(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) `perm:"admin"` ClientStartDeal func(ctx context.Context, params *api.StartDealParams) (*cid.Cid, error) `perm:"admin"`
ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"` ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"`
ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"` ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"`
ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error `perm:"admin"` ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref api.FileRef) error `perm:"admin"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) `perm:"read"` ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) `perm:"read"`
ClientCalcCommP func(ctx context.Context, inpath string, miner address.Address) (*api.CommPRet, error) `perm:"read"` ClientCalcCommP func(ctx context.Context, inpath string, miner address.Address) (*api.CommPRet, error) `perm:"read"`
ClientGenCar func(ctx context.Context, ref api.FileRef, outpath string) error `perm:"write"` ClientGenCar func(ctx context.Context, ref api.FileRef, outpath string) error `perm:"write"`
@@ -127,19 +120,16 @@ type FullNodeStruct struct {
StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) `perm:"read"` StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) `perm:"read"`
StateMinerInfo func(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) `perm:"read"` StateMinerInfo func(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) `perm:"read"`
StateMinerDeadlines func(context.Context, address.Address, types.TipSetKey) (*miner.Deadlines, error) `perm:"read"` StateMinerDeadlines func(context.Context, address.Address, types.TipSetKey) (*miner.Deadlines, error) `perm:"read"`
StateMinerFaults func(context.Context, address.Address, types.TipSetKey) (*abi.BitField, error) `perm:"read"` StateMinerFaults func(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error) `perm:"read"`
StateAllMinerFaults func(context.Context, abi.ChainEpoch, types.TipSetKey) ([]*api.Fault, error) `perm:"read"`
StateMinerRecoveries func(context.Context, address.Address, types.TipSetKey) (*abi.BitField, error) `perm:"read"`
StateMinerInitialPledgeCollateral func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (types.BigInt, error) `perm:"read"` StateMinerInitialPledgeCollateral func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (types.BigInt, error) `perm:"read"`
StateMinerAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"` StateMinerAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
StateSectorPreCommitInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"` StateSectorPreCommitInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"`
StateSectorGetInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"`
StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) `perm:"read"` StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) `perm:"read"`
StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"` StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"`
StateGetActor func(context.Context, address.Address, types.TipSetKey) (*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.TipSetKey) (*api.ActorState, error) `perm:"read"` StateReadState func(context.Context, *types.Actor, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
StatePledgeCollateral func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"` StatePledgeCollateral func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"`
StateWaitMsg func(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) `perm:"read"` StateWaitMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"`
StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"` StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"`
StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"` StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"` StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
@@ -207,17 +197,16 @@ type StorageMinerStruct struct {
WorkerConnect func(context.Context, string) error `perm:"admin"` // TODO: worker perm WorkerConnect func(context.Context, string) error `perm:"admin"` // TODO: worker perm
WorkerStats func(context.Context) (map[uint64]storiface.WorkerStats, error) `perm:"admin"` WorkerStats func(context.Context) (map[uint64]storiface.WorkerStats, error) `perm:"admin"`
StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"` StorageList func(context.Context) (map[stores.ID][]stores.Decl, error) `perm:"admin"`
StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"` StorageLocal func(context.Context) (map[stores.ID]string, error) `perm:"admin"`
StorageStat func(context.Context, stores.ID) (stores.FsStat, error) `perm:"admin"` StorageStat func(context.Context, stores.ID) (stores.FsStat, error) `perm:"admin"`
StorageAttach func(context.Context, stores.StorageInfo, stores.FsStat) error `perm:"admin"` StorageAttach func(context.Context, stores.StorageInfo, stores.FsStat) error `perm:"admin"`
StorageDeclareSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType, bool) error `perm:"admin"` StorageDeclareSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType) error `perm:"admin"`
StorageDropSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType) error `perm:"admin"` StorageDropSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType) error `perm:"admin"`
StorageFindSector func(context.Context, abi.SectorID, stores.SectorFileType, bool) ([]stores.SectorStorageInfo, error) `perm:"admin"` StorageFindSector func(context.Context, abi.SectorID, stores.SectorFileType, bool) ([]stores.StorageInfo, error) `perm:"admin"`
StorageInfo func(context.Context, stores.ID) (stores.StorageInfo, error) `perm:"admin"` StorageInfo func(context.Context, stores.ID) (stores.StorageInfo, error) `perm:"admin"`
StorageBestAlloc func(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredProof, sealing stores.PathType) ([]stores.StorageInfo, error) `perm:"admin"` StorageBestAlloc func(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredProof, sealing bool) ([]stores.StorageInfo, error) `perm:"admin"`
StorageReportHealth func(ctx context.Context, id stores.ID, report stores.HealthReport) error `perm:"admin"` StorageReportHealth func(ctx context.Context, id stores.ID, report stores.HealthReport) error `perm:"admin"`
StorageLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) error `perm:"admin"`
DealsImportData func(ctx context.Context, dealPropCid cid.Cid, file string) error `perm:"write"` DealsImportData func(ctx context.Context, dealPropCid cid.Cid, file string) error `perm:"write"`
DealsList func(ctx context.Context) ([]storagemarket.StorageDeal, error) `perm:"read"` DealsList func(ctx context.Context) ([]storagemarket.StorageDeal, error) `perm:"read"`
@@ -241,12 +230,8 @@ type WorkerStruct struct {
SealCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storage.Commit1Out, error) `perm:"admin"` SealCommit1 func(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storage.Commit1Out, error) `perm:"admin"`
SealCommit2 func(context.Context, abi.SectorID, storage.Commit1Out) (storage.Proof, error) `perm:"admin"` SealCommit2 func(context.Context, abi.SectorID, storage.Commit1Out) (storage.Proof, error) `perm:"admin"`
FinalizeSector func(context.Context, abi.SectorID) error `perm:"admin"` FinalizeSector func(context.Context, abi.SectorID) error `perm:"admin"`
MoveStorage func(ctx context.Context, sector abi.SectorID) error `perm:"admin"`
UnsealPiece func(context.Context, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) error `perm:"admin"` Fetch func(context.Context, abi.SectorID, stores.SectorFileType, bool) error `perm:"admin"`
ReadPiece func(context.Context, io.Writer, abi.SectorID, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize) error `perm:"admin"`
Fetch func(context.Context, abi.SectorID, stores.SectorFileType, stores.PathType, stores.AcquireMode) error `perm:"admin"`
Closing func(context.Context) (<-chan struct{}, error) `perm:"admin"` Closing func(context.Context) (<-chan struct{}, error) `perm:"admin"`
} }
@@ -254,17 +239,14 @@ type WorkerStruct struct {
// CommonStruct // CommonStruct
func (c *CommonStruct) AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) { func (c *CommonStruct) AuthVerify(ctx context.Context, token string) ([]api.Permission, error) {
return c.Internal.AuthVerify(ctx, token) return c.Internal.AuthVerify(ctx, token)
} }
func (c *CommonStruct) AuthNew(ctx context.Context, perms []auth.Permission) ([]byte, error) { func (c *CommonStruct) AuthNew(ctx context.Context, perms []api.Permission) ([]byte, error) {
return c.Internal.AuthNew(ctx, perms) return c.Internal.AuthNew(ctx, perms)
} }
func (c *CommonStruct) NetPubsubScores(ctx context.Context) ([]api.PubsubScore, error) {
return c.Internal.NetPubsubScores(ctx)
}
func (c *CommonStruct) NetConnectedness(ctx context.Context, pid peer.ID) (network.Connectedness, error) { func (c *CommonStruct) NetConnectedness(ctx context.Context, pid peer.ID) (network.Connectedness, error) {
return c.Internal.NetConnectedness(ctx, pid) return c.Internal.NetConnectedness(ctx, pid)
} }
@@ -307,10 +289,6 @@ func (c *CommonStruct) LogSetLevel(ctx context.Context, group, level string) err
return c.Internal.LogSetLevel(ctx, group, level) return c.Internal.LogSetLevel(ctx, group, level)
} }
func (c *CommonStruct) Shutdown(ctx context.Context) error {
return c.Internal.Shutdown(ctx)
}
// FullNodeStruct // FullNodeStruct
func (c *FullNodeStruct) ClientListImports(ctx context.Context) ([]api.Import, error) { func (c *FullNodeStruct) ClientListImports(ctx context.Context) ([]api.Import, error) {
@@ -340,7 +318,7 @@ func (c *FullNodeStruct) ClientListDeals(ctx context.Context) ([]api.DealInfo, e
return c.Internal.ClientListDeals(ctx) return c.Internal.ClientListDeals(ctx)
} }
func (c *FullNodeStruct) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error { func (c *FullNodeStruct) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref api.FileRef) error {
return c.Internal.ClientRetrieve(ctx, order, ref) return c.Internal.ClientRetrieve(ctx, order, ref)
} }
@@ -439,10 +417,6 @@ func (c *FullNodeStruct) WalletImport(ctx context.Context, ki *types.KeyInfo) (a
return c.Internal.WalletImport(ctx, ki) return c.Internal.WalletImport(ctx, ki)
} }
func (c *FullNodeStruct) WalletDelete(ctx context.Context, addr address.Address) error {
return c.Internal.WalletDelete(ctx, addr)
}
func (c *FullNodeStruct) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) { func (c *FullNodeStruct) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) {
return c.Internal.MpoolGetNonce(ctx, addr) return c.Internal.MpoolGetNonce(ctx, addr)
} }
@@ -559,18 +533,10 @@ func (c *FullNodeStruct) StateMinerDeadlines(ctx context.Context, m address.Addr
return c.Internal.StateMinerDeadlines(ctx, m, tsk) return c.Internal.StateMinerDeadlines(ctx, m, tsk)
} }
func (c *FullNodeStruct) StateMinerFaults(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*abi.BitField, error) { func (c *FullNodeStruct) StateMinerFaults(ctx context.Context, actor address.Address, tsk types.TipSetKey) ([]abi.SectorNumber, error) {
return c.Internal.StateMinerFaults(ctx, actor, tsk) return c.Internal.StateMinerFaults(ctx, actor, tsk)
} }
func (c *FullNodeStruct) StateAllMinerFaults(ctx context.Context, cutoff abi.ChainEpoch, endTsk types.TipSetKey) ([]*api.Fault, error) {
return c.Internal.StateAllMinerFaults(ctx, cutoff, endTsk)
}
func (c *FullNodeStruct) StateMinerRecoveries(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*abi.BitField, error) {
return c.Internal.StateMinerRecoveries(ctx, actor, tsk)
}
func (c *FullNodeStruct) StateMinerInitialPledgeCollateral(ctx context.Context, maddr address.Address, snum abi.SectorNumber, tsk types.TipSetKey) (types.BigInt, error) { func (c *FullNodeStruct) StateMinerInitialPledgeCollateral(ctx context.Context, maddr address.Address, snum abi.SectorNumber, tsk types.TipSetKey) (types.BigInt, error) {
return c.Internal.StateMinerInitialPledgeCollateral(ctx, maddr, snum, tsk) return c.Internal.StateMinerInitialPledgeCollateral(ctx, maddr, snum, tsk)
} }
@@ -583,10 +549,6 @@ func (c *FullNodeStruct) StateSectorPreCommitInfo(ctx context.Context, maddr add
return c.Internal.StateSectorPreCommitInfo(ctx, maddr, n, tsk) return c.Internal.StateSectorPreCommitInfo(ctx, maddr, n, tsk)
} }
func (c *FullNodeStruct) StateSectorGetInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorOnChainInfo, error) {
return c.Internal.StateSectorGetInfo(ctx, maddr, n, tsk)
}
func (c *FullNodeStruct) StateCall(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (*api.InvocResult, error) { func (c *FullNodeStruct) StateCall(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (*api.InvocResult, error) {
return c.Internal.StateCall(ctx, msg, tsk) return c.Internal.StateCall(ctx, msg, tsk)
} }
@@ -607,8 +569,8 @@ func (c *FullNodeStruct) StatePledgeCollateral(ctx context.Context, tsk types.Ti
return c.Internal.StatePledgeCollateral(ctx, tsk) return c.Internal.StatePledgeCollateral(ctx, tsk)
} }
func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid, confidence uint64) (*api.MsgLookup, error) { func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid) (*api.MsgLookup, error) {
return c.Internal.StateWaitMsg(ctx, msgc, confidence) return c.Internal.StateWaitMsg(ctx, msgc)
} }
func (c *FullNodeStruct) StateSearchMsg(ctx context.Context, msgc cid.Cid) (*api.MsgLookup, error) { func (c *FullNodeStruct) StateSearchMsg(ctx context.Context, msgc cid.Cid) (*api.MsgLookup, error) {
@@ -783,15 +745,15 @@ func (c *StorageMinerStruct) StorageAttach(ctx context.Context, si stores.Storag
return c.Internal.StorageAttach(ctx, si, st) return c.Internal.StorageAttach(ctx, si, st)
} }
func (c *StorageMinerStruct) StorageDeclareSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft stores.SectorFileType, primary bool) error { func (c *StorageMinerStruct) StorageDeclareSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft stores.SectorFileType) error {
return c.Internal.StorageDeclareSector(ctx, storageId, s, ft, primary) return c.Internal.StorageDeclareSector(ctx, storageId, s, ft)
} }
func (c *StorageMinerStruct) StorageDropSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft stores.SectorFileType) error { func (c *StorageMinerStruct) StorageDropSector(ctx context.Context, storageId stores.ID, s abi.SectorID, ft stores.SectorFileType) error {
return c.Internal.StorageDropSector(ctx, storageId, s, ft) return c.Internal.StorageDropSector(ctx, storageId, s, ft)
} }
func (c *StorageMinerStruct) StorageFindSector(ctx context.Context, si abi.SectorID, types stores.SectorFileType, allowFetch bool) ([]stores.SectorStorageInfo, error) { func (c *StorageMinerStruct) StorageFindSector(ctx context.Context, si abi.SectorID, types stores.SectorFileType, allowFetch bool) ([]stores.StorageInfo, error) {
return c.Internal.StorageFindSector(ctx, si, types, allowFetch) return c.Internal.StorageFindSector(ctx, si, types, allowFetch)
} }
@@ -811,18 +773,14 @@ func (c *StorageMinerStruct) StorageInfo(ctx context.Context, id stores.ID) (sto
return c.Internal.StorageInfo(ctx, id) return c.Internal.StorageInfo(ctx, id)
} }
func (c *StorageMinerStruct) StorageBestAlloc(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredProof, pt stores.PathType) ([]stores.StorageInfo, error) { func (c *StorageMinerStruct) StorageBestAlloc(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredProof, sealing bool) ([]stores.StorageInfo, error) {
return c.Internal.StorageBestAlloc(ctx, allocate, spt, pt) return c.Internal.StorageBestAlloc(ctx, allocate, spt, sealing)
} }
func (c *StorageMinerStruct) StorageReportHealth(ctx context.Context, id stores.ID, report stores.HealthReport) error { func (c *StorageMinerStruct) StorageReportHealth(ctx context.Context, id stores.ID, report stores.HealthReport) error {
return c.Internal.StorageReportHealth(ctx, id, report) return c.Internal.StorageReportHealth(ctx, id, report)
} }
func (c *StorageMinerStruct) StorageLock(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) error {
return c.Internal.StorageLock(ctx, sector, read, write)
}
func (c *StorageMinerStruct) MarketImportDealData(ctx context.Context, propcid cid.Cid, path string) error { func (c *StorageMinerStruct) MarketImportDealData(ctx context.Context, propcid cid.Cid, path string) error {
return c.Internal.MarketImportDealData(ctx, propcid, path) return c.Internal.MarketImportDealData(ctx, propcid, path)
} }
@@ -889,20 +847,8 @@ func (w *WorkerStruct) FinalizeSector(ctx context.Context, sector abi.SectorID)
return w.Internal.FinalizeSector(ctx, sector) return w.Internal.FinalizeSector(ctx, sector)
} }
func (w *WorkerStruct) MoveStorage(ctx context.Context, sector abi.SectorID) error { func (w *WorkerStruct) Fetch(ctx context.Context, id abi.SectorID, fileType stores.SectorFileType, b bool) error {
return w.Internal.MoveStorage(ctx, sector) return w.Internal.Fetch(ctx, id, fileType, b)
}
func (w *WorkerStruct) UnsealPiece(ctx context.Context, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, c cid.Cid) error {
return w.Internal.UnsealPiece(ctx, id, index, size, randomness, c)
}
func (w *WorkerStruct) ReadPiece(ctx context.Context, writer io.Writer, id abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) error {
return w.Internal.ReadPiece(ctx, writer, id, index, size)
}
func (w *WorkerStruct) Fetch(ctx context.Context, id abi.SectorID, fileType stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) error {
return w.Internal.Fetch(ctx, id, fileType, ptype, am)
} }
func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) { func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
@@ -912,4 +858,4 @@ func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
var _ api.Common = &CommonStruct{} var _ api.Common = &CommonStruct{}
var _ api.FullNode = &FullNodeStruct{} var _ api.FullNode = &FullNodeStruct{}
var _ api.StorageMiner = &StorageMinerStruct{} var _ api.StorageMiner = &StorageMinerStruct{}
var _ api.WorkerAPI = &WorkerStruct{} var _ api.WorkerApi = &WorkerStruct{}
+3 -4
View File
@@ -1,12 +1,11 @@
package client package client
import ( import (
"github.com/filecoin-project/lotus/api/apistruct"
"net/http" "net/http"
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apistruct" "github.com/filecoin-project/lotus/lib/jsonrpc"
) )
// NewCommonRPC creates a new http jsonrpc client. // NewCommonRPC creates a new http jsonrpc client.
@@ -48,7 +47,7 @@ func NewStorageMinerRPC(addr string, requestHeader http.Header) (api.StorageMine
return &res, closer, err return &res, closer, err
} }
func NewWorkerRPC(addr string, requestHeader http.Header) (api.WorkerAPI, jsonrpc.ClientCloser, error) { func NewWorkerRPC(addr string, requestHeader http.Header) (api.WorkerApi, jsonrpc.ClientCloser, error) {
var res apistruct.WorkerStruct var res apistruct.WorkerStruct
closer, err := jsonrpc.NewMergeClient(addr, "Filecoin", closer, err := jsonrpc.NewMergeClient(addr, "Filecoin",
[]interface{}{ []interface{}{
-338
View File
@@ -1,338 +0,0 @@
package main
import (
"encoding/json"
"fmt"
"go/ast"
"go/parser"
"go/token"
"reflect"
"sort"
"strings"
"time"
"unicode"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-filestore"
"github.com/libp2p/go-libp2p-core/network"
peer "github.com/libp2p/go-libp2p-peer"
"github.com/multiformats/go-multiaddr"
)
var ExampleValues = map[reflect.Type]interface{}{
reflect.TypeOf(auth.Permission("")): auth.Permission("write"),
reflect.TypeOf(""): "string value",
reflect.TypeOf(uint64(42)): uint64(42),
reflect.TypeOf(byte(7)): byte(7),
reflect.TypeOf([]byte{}): []byte("byte array"),
}
func addExample(v interface{}) {
ExampleValues[reflect.TypeOf(v)] = v
}
func init() {
c, err := cid.Decode("bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4")
if err != nil {
panic(err)
}
ExampleValues[reflect.TypeOf(c)] = c
c2, err := cid.Decode("bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve")
if err != nil {
panic(err)
}
tsk := types.NewTipSetKey(c, c2)
ExampleValues[reflect.TypeOf(tsk)] = tsk
addr, err := address.NewIDAddress(1234)
if err != nil {
panic(err)
}
ExampleValues[reflect.TypeOf(addr)] = addr
pid, err := peer.IDB58Decode("12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf")
if err != nil {
panic(err)
}
addExample(pid)
addExample(bitfield.NewFromSet([]uint64{5}))
addExample(abi.RegisteredProof_StackedDRG32GiBPoSt)
addExample(abi.ChainEpoch(10101))
addExample(crypto.SigTypeBLS)
addExample(int64(9))
addExample(abi.MethodNum(1))
addExample(exitcode.ExitCode(0))
addExample(crypto.DomainSeparationTag_ElectionProofProduction)
addExample(true)
addExample(abi.UnpaddedPieceSize(1024))
addExample(abi.UnpaddedPieceSize(1024).Padded())
addExample(abi.DealID(5432))
addExample(filestore.StatusFileChanged)
addExample(abi.SectorNumber(9))
addExample(abi.SectorSize(32 * 1024 * 1024 * 1024))
addExample(api.MpoolChange(0))
addExample(network.Connected)
addExample(dtypes.NetworkName("lotus"))
addExample(api.SyncStateStage(1))
addExample(build.APIVersion)
addExample(api.PCHInbound)
addExample(time.Minute)
addExample(&types.ExecutionResult{
Msg: exampleValue(reflect.TypeOf(&types.Message{})).(*types.Message),
MsgRct: exampleValue(reflect.TypeOf(&types.MessageReceipt{})).(*types.MessageReceipt),
})
addExample(map[string]types.Actor{
"t01236": exampleValue(reflect.TypeOf(types.Actor{})).(types.Actor),
})
addExample(map[string]api.MarketDeal{
"t026363": exampleValue(reflect.TypeOf(api.MarketDeal{})).(api.MarketDeal),
})
addExample(map[string]api.MarketBalance{
"t026363": exampleValue(reflect.TypeOf(api.MarketBalance{})).(api.MarketBalance),
})
maddr, err := multiaddr.NewMultiaddr("/ip4/52.36.61.156/tcp/1347/p2p/12D3KooWFETiESTf1v4PGUvtnxMAcEFMzLZbJGg4tjWfGEimYior")
if err != nil {
panic(err)
}
// because reflect.TypeOf(maddr) returns the concrete type...
ExampleValues[reflect.TypeOf(struct{ A multiaddr.Multiaddr }{}).Field(0).Type] = maddr
}
func exampleValue(t reflect.Type) interface{} {
v, ok := ExampleValues[t]
if ok {
return v
}
switch t.Kind() {
case reflect.Slice:
out := reflect.New(t).Elem()
reflect.Append(out, reflect.ValueOf(exampleValue(t.Elem())))
return out.Interface()
case reflect.Chan:
return exampleValue(t.Elem())
case reflect.Struct:
es := exampleStruct(t)
v := reflect.ValueOf(es).Elem().Interface()
ExampleValues[t] = v
return v
case reflect.Array:
out := reflect.New(t).Elem()
for i := 0; i < t.Len(); i++ {
out.Index(i).Set(reflect.ValueOf(exampleValue(t.Elem())))
}
return out.Interface()
case reflect.Ptr:
if t.Elem().Kind() == reflect.Struct {
es := exampleStruct(t.Elem())
//ExampleValues[t] = es
return es
}
case reflect.Interface:
return struct{}{}
}
panic(fmt.Sprintf("No example value for type: %s", t))
}
func exampleStruct(t reflect.Type) interface{} {
ns := reflect.New(t)
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if strings.Title(f.Name) == f.Name {
ns.Elem().Field(i).Set(reflect.ValueOf(exampleValue(f.Type)))
}
}
return ns.Interface()
}
type Visitor struct {
Methods map[string]ast.Node
}
func (v *Visitor) Visit(node ast.Node) ast.Visitor {
st, ok := node.(*ast.TypeSpec)
if !ok {
return v
}
if st.Name.Name != "FullNode" {
return nil
}
iface := st.Type.(*ast.InterfaceType)
for _, m := range iface.Methods.List {
if len(m.Names) > 0 {
v.Methods[m.Names[0].Name] = m
}
}
return v
}
const noComment = "There are not yet any comments for this method."
func parseApiASTInfo() (map[string]string, map[string]string) { //nolint:golint
fset := token.NewFileSet()
pkgs, err := parser.ParseDir(fset, "./api", nil, parser.AllErrors|parser.ParseComments)
if err != nil {
fmt.Println("parse error: ", err)
}
ap := pkgs["api"]
f := ap.Files["api/api_full.go"]
cmap := ast.NewCommentMap(fset, f, f.Comments)
v := &Visitor{make(map[string]ast.Node)}
ast.Walk(v, pkgs["api"])
groupDocs := make(map[string]string)
out := make(map[string]string)
for mn, node := range v.Methods {
cs := cmap.Filter(node).Comments()
if len(cs) == 0 {
out[mn] = noComment
} else {
for _, c := range cs {
if strings.HasPrefix(c.Text(), "MethodGroup:") {
parts := strings.Split(c.Text(), "\n")
groupName := strings.TrimSpace(parts[0][12:])
comment := strings.Join(parts[1:], "\n")
groupDocs[groupName] = comment
break
}
}
last := cs[len(cs)-1].Text()
if !strings.HasPrefix(last, "MethodGroup:") {
out[mn] = last
} else {
out[mn] = noComment
}
}
}
return out, groupDocs
}
type MethodGroup struct {
GroupName string
Header string
Methods []*Method
}
type Method struct {
Comment string
Name string
InputExample string
ResponseExample string
}
func methodGroupFromName(mn string) string {
i := strings.IndexFunc(mn[1:], func(r rune) bool {
return unicode.IsUpper(r)
})
if i < 0 {
return ""
}
return mn[:i+1]
}
func main() {
comments, groupComments := parseApiASTInfo()
groups := make(map[string]*MethodGroup)
var api struct{ api.FullNode }
t := reflect.TypeOf(api)
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
groupName := methodGroupFromName(m.Name)
g, ok := groups[groupName]
if !ok {
g = new(MethodGroup)
g.Header = groupComments[groupName]
g.GroupName = groupName
groups[groupName] = g
}
var args []interface{}
ft := m.Func.Type()
for j := 2; j < ft.NumIn(); j++ {
inp := ft.In(j)
args = append(args, exampleValue(inp))
}
v, err := json.Marshal(args)
if err != nil {
panic(err)
}
outv := exampleValue(ft.Out(0))
ov, err := json.Marshal(outv)
if err != nil {
panic(err)
}
g.Methods = append(g.Methods, &Method{
Name: m.Name,
Comment: comments[m.Name],
InputExample: string(v),
ResponseExample: string(ov),
})
}
var groupslice []*MethodGroup
for _, g := range groups {
groupslice = append(groupslice, g)
}
sort.Slice(groupslice, func(i, j int) bool {
return groupslice[i].GroupName < groupslice[j].GroupName
})
for _, g := range groupslice {
g := g
fmt.Printf("## %s\n", g.GroupName)
fmt.Printf("%s\n\n", g.Header)
sort.Slice(g.Methods, func(i, j int) bool {
return g.Methods[i].Name < g.Methods[j].Name
})
for _, m := range g.Methods {
fmt.Printf("### %s\n", m.Name)
fmt.Printf("%s\n\n", m.Comment)
fmt.Printf("Inputs: `%s`\n\n", m.InputExample)
fmt.Printf("Response: `%s`\n\n", m.ResponseExample)
}
}
}
+4 -4
View File
@@ -35,7 +35,7 @@ func init() {
} }
func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport bool) { func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport bool) {
_ = os.Setenv("BELLMAN_NO_GPU", "1") os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background() ctx := context.Background()
n, sn := b(t, 1, oneMiner) n, sn := b(t, 1, oneMiner)
@@ -72,7 +72,7 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport
} }
func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) { func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
_ = os.Setenv("BELLMAN_NO_GPU", "1") os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background() ctx := context.Background()
n, sn := b(t, 1, oneMiner) n, sn := b(t, 1, oneMiner)
@@ -193,14 +193,14 @@ func testRetrieval(t *testing.T, ctx context.Context, err error, client *impl.Fu
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer os.RemoveAll(rpath) //nolint:errcheck defer os.RemoveAll(rpath)
caddr, err := client.WalletDefaultAddress(ctx) caddr, err := client.WalletDefaultAddress(ctx)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
ref := &api.FileRef{ ref := api.FileRef{
Path: filepath.Join(rpath, "ret"), Path: filepath.Join(rpath, "ret"),
IsCAR: carExport, IsCAR: carExport,
} }
+1 -1
View File
@@ -82,7 +82,7 @@ func (ts *testSuite) testMiningReal(t *testing.T) {
} }
func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExport bool) { func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExport bool) {
_ = os.Setenv("BELLMAN_NO_GPU", "1") os.Setenv("BELLMAN_NO_GPU", "1")
// test making a deal with a fresh miner, and see if it starts to mine // test making a deal with a fresh miner, and see if it starts to mine
+4 -6
View File
@@ -4,11 +4,9 @@ import (
"context" "context"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/stretchr/testify/assert"
) )
type TestNode struct { type TestNode struct {
@@ -23,8 +21,6 @@ type TestStorageNode struct {
var PresealGenesis = -1 var PresealGenesis = -1
const GenesisPreseals = 2
type StorageMiner struct { type StorageMiner struct {
Full int Full int
Preseal int Preseal int
@@ -64,7 +60,9 @@ func (ts *testSuite) testVersion(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
require.Equal(t, v.Version, build.BuildVersion) if v.Version != build.BuildVersion {
t.Error("Version didn't work properly")
}
} }
func (ts *testSuite) testID(t *testing.T) { func (ts *testSuite) testID(t *testing.T) {
-169
View File
@@ -1,169 +0,0 @@
package test
import (
"context"
"fmt"
"github.com/filecoin-project/lotus/api"
"os"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/specs-actors/actors/abi"
miner2 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
sealing "github.com/filecoin-project/storage-fsm"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/impl"
)
func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, oneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
addrinfo, err := client.NetAddrsListen(ctx)
if err != nil {
t.Fatal(err)
}
if err := miner.NetConnect(ctx, addrinfo); err != nil {
t.Fatal(err)
}
time.Sleep(time.Second)
mine := true
done := make(chan struct{})
go func() {
defer close(done)
for mine {
time.Sleep(blocktime)
if err := sn[0].MineOne(ctx, func(bool) {}); err != nil {
t.Error(err)
}
}
}()
pledgeSectors(t, ctx, miner, nSectors)
mine = false
<-done
}
func pledgeSectors(t *testing.T, ctx context.Context, miner TestStorageNode, n int) {
for i := 0; i < n; i++ {
err := miner.PledgeSector(ctx)
require.NoError(t, err)
}
for {
s, err := miner.SectorsList(ctx) // Note - the test builder doesn't import genesis sectors into FSM
require.NoError(t, err)
fmt.Printf("Sectors: %d\n", len(s))
if len(s) >= n {
break
}
time.Sleep(100 * time.Millisecond)
}
fmt.Printf("All sectors is fsm\n")
s, err := miner.SectorsList(ctx)
require.NoError(t, err)
toCheck := map[abi.SectorNumber]struct{}{}
for _, number := range s {
toCheck[number] = struct{}{}
}
for len(toCheck) > 0 {
for n := range toCheck {
st, err := miner.SectorsStatus(ctx, n)
require.NoError(t, err)
if st.State == api.SectorState(sealing.Proving) {
delete(toCheck, n)
}
if strings.Contains(string(st.State), "Fail") {
t.Fatal("sector in a failed state", st.State)
}
}
time.Sleep(100 * time.Millisecond)
fmt.Printf("WaitSeal: %d\n", len(s))
}
}
func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, oneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
addrinfo, err := client.NetAddrsListen(ctx)
if err != nil {
t.Fatal(err)
}
if err := miner.NetConnect(ctx, addrinfo); err != nil {
t.Fatal(err)
}
time.Sleep(time.Second)
mine := true
done := make(chan struct{})
go func() {
defer close(done)
for mine {
time.Sleep(blocktime)
if err := sn[0].MineOne(ctx, func(bool) {}); err != nil {
t.Error(err)
}
}
}()
pledgeSectors(t, ctx, miner, nSectors)
maddr, err := miner.ActorAddress(ctx)
require.NoError(t, err)
di, err := client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
fmt.Printf("Running one proving periods\n")
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
if head.Height() > di.PeriodStart+(miner2.WPoStProvingPeriod)+2 {
break
}
if head.Height()%100 == 0 {
fmt.Printf("@%d\n", head.Height())
}
time.Sleep(blocktime)
}
p, err := client.StateMinerPower(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
ssz, err := miner.ActorSectorSize(ctx, maddr)
require.NoError(t, err)
require.Equal(t, p.MinerPower, p.TotalPower)
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)*uint64(nSectors+GenesisPreseals)))
// TODO: Inject faults here
mine = false
<-done
}
-7
View File
@@ -3,12 +3,10 @@ package api
import ( import (
"encoding/json" "encoding/json"
"github.com/libp2p/go-libp2p-core/peer"
ma "github.com/multiformats/go-multiaddr" ma "github.com/multiformats/go-multiaddr"
) )
// TODO: check if this exists anywhere else // TODO: check if this exists anywhere else
type MultiaddrSlice []ma.Multiaddr type MultiaddrSlice []ma.Multiaddr
func (m *MultiaddrSlice) UnmarshalJSON(raw []byte) (err error) { func (m *MultiaddrSlice) UnmarshalJSON(raw []byte) (err error) {
@@ -34,8 +32,3 @@ type ObjStat struct {
Size uint64 Size uint64
Links uint64 Links uint64
} }
type PubsubScore struct {
ID peer.ID
Score float64
}
-9
View File
@@ -34,12 +34,3 @@ func BuiltinBootstrap() ([]peer.AddrInfo, error) {
}) })
return out, err return out, err
} }
func DrandBootstrap() ([]peer.AddrInfo, error) {
addrs := []string{
"/dnsaddr/pl-eu.testnet.drand.sh/",
"/dnsaddr/pl-us.testnet.drand.sh/",
"/dnsaddr/pl-sin.testnet.drand.sh/",
}
return addrutil.ParseAddresses(context.TODO(), addrs)
}
+6 -6
View File
@@ -1,6 +1,6 @@
/dns4/t01000.miner.interopnet.kittyhawk.wtf/tcp/1347/p2p/12D3KooWLVgeFhXA7ztuSS1uvk4NVzZwRZLxg8PBy1mJuHfc8J6E /dns4/t01000.miner.interopnet.kittyhawk.wtf/tcp/1347/p2p/12D3KooWQfrGdBE8N2RzcnuHfyWZ4MBKMYZ6z1oPdhEbFxSNo1du
/ip4/34.217.110.132/tcp/1347/p2p/12D3KooWLVgeFhXA7ztuSS1uvk4NVzZwRZLxg8PBy1mJuHfc8J6E /ip4/34.217.110.132/tcp/1347/p2p/12D3KooWQfrGdBE8N2RzcnuHfyWZ4MBKMYZ6z1oPdhEbFxSNo1du
/dns4/peer0.interopnet.kittyhawk.wtf/tcp/1347/p2p/12D3KooWBkXWpT1hLHXz7VzR8ZHCJ42P6c9Nb9532ATSguBpLTKJ /dns4/peer0.interopnet.kittyhawk.wtf/tcp/1347/p2p/12D3KooWKmHh5mQofRhFr6f6qsT4ksL7qUtd2BWC24wPHVFL9gej
/ip4/54.187.182.170/tcp/1347/p2p/12D3KooWBkXWpT1hLHXz7VzR8ZHCJ42P6c9Nb9532ATSguBpLTKJ /ip4/54.187.182.170/tcp/1347/p2p/12D3KooWKmHh5mQofRhFr6f6qsT4ksL7qUtd2BWC24wPHVFL9gej
/dns4/peer1.interopnet.kittyhawk.wtf/tcp/1347/p2p/12D3KooWJk5hQHNdCsidtX4jhKQMBXKJdo2kjhrNHUZBPmCZKwKt /dns4/peer1.interopnet.kittyhawk.wtf/tcp/1347/p2p/12D3KooWCWWtn3GMFVSn2PY7k9K7QkQTVA6p6wojUr5PgS5h1xtK
/ip4/52.24.84.39/tcp/1347/p2p/12D3KooWJk5hQHNdCsidtX4jhKQMBXKJdo2kjhrNHUZBPmCZKwKt /ip4/52.24.84.39/tcp/1347/p2p/12D3KooWCWWtn3GMFVSn2PY7k9K7QkQTVA6p6wojUr5PgS5h1xtK
Binary file not shown.
+1 -1
View File
@@ -2,6 +2,6 @@ package build
import rice "github.com/GeertJohan/go.rice" import rice "github.com/GeertJohan/go.rice"
func ParametersJSON() []byte { func ParametersJson() []byte {
return rice.MustFindBox("proof-params").MustBytes("parameters.json") return rice.MustFindBox("proof-params").MustBytes("parameters.json")
} }
-4
View File
@@ -7,7 +7,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/abi/big" "github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power" "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
) )
func init() { func init() {
@@ -15,9 +14,6 @@ func init() {
miner.SupportedProofTypes = map[abi.RegisteredProof]struct{}{ miner.SupportedProofTypes = map[abi.RegisteredProof]struct{}{
abi.RegisteredProof_StackedDRG2KiBSeal: {}, abi.RegisteredProof_StackedDRG2KiBSeal: {},
} }
verifreg.MinVerifiedDealSize = big.NewInt(256)
BuildType |= Build2k
} }
// Seconds // Seconds
-1
View File
@@ -4,7 +4,6 @@ package build
func init() { func init() {
InsecurePoStValidation = true InsecurePoStValidation = true
BuildType |= BuildDebug
} }
// NOTE: Also includes settings from params_2k // NOTE: Also includes settings from params_2k
+8 -8
View File
@@ -25,7 +25,7 @@ func DefaultSectorSize() abi.SectorSize {
} }
sort.Slice(szs, func(i, j int) bool { sort.Slice(szs, func(i, j int) bool {
return szs[i] < szs[j] return szs[i] < szs[i]
}) })
return szs[0] return szs[0]
@@ -59,7 +59,6 @@ var BlocksPerEpoch = uint64(builtin.ExpectedLeadersPerEpoch)
// Epochs // Epochs
const Finality = miner.ChainFinalityish const Finality = miner.ChainFinalityish
const MessageConfidence = 5
// constants for Weight calculation // constants for Weight calculation
// The ratio of weight contributed by short-term vs long-term factors in a given round // The ratio of weight contributed by short-term vs long-term factors in a given round
@@ -110,15 +109,16 @@ const BadBlockCacheSize = 1 << 15
// 10 block reorg. // 10 block reorg.
const BlsSignatureCacheSize = 40000 const BlsSignatureCacheSize = 40000
// Size of signature verification cache
// 32k keeps the cache around 10MB in size, max
const VerifSigCacheSize = 32000
// /////// // ///////
// Limits // Limits
// TODO: If this is gonna stay, it should move to specs-actors // TODO: If this is gonna stay, it should move to specs-actors
const BlockMessageLimit = 512 const BlockMessageLimit = 512
const BlockGasLimit = 100_000_000_000 const BlockGasLimit = 100_000_000
var DrandChain = `{"public_key":"922a2e93828ff83345bae533f5172669a26c02dc76d6bf59c80892e12ab1455c229211886f35bb56af6d5bea981024df","period":25,"genesis_time":1590445175,"hash":"138a324aa6540f93d0dad002aa89454b1bec2b6e948682cde6bd4db40f4b7c9b"}` var DrandCoeffs = []string{
"82c279cce744450e68de98ee08f9698a01dd38f8e3be3c53f2b840fb9d09ad62a0b6b87981e179e1b14bc9a2d284c985",
"82d51308ad346c686f81b8094551597d7b963295cbf313401a93df9baf52d5ae98a87745bee70839a4d6e65c342bd15b",
"94eebfd53f4ba6a3b8304236400a12e73885e5a781509a5c8d41d2e8b476923d8ea6052649b3c17282f596217f96c5de",
"8dc4231e42b4edf39e86ef1579401692480647918275da767d3e558c520d6375ad953530610fd27daf110187877a65d0",
}
+1 -1
View File
@@ -12,7 +12,7 @@ import (
) )
func init() { func init() {
power.ConsensusMinerMinPower = big.NewInt(1024 << 20) power.ConsensusMinerMinPower = big.NewInt(2 << 30)
miner.SupportedProofTypes = map[abi.RegisteredProof]struct{}{ miner.SupportedProofTypes = map[abi.RegisteredProof]struct{}{
abi.RegisteredProof_StackedDRG512MiBSeal: {}, abi.RegisteredProof_StackedDRG512MiBSeal: {},
abi.RegisteredProof_StackedDRG32GiBSeal: {}, abi.RegisteredProof_StackedDRG32GiBSeal: {},
+2 -25
View File
@@ -3,33 +3,11 @@ package build
import "fmt" import "fmt"
var CurrentCommit string var CurrentCommit string
var BuildType int
const (
BuildDefault = 0
Build2k = 0x1
BuildDebug = 0x3
)
func buildType() string {
switch BuildType {
case BuildDefault:
return ""
case BuildDebug:
return "+debug"
case Build2k:
return "+2k"
default:
return "+huh?"
}
}
// BuildVersion is the local build version, set by build system // BuildVersion is the local build version, set by build system
const BuildVersion = "0.4.0" const BuildVersion = "0.3.0"
func UserVersion() string { var UserVersion = BuildVersion + CurrentCommit
return BuildVersion + buildType() + CurrentCommit
}
type Version uint32 type Version uint32
@@ -55,7 +33,6 @@ func (ve Version) EqMajorMinor(v2 Version) bool {
// APIVersion is a semver version of the rpc api exposed // APIVersion is a semver version of the rpc api exposed
var APIVersion Version = newVer(0, 3, 0) var APIVersion Version = newVer(0, 3, 0)
//nolint:varcheck,deadcode
const ( const (
majorMask = 0xff0000 majorMask = 0xff0000
minorMask = 0xffff00 minorMask = 0xffff00
-1
View File
@@ -50,7 +50,6 @@ func Newf(retCode exitcode.ExitCode, format string, args ...interface{}) ActorEr
} }
// todo: bit hacky // todo: bit hacky
func NewfSkip(skip int, retCode exitcode.ExitCode, format string, args ...interface{}) ActorError { func NewfSkip(skip int, retCode exitcode.ExitCode, format string, args ...interface{}) ActorError {
if retCode == 0 { if retCode == 0 {
return &actorError{ return &actorError{
+116 -74
View File
@@ -1,45 +1,45 @@
package drand package drand
import ( import (
"bytes"
"context" "context"
"math/rand"
"sync" "sync"
"time" "time"
dchain "github.com/drand/drand/chain"
dclient "github.com/drand/drand/client"
gclient "github.com/drand/drand/cmd/relay-gossip/client"
dlog "github.com/drand/drand/log"
"github.com/drand/kyber"
kzap "github.com/go-kit/kit/log/zap"
"go.uber.org/zap/zapcore"
"golang.org/x/xerrors"
logging "github.com/ipfs/go-log"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/beacon" "github.com/filecoin-project/lotus/chain/beacon"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"golang.org/x/xerrors"
logging "github.com/ipfs/go-log"
dbeacon "github.com/drand/drand/beacon"
"github.com/drand/drand/core"
dkey "github.com/drand/drand/key"
dnet "github.com/drand/drand/net"
dproto "github.com/drand/drand/protobuf/drand"
) )
var log = logging.Logger("drand") var log = logging.Logger("drand")
var drandServers = []string{ var drandServers = []string{
"https://pl-eu.testnet.drand.sh", "nicolas.drand.fil-test.net:443",
"https://pl-us.testnet.drand.sh", "philipp.drand.fil-test.net:443",
"https://pl-sin.testnet.drand.sh", "mathilde.drand.fil-test.net:443",
"ludovic.drand.fil-test.net:443",
"gabbi.drand.fil-test.net:443",
"linus.drand.fil-test.net:443",
"jeff.drand.fil-test.net:443",
} }
var drandChain *dchain.Info var drandPubKey *dkey.DistPublic
func init() { func init() {
drandPubKey = new(dkey.DistPublic)
var err error err := drandPubKey.FromTOML(&dkey.DistPublicTOML{Coefficients: build.DrandCoeffs})
drandChain, err = dchain.InfoFromJSON(bytes.NewReader([]byte(build.DrandChain)))
if err != nil { if err != nil {
panic("could not unmarshal chain info: " + err.Error()) panic(err)
} }
} }
@@ -57,9 +57,13 @@ func (dp *drandPeer) IsTLS() bool {
} }
type DrandBeacon struct { type DrandBeacon struct {
client dclient.Client client dnet.Client
pubkey kyber.Point peers []dnet.Peer
peersIndex int
peersIndexMtx sync.Mutex
pubkey *dkey.DistPublic
// seconds // seconds
interval time.Duration interval time.Duration
@@ -72,83 +76,120 @@ type DrandBeacon struct {
localCache map[uint64]types.BeaconEntry localCache map[uint64]types.BeaconEntry
} }
func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub) (*DrandBeacon, error) { func NewDrandBeacon(genesisTs, interval uint64) (*DrandBeacon, error) {
if genesisTs == 0 { if genesisTs == 0 {
panic("what are you doing this cant be zero") panic("what are you doing this cant be zero")
} }
dlogger := dlog.NewKitLoggerFrom(kzap.NewZapSugarLogger(
log.SugaredLogger.Desugar(), zapcore.InfoLevel))
opts := []dclient.Option{
dclient.WithChainInfo(drandChain),
dclient.WithHTTPEndpoints(drandServers),
dclient.WithCacheSize(1024),
dclient.WithLogger(dlogger),
}
if ps != nil {
opts = append(opts, gclient.WithPubsub(ps))
} else {
log.Info("drand beacon without pubsub")
}
client, err := dclient.New(opts...)
if err != nil {
return nil, xerrors.Errorf("creating drand client")
}
go func() {
// Explicitly Watch until that is fixed in drand
ch := client.Watch(context.Background())
for range ch {
}
log.Error("dranch Watch bork")
}()
db := &DrandBeacon{ db := &DrandBeacon{
client: client, client: dnet.NewGrpcClient(),
localCache: make(map[uint64]types.BeaconEntry), localCache: make(map[uint64]types.BeaconEntry),
} }
for _, ds := range drandServers {
db.peers = append(db.peers, &drandPeer{addr: ds, tls: true})
}
db.pubkey = drandChain.PublicKey db.peersIndex = rand.Intn(len(db.peers))
db.interval = drandChain.Period
db.drandGenTime = uint64(drandChain.GenesisTime) groupResp, err := db.client.Group(context.TODO(), db.peers[db.peersIndex], &dproto.GroupRequest{})
if err != nil {
return nil, xerrors.Errorf("failed to get group response from beacon peer: %w", err)
}
kgroup, err := core.ProtoToGroup(groupResp)
if err != nil {
return nil, xerrors.Errorf("failed to parse group response: %w", err)
}
// TODO: verify these values are what we expect them to be
if !kgroup.PublicKey.Equal(drandPubKey) {
return nil, xerrors.Errorf("public key does not match")
}
// fmt.Printf("Drand Pubkey:\n%#v\n", kgroup.PublicKey.TOML()) // use to print public key
db.pubkey = drandPubKey
db.interval = kgroup.Period
db.drandGenTime = uint64(kgroup.GenesisTime)
db.filRoundTime = interval db.filRoundTime = interval
db.filGenTime = genesisTs db.filGenTime = genesisTs
// TODO: the stream currently gives you back *all* values since drand genesis.
// Having the stream in the background is merely an optimization, so not a big deal to disable it for now
// go db.handleStreamingUpdates()
return db, nil return db, nil
} }
func (db *DrandBeacon) Entry(ctx context.Context, round uint64) <-chan beacon.Response { func (db *DrandBeacon) rotatePeersIndex() {
out := make(chan beacon.Response, 1) db.peersIndexMtx.Lock()
if round != 0 { nval := rand.Intn(len(db.peers))
be := db.getCachedValue(round) db.peersIndex = nval
if be != nil { db.peersIndexMtx.Unlock()
out <- beacon.Response{Entry: *be}
close(out) log.Warnf("rotated to drand peer %d, %q", nval, db.peers[nval].Address())
return out }
func (db *DrandBeacon) getPeerIndex() int {
db.peersIndexMtx.Lock()
defer db.peersIndexMtx.Unlock()
return db.peersIndex
}
func (db *DrandBeacon) handleStreamingUpdates() {
for {
p := db.peers[db.getPeerIndex()]
ch, err := db.client.PublicRandStream(context.Background(), p, &dproto.PublicRandRequest{})
if err != nil {
log.Warnf("failed to get public rand stream to peer %q: %s", p.Address(), err)
log.Warnf("trying again in 10 seconds")
db.rotatePeersIndex()
time.Sleep(time.Second * 10)
continue
} }
for e := range ch {
db.cacheValue(types.BeaconEntry{
Round: e.Round,
Data: e.Signature,
})
}
log.Warnf("drand beacon stream to peer %q broke, reconnecting in 10 seconds", p.Address())
db.rotatePeersIndex()
time.Sleep(time.Second * 10)
}
}
func (db *DrandBeacon) Entry(ctx context.Context, round uint64) <-chan beacon.Response {
// check cache, it it if there, otherwise query the endpoint
cres := db.getCachedValue(round)
if cres != nil {
out := make(chan beacon.Response, 1)
out <- beacon.Response{Entry: *cres}
close(out)
return out
} }
out := make(chan beacon.Response, 1)
go func() { go func() {
start := time.Now() p := db.peers[db.getPeerIndex()]
log.Infow("start fetching randomness", "round", round) resp, err := db.client.PublicRand(ctx, p, &dproto.PublicRandRequest{Round: round})
resp, err := db.client.Get(ctx, round)
var br beacon.Response var br beacon.Response
if err != nil { if err != nil {
br.Err = xerrors.Errorf("drand failed Get request: %w", err) db.rotatePeersIndex()
br.Err = xerrors.Errorf("drand peer %q failed publicRand request: %w", p.Address(), err)
} else { } else {
br.Entry.Round = resp.Round() br.Entry.Round = resp.GetRound()
br.Entry.Data = resp.Signature() br.Entry.Data = resp.GetSignature()
} }
log.Infow("done fetching randomness", "round", round, "took", time.Since(start))
out <- br out <- br
close(out) close(out)
}() }()
return out return out
} }
func (db *DrandBeacon) cacheValue(e types.BeaconEntry) { func (db *DrandBeacon) cacheValue(e types.BeaconEntry) {
db.cacheLk.Lock() db.cacheLk.Lock()
defer db.cacheLk.Unlock() defer db.cacheLk.Unlock()
@@ -170,12 +211,13 @@ func (db *DrandBeacon) VerifyEntry(curr types.BeaconEntry, prev types.BeaconEntr
// TODO handle genesis better // TODO handle genesis better
return nil return nil
} }
b := &dchain.Beacon{ b := &dbeacon.Beacon{
PreviousSig: prev.Data, PreviousSig: prev.Data,
Round: curr.Round, Round: curr.Round,
Signature: curr.Data, Signature: curr.Data,
} }
err := dchain.VerifyBeacon(db.pubkey, b) //log.Warnw("VerifyEntry", "beacon", b)
err := dbeacon.VerifyBeacon(db.pubkey.Key(), b)
if err == nil { if err == nil {
db.cacheValue(curr) db.cacheValue(curr)
} }
+7 -15
View File
@@ -1,22 +1,14 @@
package drand package drand
import ( import (
"os" "fmt"
"testing" "testing"
dchain "github.com/drand/drand/chain"
dclient "github.com/drand/drand/client"
"github.com/stretchr/testify/assert"
) )
func TestPrintGroupInfo(t *testing.T) { func TestPrintDrandPubkey(t *testing.T) {
c, err := dclient.NewHTTPClient(drandServers[0], nil, nil) bc, err := NewDrandBeacon(1, 1)
assert.NoError(t, err) if err != nil {
cg := c.(interface { t.Fatal(err)
FetchChainInfo(groupHash []byte) (*dchain.Info, error) }
}) fmt.Printf("Drand Pubkey:\n%#v\n", bc.pubkey.TOML())
chain, err := cg.FetchChainInfo(nil)
assert.NoError(t, err)
err = chain.ToJSON(os.Stdout)
assert.NoError(t, err)
} }
+2 -2
View File
@@ -91,7 +91,7 @@ func (bss *BlockSyncService) HandleStream(s inet.Stream) {
ctx, span := trace.StartSpan(context.Background(), "blocksync.HandleStream") ctx, span := trace.StartSpan(context.Background(), "blocksync.HandleStream")
defer span.End() defer span.End()
defer s.Close() //nolint:errcheck defer s.Close()
var req BlockSyncRequest var req BlockSyncRequest
if err := cborutil.ReadCborRPC(bufio.NewReader(s), &req); err != nil { if err := cborutil.ReadCborRPC(bufio.NewReader(s), &req); err != nil {
@@ -107,7 +107,7 @@ func (bss *BlockSyncService) HandleStream(s inet.Stream) {
} }
writeDeadline := 60 * time.Second writeDeadline := 60 * time.Second
_ = s.SetDeadline(time.Now().Add(writeDeadline)) s.SetDeadline(time.Now().Add(writeDeadline))
if err := cborutil.WriteCborRPC(s, resp); err != nil { if err := cborutil.WriteCborRPC(s, resp); err != nil {
log.Warnw("failed to write back response for handle stream", "err", err, "peer", s.Conn().RemotePeer()) log.Warnw("failed to write back response for handle stream", "err", err, "peer", s.Conn().RemotePeer())
return return
+12 -16
View File
@@ -283,14 +283,14 @@ func (bs *BlockSync) fetchBlocksBlockSync(ctx context.Context, p peer.ID, req *B
bs.RemovePeer(p) bs.RemovePeer(p)
return nil, xerrors.Errorf("failed to open stream to peer: %w", err) return nil, xerrors.Errorf("failed to open stream to peer: %w", err)
} }
_ = s.SetWriteDeadline(time.Now().Add(5 * time.Second)) s.SetWriteDeadline(time.Now().Add(5 * time.Second))
if err := cborutil.WriteCborRPC(s, req); err != nil { if err := cborutil.WriteCborRPC(s, req); err != nil {
_ = s.SetWriteDeadline(time.Time{}) s.SetWriteDeadline(time.Time{})
bs.syncPeers.logFailure(p, time.Since(start)) bs.syncPeers.logFailure(p, time.Since(start))
return nil, err return nil, err
} }
_ = s.SetWriteDeadline(time.Time{}) s.SetWriteDeadline(time.Time{})
var res BlockSyncResponse var res BlockSyncResponse
r := incrt.New(s, 50<<10, 5*time.Second) r := incrt.New(s, 50<<10, 5*time.Second)
@@ -561,30 +561,26 @@ func (bpt *bsPeerTracker) logSuccess(p peer.ID, dur time.Duration) {
bpt.lk.Lock() bpt.lk.Lock()
defer bpt.lk.Unlock() defer bpt.lk.Unlock()
var pi *peerStats if pi, ok := bpt.peers[p]; !ok {
var ok bool
if pi, ok = bpt.peers[p]; !ok {
log.Warnw("log success called on peer not in tracker", "peerid", p.String()) log.Warnw("log success called on peer not in tracker", "peerid", p.String())
return return
} } else {
pi.successes++
pi.successes++ logTime(pi, dur)
logTime(pi, dur) }
} }
func (bpt *bsPeerTracker) logFailure(p peer.ID, dur time.Duration) { func (bpt *bsPeerTracker) logFailure(p peer.ID, dur time.Duration) {
bpt.lk.Lock() bpt.lk.Lock()
defer bpt.lk.Unlock() defer bpt.lk.Unlock()
if pi, ok := bpt.peers[p]; !ok {
var pi *peerStats
var ok bool
if pi, ok = bpt.peers[p]; !ok {
log.Warn("log failure called on peer not in tracker", "peerid", p.String()) log.Warn("log failure called on peer not in tracker", "peerid", p.String())
return return
} else {
pi.failures++
logTime(pi, dur)
} }
pi.failures++
logTime(pi, dur)
} }
func (bpt *bsPeerTracker) removePeer(p peer.ID) { func (bpt *bsPeerTracker) removePeer(p peer.ID) {
+8 -14
View File
@@ -19,7 +19,7 @@ import (
var log = logging.Logger("events") var log = logging.Logger("events")
// HeightHandler `curH`-`ts.Height` = `confidence` // `curH`-`ts.Height` = `confidence`
type HeightHandler func(ctx context.Context, ts *types.TipSet, curH abi.ChainEpoch) error type HeightHandler func(ctx context.Context, ts *types.TipSet, curH abi.ChainEpoch) error
type RevertHandler func(ctx context.Context, ts *types.TipSet) error type RevertHandler func(ctx context.Context, ts *types.TipSet) error
@@ -31,18 +31,17 @@ type heightHandler struct {
revert RevertHandler revert RevertHandler
} }
type eventAPI interface { type eventApi interface {
ChainNotify(context.Context) (<-chan []*api.HeadChange, error) ChainNotify(context.Context) (<-chan []*api.HeadChange, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error)
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // optional / for CalledMsg StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // optional / for CalledMsg
} }
type Events struct { type Events struct {
api eventAPI api eventApi
tsc *tipSetCache tsc *tipSetCache
lk sync.Mutex lk sync.Mutex
@@ -54,7 +53,7 @@ type Events struct {
calledEvents calledEvents
} }
func NewEvents(ctx context.Context, api eventAPI) *Events { func NewEvents(ctx context.Context, api eventApi) *Events {
gcConfidence := 2 * build.ForkLengthThreshold gcConfidence := 2 * build.ForkLengthThreshold
tsc := newTSCache(gcConfidence, api.ChainGetTipSetByHeight) tsc := newTSCache(gcConfidence, api.ChainGetTipSetByHeight)
@@ -67,7 +66,7 @@ func NewEvents(ctx context.Context, api eventAPI) *Events {
heightEvents: heightEvents{ heightEvents: heightEvents{
tsc: tsc, tsc: tsc,
ctx: ctx, ctx: ctx,
gcConfidence: gcConfidence, gcConfidence: abi.ChainEpoch(gcConfidence),
heightTriggers: map[uint64]*heightHandler{}, heightTriggers: map[uint64]*heightHandler{},
htTriggerHeights: map[abi.ChainEpoch][]uint64{}, htTriggerHeights: map[abi.ChainEpoch][]uint64{},
@@ -82,9 +81,9 @@ func NewEvents(ctx context.Context, api eventAPI) *Events {
confQueue: map[triggerH]map[msgH][]*queuedEvent{}, confQueue: map[triggerH]map[msgH][]*queuedEvent{},
revertQueue: map[msgH][]triggerH{}, revertQueue: map[msgH][]triggerH{},
triggers: map[triggerID]*callHandler{}, triggers: map[triggerId]*callHandler{},
matchers: map[triggerID][]MatchFunc{}, matchers: map[triggerId][]MatchFunc{},
timeouts: map[abi.ChainEpoch]map[triggerID]int{}, timeouts: map[abi.ChainEpoch]map[triggerId]int{},
}, },
} }
@@ -164,11 +163,6 @@ func (e *Events) listenHeadChangesOnce(ctx context.Context) error {
if err := e.headChange(rev, app); err != nil { if err := e.headChange(rev, app); err != nil {
log.Warnf("headChange failed: %s", err) log.Warnf("headChange failed: %s", err)
} }
// sync with fake chainstore (for tests)
if fcs, ok := e.api.(interface{ notifDone() }); ok {
fcs.notifDone()
}
} }
return nil return nil
+16 -22
View File
@@ -14,7 +14,7 @@ import (
const NoTimeout = math.MaxInt64 const NoTimeout = math.MaxInt64
type triggerID = uint64 type triggerId = uint64
// msgH is the block height at which a message was present / event has happened // msgH is the block height at which a message was present / event has happened
type msgH = abi.ChainEpoch type msgH = abi.ChainEpoch
@@ -23,7 +23,6 @@ type msgH = abi.ChainEpoch
// message (msgH+confidence) // message (msgH+confidence)
type triggerH = abi.ChainEpoch type triggerH = abi.ChainEpoch
// CalledHandler arguments:
// `ts` is the tipset, in which the `msg` is included. // `ts` is the tipset, in which the `msg` is included.
// `curH`-`ts.Height` = `confidence` // `curH`-`ts.Height` = `confidence`
type CalledHandler func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (more bool, err error) type CalledHandler func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (more bool, err error)
@@ -49,7 +48,7 @@ type callHandler struct {
} }
type queuedEvent struct { type queuedEvent struct {
trigger triggerID trigger triggerId
h abi.ChainEpoch h abi.ChainEpoch
msg *types.Message msg *types.Message
@@ -58,7 +57,7 @@ type queuedEvent struct {
} }
type calledEvents struct { type calledEvents struct {
cs eventAPI cs eventApi
tsc *tipSetCache tsc *tipSetCache
ctx context.Context ctx context.Context
gcConfidence uint64 gcConfidence uint64
@@ -67,10 +66,10 @@ type calledEvents struct {
lk sync.Mutex lk sync.Mutex
ctr triggerID ctr triggerId
triggers map[triggerID]*callHandler triggers map[triggerId]*callHandler
matchers map[triggerID][]MatchFunc matchers map[triggerId][]MatchFunc
// maps block heights to events // maps block heights to events
// [triggerH][msgH][event] // [triggerH][msgH][event]
@@ -79,8 +78,8 @@ type calledEvents struct {
// [msgH][triggerH] // [msgH][triggerH]
revertQueue map[msgH][]triggerH revertQueue map[msgH][]triggerH
// [timeoutH+confidence][triggerID]{calls} // [timeoutH+confidence][triggerId]{calls}
timeouts map[abi.ChainEpoch]map[triggerID]int timeouts map[abi.ChainEpoch]map[triggerId]int
} }
func (e *calledEvents) headChangeCalled(rev, app []*types.TipSet) error { func (e *calledEvents) headChangeCalled(rev, app []*types.TipSet) error {
@@ -126,13 +125,7 @@ func (e *calledEvents) handleReverts(ts *types.TipSet) {
} }
func (e *calledEvents) checkNewCalls(ts *types.TipSet) { func (e *calledEvents) checkNewCalls(ts *types.TipSet) {
pts, err := e.cs.ChainGetTipSet(e.ctx, ts.Parents()) // we actually care about messages in the parent tipset here e.messagesForTs(ts, func(msg *types.Message) {
if err != nil {
log.Errorf("getting parent tipset in checkNewCalls: %s", err)
return
}
e.messagesForTs(pts, func(msg *types.Message) {
// TODO: provide receipts // TODO: provide receipts
for tid, matchFns := range e.matchers { for tid, matchFns := range e.matchers {
@@ -158,10 +151,11 @@ func (e *calledEvents) checkNewCalls(ts *types.TipSet) {
}) })
} }
func (e *calledEvents) queueForConfidence(trigID uint64, msg *types.Message, ts *types.TipSet) { func (e *calledEvents) queueForConfidence(triggerId uint64, msg *types.Message, ts *types.TipSet) {
trigger := e.triggers[trigID] trigger := e.triggers[triggerId]
appliedH := ts.Height() // messages are not applied in the tipset they are included in
appliedH := ts.Height() + 1
triggerH := appliedH + abi.ChainEpoch(trigger.confidence) triggerH := appliedH + abi.ChainEpoch(trigger.confidence)
@@ -172,7 +166,7 @@ func (e *calledEvents) queueForConfidence(trigID uint64, msg *types.Message, ts
} }
byOrigH[appliedH] = append(byOrigH[appliedH], &queuedEvent{ byOrigH[appliedH] = append(byOrigH[appliedH], &queuedEvent{
trigger: trigID, trigger: triggerId,
h: appliedH, h: appliedH,
msg: msg, msg: msg,
}) })
@@ -232,11 +226,11 @@ func (e *calledEvents) applyTimeouts(ts *types.TipSet) {
return // nothing to do return // nothing to do
} }
for triggerID, calls := range triggers { for triggerId, calls := range triggers {
if calls > 0 { if calls > 0 {
continue // don't timeout if the method was called continue // don't timeout if the method was called
} }
trigger := e.triggers[triggerID] trigger := e.triggers[triggerId]
if trigger.disabled { if trigger.disabled {
continue continue
} }
+4 -4
View File
@@ -15,12 +15,12 @@ type heightEvents struct {
tsc *tipSetCache tsc *tipSetCache
gcConfidence abi.ChainEpoch gcConfidence abi.ChainEpoch
ctr triggerID ctr triggerId
heightTriggers map[triggerID]*heightHandler heightTriggers map[triggerId]*heightHandler
htTriggerHeights map[triggerH][]triggerID htTriggerHeights map[triggerH][]triggerId
htHeights map[msgH][]triggerID htHeights map[msgH][]triggerId
ctx context.Context ctx context.Context
} }
+31 -149
View File
@@ -3,20 +3,21 @@ package events
import ( import (
"context" "context"
"fmt" "fmt"
"sync"
"testing" "testing"
"time"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/store"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash" "github.com/multiformats/go-multihash"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
@@ -39,17 +40,9 @@ type fakeCS struct {
msgs map[cid.Cid]fakeMsg msgs map[cid.Cid]fakeMsg
blkMsgs map[cid.Cid]cid.Cid blkMsgs map[cid.Cid]cid.Cid
sync sync.Mutex
tipsets map[types.TipSetKey]*types.TipSet
sub func(rev, app []*types.TipSet) sub func(rev, app []*types.TipSet)
} }
func (fcs *fakeCS) ChainGetTipSet(ctx context.Context, key types.TipSetKey) (*types.TipSet, error) {
return fcs.tipsets[key], nil
}
func (fcs *fakeCS) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) { func (fcs *fakeCS) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) {
return nil, nil return nil, nil
} }
@@ -62,7 +55,7 @@ func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types
panic("Not Implemented") panic("Not Implemented")
} }
func (fcs *fakeCS) makeTs(t *testing.T, parents []cid.Cid, h abi.ChainEpoch, msgcid cid.Cid) *types.TipSet { func makeTs(t *testing.T, h abi.ChainEpoch, msgcid cid.Cid) *types.TipSet {
a, _ := address.NewFromString("t00") a, _ := address.NewFromString("t00")
b, _ := address.NewFromString("t02") b, _ := address.NewFromString("t02")
var ts, err = types.NewTipSet([]*types.BlockHeader{ var ts, err = types.NewTipSet([]*types.BlockHeader{
@@ -70,8 +63,6 @@ func (fcs *fakeCS) makeTs(t *testing.T, parents []cid.Cid, h abi.ChainEpoch, msg
Height: h, Height: h,
Miner: a, Miner: a,
Parents: parents,
Ticket: &types.Ticket{VRFProof: []byte{byte(h % 2)}}, Ticket: &types.Ticket{VRFProof: []byte{byte(h % 2)}},
ParentStateRoot: dummyCid, ParentStateRoot: dummyCid,
@@ -85,8 +76,6 @@ func (fcs *fakeCS) makeTs(t *testing.T, parents []cid.Cid, h abi.ChainEpoch, msg
Height: h, Height: h,
Miner: b, Miner: b,
Parents: parents,
Ticket: &types.Ticket{VRFProof: []byte{byte((h + 1) % 2)}}, Ticket: &types.Ticket{VRFProof: []byte{byte((h + 1) % 2)}},
ParentStateRoot: dummyCid, ParentStateRoot: dummyCid,
@@ -98,11 +87,6 @@ func (fcs *fakeCS) makeTs(t *testing.T, parents []cid.Cid, h abi.ChainEpoch, msg
}, },
}) })
if fcs.tipsets == nil {
fcs.tipsets = map[types.TipSetKey]*types.TipSet{}
}
fcs.tipsets[ts.Key()] = ts
require.NoError(t, err) require.NoError(t, err)
return ts return ts
@@ -196,7 +180,7 @@ func (fcs *fakeCS) advance(rev, app int, msgs map[int]cid.Cid, nulls ...int) { /
continue continue
} }
ts := fcs.makeTs(fcs.t, fcs.tsc.best().Key().Cids(), fcs.h, mc) ts := makeTs(fcs.t, fcs.h, mc)
require.NoError(fcs.t, fcs.tsc.add(ts)) require.NoError(fcs.t, fcs.tsc.add(ts))
if hasMsgs { if hasMsgs {
@@ -206,19 +190,11 @@ func (fcs *fakeCS) advance(rev, app int, msgs map[int]cid.Cid, nulls ...int) { /
apps = append(apps, ts) apps = append(apps, ts)
} }
fcs.sync.Lock()
fcs.sub(revs, apps) fcs.sub(revs, apps)
time.Sleep(100 * time.Millisecond) // TODO: :c
fcs.sync.Lock()
fcs.sync.Unlock() //nolint:staticcheck
} }
func (fcs *fakeCS) notifDone() { var _ eventApi = &fakeCS{}
fcs.sync.Unlock()
}
var _ eventAPI = &fakeCS{}
func TestAt(t *testing.T) { func TestAt(t *testing.T) {
fcs := &fakeCS{ fcs := &fakeCS{
@@ -226,7 +202,7 @@ func TestAt(t *testing.T) {
h: 1, h: 1,
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs) events := NewEvents(context.Background(), fcs)
@@ -291,7 +267,7 @@ func TestAtDoubleTrigger(t *testing.T) {
h: 1, h: 1,
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs) events := NewEvents(context.Background(), fcs)
@@ -333,7 +309,7 @@ func TestAtNullTrigger(t *testing.T) {
h: 1, h: 1,
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs) events := NewEvents(context.Background(), fcs)
@@ -367,7 +343,7 @@ func TestAtNullConf(t *testing.T) {
h: 1, h: 1,
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs) events := NewEvents(context.Background(), fcs)
@@ -406,7 +382,7 @@ func TestAtStart(t *testing.T) {
h: 1, h: 1,
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs) events := NewEvents(context.Background(), fcs)
@@ -440,7 +416,7 @@ func TestAtStartConfidence(t *testing.T) {
h: 1, h: 1,
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs) events := NewEvents(context.Background(), fcs)
@@ -470,7 +446,7 @@ func TestAtChained(t *testing.T) {
h: 1, h: 1,
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs) events := NewEvents(context.Background(), fcs)
@@ -504,7 +480,7 @@ func TestAtChainedConfidence(t *testing.T) {
h: 1, h: 1,
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs) events := NewEvents(context.Background(), fcs)
@@ -538,7 +514,7 @@ func TestAtChainedConfidenceNull(t *testing.T) {
h: 1, h: 1,
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs) events := NewEvents(context.Background(), fcs)
@@ -576,7 +552,7 @@ func TestCalled(t *testing.T) {
blkMsgs: map[cid.Cid]cid.Cid{}, blkMsgs: map[cid.Cid]cid.Cid{},
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs) events := NewEvents(context.Background(), fcs)
@@ -652,7 +628,7 @@ func TestCalled(t *testing.T) {
// revert the message // revert the message
fcs.advance(2, 1, nil) // H=7, we reverted ts with the msg execution, but not the msg itself fcs.advance(2, 1, nil) // H=7, we reverted ts with the msg
require.Equal(t, false, applied) require.Equal(t, false, applied)
require.Equal(t, true, reverted) require.Equal(t, true, reverted)
@@ -666,17 +642,10 @@ func TestCalled(t *testing.T) {
}, },
}) })
fcs.advance(0, 3, map[int]cid.Cid{ // (n2msg confidence=1) fcs.advance(0, 5, map[int]cid.Cid{ // (confidence=3)
0: n2msg, 0: n2msg,
}) })
require.Equal(t, true, applied) // msg from H=7, which had reverted execution
require.Equal(t, false, reverted)
require.Equal(t, abi.ChainEpoch(10), appliedH)
applied = false
fcs.advance(0, 2, nil) // (confidence=3)
require.Equal(t, true, applied) require.Equal(t, true, applied)
require.Equal(t, false, reverted) require.Equal(t, false, reverted)
applied = false applied = false
@@ -690,7 +659,7 @@ func TestCalled(t *testing.T) {
// revert and apply at different height // revert and apply at different height
fcs.advance(8, 6, map[int]cid.Cid{ // (confidence=3) fcs.advance(4, 6, map[int]cid.Cid{ // (confidence=3)
1: n2msg, 1: n2msg,
}) })
@@ -702,9 +671,9 @@ func TestCalled(t *testing.T) {
reverted = false reverted = false
applied = false applied = false
require.Equal(t, abi.ChainEpoch(7), appliedTs.Height()) require.Equal(t, abi.ChainEpoch(11), appliedTs.Height())
require.Equal(t, "bafkqaaa", appliedTs.Blocks()[0].Messages.String()) require.Equal(t, "bafkqaaa", appliedTs.Blocks()[0].Messages.String())
require.Equal(t, abi.ChainEpoch(10), appliedH) require.Equal(t, abi.ChainEpoch(14), appliedH)
require.Equal(t, t0123, appliedMsg.To) require.Equal(t, t0123, appliedMsg.To)
require.Equal(t, uint64(2), appliedMsg.Nonce) require.Equal(t, uint64(2), appliedMsg.Nonce)
require.Equal(t, abi.MethodNum(5), appliedMsg.Method) require.Equal(t, abi.MethodNum(5), appliedMsg.Method)
@@ -728,7 +697,7 @@ func TestCalled(t *testing.T) {
}), }),
}) })
fcs.advance(2, 5, nil) // H=19, but message reverted fcs.advance(1, 4, nil) // H=19, but message reverted
require.Equal(t, false, applied) require.Equal(t, false, applied)
require.Equal(t, false, reverted) require.Equal(t, false, reverted)
@@ -788,7 +757,7 @@ func TestCalledTimeout(t *testing.T) {
blkMsgs: map[cid.Cid]cid.Cid{}, blkMsgs: map[cid.Cid]cid.Cid{},
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs) events := NewEvents(context.Background(), fcs)
@@ -828,7 +797,7 @@ func TestCalledTimeout(t *testing.T) {
blkMsgs: map[cid.Cid]cid.Cid{}, blkMsgs: map[cid.Cid]cid.Cid{},
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events = NewEvents(context.Background(), fcs) events = NewEvents(context.Background(), fcs)
@@ -862,7 +831,7 @@ func TestCalledOrder(t *testing.T) {
blkMsgs: map[cid.Cid]cid.Cid{}, blkMsgs: map[cid.Cid]cid.Cid{},
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs) events := NewEvents(context.Background(), fcs)
@@ -925,7 +894,7 @@ func TestCalledNull(t *testing.T) {
blkMsgs: map[cid.Cid]cid.Cid{}, blkMsgs: map[cid.Cid]cid.Cid{},
tsc: newTSCache(2*build.ForkLengthThreshold, nil), tsc: newTSCache(2*build.ForkLengthThreshold, nil),
} }
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid))) require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid)))
events := NewEvents(context.Background(), fcs) events := NewEvents(context.Background(), fcs)
@@ -980,90 +949,3 @@ func TestCalledNull(t *testing.T) {
require.Equal(t, false, applied) require.Equal(t, false, applied)
require.Equal(t, true, reverted) require.Equal(t, true, reverted)
} }
func TestRemoveTriggersOnMessage(t *testing.T) {
fcs := &fakeCS{
t: t,
h: 1,
msgs: map[cid.Cid]fakeMsg{},
blkMsgs: map[cid.Cid]cid.Cid{},
tsc: newTSCache(2*build.ForkLengthThreshold, nil),
}
require.NoError(t, fcs.tsc.add(fcs.makeTs(t, nil, 1, dummyCid)))
events := NewEvents(context.Background(), fcs)
t0123, err := address.NewFromString("t0123")
require.NoError(t, err)
more := true
var applied, reverted bool
err = events.Called(func(ts *types.TipSet) (d bool, m bool, e error) {
return false, true, nil
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (bool, error) {
require.Equal(t, false, applied)
fmt.Println(msg == nil)
fmt.Println(curH)
applied = true
return more, nil
}, func(_ context.Context, ts *types.TipSet) error {
reverted = true
return nil
}, 3, 20, matchAddrMethod(t0123, 5))
require.NoError(t, err)
// create few blocks to make sure nothing get's randomly called
fcs.advance(0, 4, nil) // H=5
require.Equal(t, false, applied)
require.Equal(t, false, reverted)
// create blocks with message (but below confidence threshold)
fcs.advance(0, 3, map[int]cid.Cid{ // msg occurs at H=5, applied at H=6; H=8 (confidence=2)
0: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{
{To: t0123, From: t0123, Method: 5, Nonce: 1},
},
}),
})
require.Equal(t, false, applied)
require.Equal(t, false, reverted)
// revert applied TS & message TS
fcs.advance(3, 1, nil) // H=6 (tipset message applied in reverted, AND message reverted)
require.Equal(t, false, applied)
require.Equal(t, false, reverted)
// create additional blocks so we are above confidence threshold, but message not applied
// as it was reverted
fcs.advance(0, 5, nil) // H=11 (confidence=3, apply)
require.Equal(t, false, applied)
require.Equal(t, false, reverted)
// create blocks with message again (but below confidence threshold)
fcs.advance(0, 3, map[int]cid.Cid{ // msg occurs at H=12, applied at H=13; H=15 (confidence=2)
0: fcs.fakeMsgs(fakeMsg{
bmsgs: []*types.Message{
{To: t0123, From: t0123, Method: 5, Nonce: 2},
},
}),
})
require.Equal(t, false, applied)
require.Equal(t, false, reverted)
// revert applied height TS, but don't remove message trigger
fcs.advance(2, 1, nil) // H=13 (tipset message applied in reverted, by tipset with message not reverted)
require.Equal(t, false, applied)
require.Equal(t, false, reverted)
// create additional blocks so we are above confidence threshold
fcs.advance(0, 4, nil) // H=18 (confidence=3, apply)
require.Equal(t, true, applied)
require.Equal(t, false, reverted)
}
+1 -1
View File
@@ -36,7 +36,7 @@ func (e *calledEvents) CheckMsg(ctx context.Context, smsg types.ChainMsg, hnd Ca
func (e *calledEvents) MatchMsg(inmsg *types.Message) MatchFunc { func (e *calledEvents) MatchMsg(inmsg *types.Message) MatchFunc {
return func(msg *types.Message) (bool, error) { return func(msg *types.Message) (bool, error) {
if msg.From == inmsg.From && msg.Nonce == inmsg.Nonce && !inmsg.Equals(msg) { if msg.From == inmsg.From && msg.Nonce == inmsg.Nonce && !inmsg.Equals(msg) {
return false, xerrors.Errorf("matching msg %s from %s, nonce %d: got duplicate origin/nonce msg %d", inmsg.Cid(), inmsg.From, inmsg.Nonce, msg.Nonce) return false, xerrors.Errorf("matching msg %s from %s, nonce %d: got duplicate origin/nonce msg %s", inmsg.Cid(), inmsg.From, inmsg.Nonce, msg.Nonce)
} }
return inmsg.Equals(msg), nil return inmsg.Equals(msg), nil
+9 -6
View File
@@ -104,7 +104,7 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
return nil, xerrors.Errorf("failed to get metadata datastore: %w", err) return nil, xerrors.Errorf("failed to get metadata datastore: %w", err)
} }
bds, err := lr.Datastore("/chain") bds, err := lr.Datastore("/blocks")
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to get blocks datastore: %w", err) return nil, xerrors.Errorf("failed to get blocks datastore: %w", err)
} }
@@ -219,10 +219,6 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
miners := []address.Address{maddr1, maddr2} miners := []address.Address{maddr1, maddr2}
beac := beacon.NewMockBeacon(time.Second) beac := beacon.NewMockBeacon(time.Second)
//beac, err := drand.NewDrandBeacon(tpl.Timestamp, build.BlockDelay)
//if err != nil {
//return nil, xerrors.Errorf("creating drand beacon: %w", err)
//}
gen := &ChainGen{ gen := &ChainGen{
bs: bs, bs: bs,
@@ -431,7 +427,7 @@ func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, vrfticke
return fblk, err return fblk, err
} }
// ResyncBankerNonce is used for dealing with messages made when // This function is awkward. It's used to deal with messages made when
// simulating forks // simulating forks
func (cg *ChainGen) ResyncBankerNonce(ts *types.TipSet) error { func (cg *ChainGen) ResyncBankerNonce(ts *types.TipSet) error {
act, err := cg.sm.GetActor(cg.banker, ts) act, err := cg.sm.GetActor(cg.banker, ts)
@@ -538,6 +534,13 @@ func (wpp *wppProvider) ComputeProof(context.Context, []abi.SectorInfo, abi.PoSt
}}, nil }}, nil
} }
type ProofInput struct {
sectors []abi.SectorInfo
hvrf []byte
challengedSectors []uint64
vrfout []byte
}
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round abi.ChainEpoch, func IsRoundWinner(ctx context.Context, ts *types.TipSet, round abi.ChainEpoch,
miner address.Address, brand types.BeaconEntry, mbi *api.MiningBaseInfo, a MiningCheckAPI) (*types.ElectionProof, error) { miner address.Address, brand types.BeaconEntry, mbi *api.MiningBaseInfo, a MiningCheckAPI) (*types.ElectionProof, error) {
-2
View File
@@ -7,7 +7,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/abi/big" "github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power" "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" _ "github.com/filecoin-project/lotus/lib/sigs/secp"
@@ -18,7 +17,6 @@ func init() {
abi.RegisteredProof_StackedDRG2KiBSeal: {}, abi.RegisteredProof_StackedDRG2KiBSeal: {},
} }
power.ConsensusMinerMinPower = big.NewInt(2048) power.ConsensusMinerMinPower = big.NewInt(2048)
verifreg.MinVerifiedDealSize = big.NewInt(256)
} }
func testGeneration(t testing.TB, n int, msgs int, sectors int) { func testGeneration(t testing.TB, n int, msgs int, sectors int) {
-73
View File
@@ -5,10 +5,8 @@ import (
"encoding/json" "encoding/json"
"github.com/filecoin-project/go-amt-ipld/v2" "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/account" "github.com/filecoin-project/specs-actors/actors/builtin/account"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/runtime" "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
@@ -22,7 +20,6 @@ import (
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"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"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/genesis"
) )
@@ -218,72 +215,9 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
} }
} }
vregroot, err := address.NewIDAddress(80)
if err != nil {
return nil, err
}
vrst, err := cst.Put(ctx, &account.State{Address: RootVerifierAddr})
if err != nil {
return nil, err
}
err = state.SetActor(vregroot, &types.Actor{
Code: builtin.AccountActorCodeID,
Balance: types.NewInt(0),
Head: vrst,
})
if err != nil {
return nil, xerrors.Errorf("setting account from actmap: %w", err)
}
return state, nil return state, nil
} }
func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot cid.Cid, template genesis.Template) (cid.Cid, error) {
verifNeeds := make(map[address.Address]abi.PaddedPieceSize)
var sum abi.PaddedPieceSize
for _, m := range template.Miners {
for _, s := range m.Sectors {
amt := s.Deal.PieceSize
verifNeeds[s.Deal.Client] += amt
sum += amt
}
}
verifier, err := address.NewIDAddress(80)
if err != nil {
return cid.Undef, err
}
vm, err := vm.NewVM(stateroot, 0, &fakeRand{}, cs.Blockstore(), &fakedSigSyscalls{cs.VMSys()})
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
}
_, err = doExecValue(ctx, vm, builtin.VerifiedRegistryActorAddr, RootVerifierAddr, types.NewInt(0), builtin.MethodsVerifiedRegistry.AddVerifier, mustEnc(&verifreg.AddVerifierParams{
Address: verifier,
Allowance: abi.NewStoragePower(int64(sum)), // eh, close enough
}))
if err != nil {
return cid.Undef, xerrors.Errorf("failed to failed to create verifier: %w", err)
}
for c, amt := range verifNeeds {
_, err := doExecValue(ctx, vm, builtin.VerifiedRegistryActorAddr, verifier, types.NewInt(0), builtin.MethodsVerifiedRegistry.AddVerifiedClient, mustEnc(&verifreg.AddVerifiedClientParams{
Address: c,
Allowance: abi.NewStoragePower(int64(amt)),
}))
if err != nil {
return cid.Undef, xerrors.Errorf("failed to add verified client: %w", err)
}
}
return vm.Flush(ctx)
}
func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys runtime.Syscalls, template genesis.Template) (*GenesisBootstrap, error) { func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys runtime.Syscalls, template genesis.Template) (*GenesisBootstrap, error) {
st, err := MakeInitialStateTree(ctx, bs, template) st, err := MakeInitialStateTree(ctx, bs, template)
if err != nil { if err != nil {
@@ -297,13 +231,6 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys runtime.Sys
// temp chainstore // temp chainstore
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys) cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys)
// Verify PreSealed Data
stateroot, err = VerifyPreSealedData(ctx, cs, stateroot, template)
if err != nil {
return nil, xerrors.Errorf("failed to verify presealed data: %w", err)
}
stateroot, err = SetupStorageMiners(ctx, cs, stateroot, template.Miners) stateroot, err = SetupStorageMiners(ctx, cs, stateroot, template.Miners)
if err != nil { if err != nil {
return nil, xerrors.Errorf("setup storage miners failed: %w", err) return nil, xerrors.Errorf("setup storage miners failed: %w", err)
+1 -5
View File
@@ -58,8 +58,6 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
for i, m := range miners { for i, m := range miners {
// Create miner through power actor // Create miner through power actor
i := i
m := m
spt, err := ffiwrapper.SealProofTypeFromSectorSize(m.SectorSize) spt, err := ffiwrapper.SealProofTypeFromSectorSize(m.SectorSize)
if err != nil { if err != nil {
@@ -71,7 +69,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
constructorParams := &power.CreateMinerParams{ constructorParams := &power.CreateMinerParams{
Owner: m.Worker, Owner: m.Worker,
Worker: m.Worker, Worker: m.Worker,
Peer: []byte(m.PeerId), Peer: m.PeerId,
SealProofType: spt, SealProofType: spt,
} }
@@ -132,7 +130,6 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
params := &market.PublishStorageDealsParams{} params := &market.PublishStorageDealsParams{}
for _, preseal := range m.Sectors { for _, preseal := range m.Sectors {
preseal.Deal.VerifiedDeal = true
params.Deals = append(params.Deals, market.ClientDealProposal{ params.Deals = append(params.Deals, market.ClientDealProposal{
Proposal: preseal.Deal, Proposal: preseal.Deal,
ClientSignature: crypto.Signature{Type: crypto.SigTypeBLS}, // TODO: do we want to sign these? Or do we want to fake signatures for genesis setup? ClientSignature: crypto.Signature{Type: crypto.SigTypeBLS}, // TODO: do we want to sign these? Or do we want to fake signatures for genesis setup?
@@ -156,7 +153,6 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
// Commit sectors // Commit sectors
for pi, preseal := range m.Sectors { for pi, preseal := range m.Sectors {
preseal := preseal
// TODO: Maybe check seal (Can just be snark inputs, doesn't go into the genesis file) // TODO: Maybe check seal (Can just be snark inputs, doesn't go into the genesis file)
// check deals, get dealWeight // check deals, get dealWeight
-5
View File
@@ -4,7 +4,6 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init" init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
@@ -46,10 +45,6 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi
} }
} }
if err := amap.Set(context.TODO(), string(RootVerifierAddr.Bytes()), 80); err != nil {
return nil, err
}
if err := amap.Flush(context.TODO()); err != nil { if err := amap.Flush(context.TODO()); err != nil {
return nil, err return nil, err
} }
+6 -21
View File
@@ -2,6 +2,7 @@ package genesis
import ( import (
"context" "context"
"crypto/rand"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/ipfs/go-hamt-ipld" "github.com/ipfs/go-hamt-ipld"
@@ -14,26 +15,6 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
var RootVerifierAddr address.Address
var RootVerifierID address.Address
func init() {
k, err := address.NewFromString("t3qfoulel6fy6gn3hjmbhpdpf6fs5aqjb5fkurhtwvgssizq4jey5nw4ptq5up6h7jk7frdvvobv52qzmgjinq")
if err != nil {
panic(err)
}
RootVerifierAddr = k
idk, err := address.NewFromString("t080")
if err != nil {
panic(err)
}
RootVerifierID = idk
}
func SetupVerifiedRegistryActor(bs bstore.Blockstore) (*types.Actor, error) { func SetupVerifiedRegistryActor(bs bstore.Blockstore) (*types.Actor, error) {
cst := cbor.NewCborStore(bs) cst := cbor.NewCborStore(bs)
@@ -42,7 +23,11 @@ func SetupVerifiedRegistryActor(bs bstore.Blockstore) (*types.Actor, error) {
return nil, err return nil, err
} }
sms := verifreg.ConstructState(h, RootVerifierID) var r [32]byte // TODO: grab from genesis template
_, _ = rand.Read(r[:])
k, _ := address.NewSecp256k1Address(r[:])
sms := verifreg.ConstructState(h, k)
stcid, err := cst.Put(context.TODO(), sms) stcid, err := cst.Put(context.TODO(), sms)
if err != nil { if err != nil {
+7 -49
View File
@@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"context" "context"
"errors" "errors"
"fmt"
"math" "math"
"sort" "sort"
"sync" "sync"
@@ -88,8 +87,6 @@ type MessagePool struct {
localMsgs datastore.Datastore localMsgs datastore.Datastore
netName dtypes.NetworkName netName dtypes.NetworkName
sigValCache *lru.TwoQueueCache
} }
type msgSet struct { type msgSet struct {
@@ -183,8 +180,6 @@ func (mpp *mpoolProvider) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error)
func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*MessagePool, error) { func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*MessagePool, error) {
cache, _ := lru.New2Q(build.BlsSignatureCacheSize) cache, _ := lru.New2Q(build.BlsSignatureCacheSize)
verifcache, _ := lru.New2Q(build.VerifSigCacheSize)
mp := &MessagePool{ mp := &MessagePool{
closer: make(chan struct{}), closer: make(chan struct{}),
repubTk: time.NewTicker(build.BlockDelay * 10 * time.Second), repubTk: time.NewTicker(build.BlockDelay * 10 * time.Second),
@@ -193,7 +188,6 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*Messa
minGasPrice: types.NewInt(0), minGasPrice: types.NewInt(0),
maxTxPoolSize: 5000, maxTxPoolSize: 5000,
blsSigCache: cache, blsSigCache: cache,
sigValCache: verifcache,
changes: lps.New(50), changes: lps.New(50),
localMsgs: namespace.Wrap(ds, datastore.NewKey(localMsgsDs)), localMsgs: namespace.Wrap(ds, datastore.NewKey(localMsgsDs)),
api: api, api: api,
@@ -319,6 +313,12 @@ func (mp *MessagePool) Push(m *types.SignedMessage) (cid.Cid, error) {
} }
func (mp *MessagePool) Add(m *types.SignedMessage) error { func (mp *MessagePool) Add(m *types.SignedMessage) error {
mp.curTsLk.Lock()
defer mp.curTsLk.Unlock()
return mp.addTs(m, mp.curTs)
}
func (mp *MessagePool) addTs(m *types.SignedMessage, curTs *types.TipSet) error {
// big messages are bad, anti DOS // big messages are bad, anti DOS
if m.Size() > 32*1024 { if m.Size() > 32*1024 {
return xerrors.Errorf("mpool message too large (%dB): %w", m.Size(), ErrMessageTooBig) return xerrors.Errorf("mpool message too large (%dB): %w", m.Size(), ErrMessageTooBig)
@@ -332,53 +332,11 @@ func (mp *MessagePool) Add(m *types.SignedMessage) error {
return ErrMessageValueTooHigh return ErrMessageValueTooHigh
} }
if err := mp.VerifyMsgSig(m); err != nil { if err := sigs.Verify(&m.Signature, m.Message.From, m.Message.Cid().Bytes()); err != nil {
log.Warnf("mpooladd signature verification failed: %s", err) log.Warnf("mpooladd signature verification failed: %s", err)
return err return err
} }
mp.curTsLk.Lock()
defer mp.curTsLk.Unlock()
return mp.addTs(m, mp.curTs)
}
func sigCacheKey(m *types.SignedMessage) (string, error) {
switch m.Signature.Type {
case crypto.SigTypeBLS:
if len(m.Signature.Data) < 90 {
return "", fmt.Errorf("bls signature too short")
}
return string(m.Cid().Bytes()) + string(m.Signature.Data[64:]), nil
case crypto.SigTypeSecp256k1:
return string(m.Cid().Bytes()), nil
default:
return "", xerrors.Errorf("unrecognized signature type: %d", m.Signature.Type)
}
}
func (mp *MessagePool) VerifyMsgSig(m *types.SignedMessage) error {
sck, err := sigCacheKey(m)
if err != nil {
return err
}
_, ok := mp.sigValCache.Get(sck)
if ok {
// already validated, great
return nil
}
if err := sigs.Verify(&m.Signature, m.Message.From, m.Message.Cid().Bytes()); err != nil {
return err
}
mp.sigValCache.Add(sck, struct{}{})
return nil
}
func (mp *MessagePool) addTs(m *types.SignedMessage, curTs *types.TipSet) error {
snonce, err := mp.getStateNonce(m.Message.From, curTs) snonce, err := mp.getStateNonce(m.Message.From, curTs)
if err != nil { if err != nil {
return xerrors.Errorf("failed to look up actor state nonce: %s: %w", err, ErrBroadcastAnyway) return xerrors.Errorf("failed to look up actor state nonce: %s: %w", err, ErrBroadcastAnyway)
+17 -17
View File
@@ -16,7 +16,7 @@ import (
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
) )
type testMpoolAPI struct { type testMpoolApi struct {
cb func(rev, app []*types.TipSet) error cb func(rev, app []*types.TipSet) error
bmsgs map[cid.Cid][]*types.SignedMessage bmsgs map[cid.Cid][]*types.SignedMessage
@@ -25,68 +25,68 @@ type testMpoolAPI struct {
tipsets []*types.TipSet tipsets []*types.TipSet
} }
func newTestMpoolAPI() *testMpoolAPI { func newTestMpoolApi() *testMpoolApi {
return &testMpoolAPI{ return &testMpoolApi{
bmsgs: make(map[cid.Cid][]*types.SignedMessage), bmsgs: make(map[cid.Cid][]*types.SignedMessage),
statenonce: make(map[address.Address]uint64), statenonce: make(map[address.Address]uint64),
} }
} }
func (tma *testMpoolAPI) applyBlock(t *testing.T, b *types.BlockHeader) { func (tma *testMpoolApi) applyBlock(t *testing.T, b *types.BlockHeader) {
t.Helper() t.Helper()
if err := tma.cb(nil, []*types.TipSet{mock.TipSet(b)}); err != nil { if err := tma.cb(nil, []*types.TipSet{mock.TipSet(b)}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func (tma *testMpoolAPI) revertBlock(t *testing.T, b *types.BlockHeader) { func (tma *testMpoolApi) revertBlock(t *testing.T, b *types.BlockHeader) {
t.Helper() t.Helper()
if err := tma.cb([]*types.TipSet{mock.TipSet(b)}, nil); err != nil { if err := tma.cb([]*types.TipSet{mock.TipSet(b)}, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func (tma *testMpoolAPI) setStateNonce(addr address.Address, v uint64) { func (tma *testMpoolApi) setStateNonce(addr address.Address, v uint64) {
tma.statenonce[addr] = v tma.statenonce[addr] = v
} }
func (tma *testMpoolAPI) setBlockMessages(h *types.BlockHeader, msgs ...*types.SignedMessage) { func (tma *testMpoolApi) setBlockMessages(h *types.BlockHeader, msgs ...*types.SignedMessage) {
tma.bmsgs[h.Cid()] = msgs tma.bmsgs[h.Cid()] = msgs
tma.tipsets = append(tma.tipsets, mock.TipSet(h)) tma.tipsets = append(tma.tipsets, mock.TipSet(h))
} }
func (tma *testMpoolAPI) SubscribeHeadChanges(cb func(rev, app []*types.TipSet) error) *types.TipSet { func (tma *testMpoolApi) SubscribeHeadChanges(cb func(rev, app []*types.TipSet) error) *types.TipSet {
tma.cb = cb tma.cb = cb
return nil return nil
} }
func (tma *testMpoolAPI) PutMessage(m types.ChainMsg) (cid.Cid, error) { func (tma *testMpoolApi) PutMessage(m types.ChainMsg) (cid.Cid, error) {
return cid.Undef, nil return cid.Undef, nil
} }
func (tma *testMpoolAPI) PubSubPublish(string, []byte) error { func (tma *testMpoolApi) PubSubPublish(string, []byte) error {
return nil return nil
} }
func (tma *testMpoolAPI) StateGetActor(addr address.Address, ts *types.TipSet) (*types.Actor, error) { func (tma *testMpoolApi) StateGetActor(addr address.Address, ts *types.TipSet) (*types.Actor, error) {
return &types.Actor{ return &types.Actor{
Nonce: tma.statenonce[addr], Nonce: tma.statenonce[addr],
Balance: types.NewInt(90000000), Balance: types.NewInt(90000000),
}, nil }, nil
} }
func (tma *testMpoolAPI) StateAccountKey(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) { func (tma *testMpoolApi) StateAccountKey(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
if addr.Protocol() != address.BLS && addr.Protocol() != address.SECP256K1 { if addr.Protocol() != address.BLS && addr.Protocol() != address.SECP256K1 {
return address.Undef, fmt.Errorf("given address was not a key addr") return address.Undef, fmt.Errorf("given address was not a key addr")
} }
return addr, nil return addr, nil
} }
func (tma *testMpoolAPI) MessagesForBlock(h *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error) { func (tma *testMpoolApi) MessagesForBlock(h *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error) {
return nil, tma.bmsgs[h.Cid()], nil return nil, tma.bmsgs[h.Cid()], nil
} }
func (tma *testMpoolAPI) MessagesForTipset(ts *types.TipSet) ([]types.ChainMsg, error) { func (tma *testMpoolApi) MessagesForTipset(ts *types.TipSet) ([]types.ChainMsg, error) {
if len(ts.Blocks()) != 1 { if len(ts.Blocks()) != 1 {
panic("cant deal with multiblock tipsets in this test") panic("cant deal with multiblock tipsets in this test")
} }
@@ -108,7 +108,7 @@ func (tma *testMpoolAPI) MessagesForTipset(ts *types.TipSet) ([]types.ChainMsg,
return out, nil return out, nil
} }
func (tma *testMpoolAPI) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error) { func (tma *testMpoolApi) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error) {
for _, ts := range tma.tipsets { for _, ts := range tma.tipsets {
if types.CidArrsEqual(tsk.Cids(), ts.Cids()) { if types.CidArrsEqual(tsk.Cids(), ts.Cids()) {
return ts, nil return ts, nil
@@ -138,7 +138,7 @@ func mustAdd(t *testing.T, mp *MessagePool, msg *types.SignedMessage) {
} }
func TestMessagePool(t *testing.T) { func TestMessagePool(t *testing.T) {
tma := newTestMpoolAPI() tma := newTestMpoolApi()
w, err := wallet.NewWallet(wallet.NewMemKeyStore()) w, err := wallet.NewWallet(wallet.NewMemKeyStore())
if err != nil { if err != nil {
@@ -179,7 +179,7 @@ func TestMessagePool(t *testing.T) {
} }
func TestRevertMessages(t *testing.T) { func TestRevertMessages(t *testing.T) {
tma := newTestMpoolAPI() tma := newTestMpoolApi()
w, err := wallet.NewWallet(wallet.NewMemKeyStore()) w, err := wallet.NewWallet(wallet.NewMemKeyStore())
if err != nil { if err != nil {
+2 -2
View File
@@ -21,7 +21,7 @@ import (
var log = logging.Logger("statetree") var log = logging.Logger("statetree")
// StateTree stores actors state by their ID. // Stores actors state by their ID.
type StateTree struct { type StateTree struct {
root *hamt.Node root *hamt.Node
Store cbor.IpldStore Store cbor.IpldStore
@@ -149,7 +149,7 @@ func (st *StateTree) SetActor(addr address.Address, act *types.Actor) error {
return nil return nil
} }
// LookupID gets the ID address of this actor's `addr` stored in the `InitActor`. // `LookupID` gets the ID address of this actor's `addr` stored in the `InitActor`.
func (st *StateTree) LookupID(addr address.Address) (address.Address, error) { func (st *StateTree) LookupID(addr address.Address) (address.Address, error) {
if addr.Protocol() == address.ID { if addr.Protocol() == address.ID {
return addr, nil return addr, nil
+1 -4
View File
@@ -255,15 +255,12 @@ func TestStateTreeConsistency(t *testing.T) {
} }
for i, a := range addrs { for i, a := range addrs {
err := st.SetActor(a, &types.Actor{ st.SetActor(a, &types.Actor{
Code: randomCid, Code: randomCid,
Head: randomCid, Head: randomCid,
Balance: types.NewInt(uint64(10000 + i)), Balance: types.NewInt(uint64(10000 + i)),
Nonce: uint64(1000 - i), Nonce: uint64(1000 - i),
}) })
if err != nil {
t.Fatalf("while setting actor: %+v", err)
}
} }
root, err := st.Flush(context.TODO()) root, err := st.Flush(context.TODO())
-2
View File
@@ -13,7 +13,6 @@ import (
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init" init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power" "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/runtime" "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@@ -41,7 +40,6 @@ func init() {
abi.RegisteredProof_StackedDRG2KiBSeal: {}, abi.RegisteredProof_StackedDRG2KiBSeal: {},
} }
power.ConsensusMinerMinPower = big.NewInt(2048) power.ConsensusMinerMinPower = big.NewInt(2048)
verifreg.MinVerifiedDealSize = big.NewInt(256)
} }
const testForkHeight = 40 const testForkHeight = 40
+13 -44
View File
@@ -326,7 +326,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
blkmsgs = append(blkmsgs, bm) blkmsgs = append(blkmsgs, bm)
} }
return sm.ApplyBlocks(ctx, pstate, blkmsgs, blks[0].Height, r, cb) return sm.ApplyBlocks(ctx, pstate, blkmsgs, abi.ChainEpoch(blks[0].Height), r, cb)
} }
func (sm *StateManager) parentState(ts *types.TipSet) cid.Cid { func (sm *StateManager) parentState(ts *types.TipSet) cid.Cid {
@@ -382,8 +382,8 @@ func (sm *StateManager) LoadActorState(ctx context.Context, a address.Address, o
cst := cbor.NewCborStore(sm.cs.Blockstore()) cst := cbor.NewCborStore(sm.cs.Blockstore())
if err := cst.Get(ctx, act.Head, out); err != nil { if err := cst.Get(ctx, act.Head, out); err != nil {
var r cbg.Deferred var r cbg.Deferred
_ = cst.Get(ctx, act.Head, &r) cst.Get(ctx, act.Head, &r)
log.Errorw("bad actor head", "error", err, "raw", r.Raw, "address", a) fmt.Printf("badhead %x\n", r.Raw)
return nil, err return nil, err
} }
@@ -405,8 +405,8 @@ func (sm *StateManager) LoadActorStateRaw(ctx context.Context, a address.Address
return act, nil return act, nil
} }
// ResolveToKeyAddress is similar to `vm.ResolveToKeyAddr` but does not allow `Actor` type of addresses. // Similar to `vm.ResolveToKeyAddr` but does not allow `Actor` type of addresses. Uses the `TipSet` `ts`
// Uses the `TipSet` `ts` to generate the VM state. // to generate the VM state.
func (sm *StateManager) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) { func (sm *StateManager) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
switch addr.Protocol() { switch addr.Protocol() {
case address.BLS, address.SECP256K1: case address.BLS, address.SECP256K1:
@@ -480,10 +480,7 @@ func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.T
return r, nil return r, nil
} }
// WaitForMessage blocks until a message appears on chain. It looks backwards in the chain to see if this has already func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid) (*types.TipSet, *types.MessageReceipt, error) {
// happened. It guarantees that the message has been on chain for at least confidence epochs without being reverted
// before returning.
func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confidence uint64) (*types.TipSet, *types.MessageReceipt, error) {
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
defer cancel() defer cancel()
@@ -531,11 +528,6 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confid
close(backSearchWait) close(backSearchWait)
}() }()
var candidateTs *types.TipSet
var candidateRcp *types.MessageReceipt
heightOfHead := head[0].Val.Height()
reverts := map[types.TipSetKey]bool{}
for { for {
select { select {
case notif, ok := <-tsub: case notif, ok := <-tsub:
@@ -545,44 +537,21 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confid
for _, val := range notif { for _, val := range notif {
switch val.Type { switch val.Type {
case store.HCRevert: case store.HCRevert:
if val.Val.Equals(candidateTs) { continue
candidateTs = nil
candidateRcp = nil
}
if backSearchWait != nil {
reverts[val.Val.Key()] = true
}
case store.HCApply: case store.HCApply:
if candidateTs != nil && val.Val.Height() >= candidateTs.Height()+abi.ChainEpoch(confidence) {
return candidateTs, candidateRcp, nil
}
r, err := sm.tipsetExecutedMessage(val.Val, mcid, msg.VMMessage()) r, err := sm.tipsetExecutedMessage(val.Val, mcid, msg.VMMessage())
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
if r != nil { if r != nil {
if confidence == 0 { return val.Val, r, nil
return val.Val, r, err
}
candidateTs = val.Val
candidateRcp = r
} }
heightOfHead = val.Val.Height()
} }
} }
case <-backSearchWait: case <-backSearchWait:
// check if we found the message in the chain and that is hasn't been reverted since we started searching if backTs != nil {
if backTs != nil && !reverts[backTs.Key()] { return backTs, backRcp, nil
// if head is at or past confidence interval, return immediately
if heightOfHead >= backTs.Height()+abi.ChainEpoch(confidence) {
return backTs, backRcp, nil
}
// wait for confidence interval
candidateTs = backTs
candidateRcp = backRcp
} }
reverts = nil
backSearchWait = nil backSearchWait = nil
case <-ctx.Done(): case <-ctx.Done():
return nil, nil, ctx.Err() return nil, nil, ctx.Err()
@@ -641,9 +610,9 @@ func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet
return nil, nil, err return nil, nil, err
} }
// we either have no messages from the sender, or the latest message we found has a lower nonce than the one being searched for, if act.Nonce < m.VMMessage().Nonce {
// either way, no reason to lookback, it ain't there // nonce on chain is before message nonce we're looking for, its
if act.Nonce == 0 || act.Nonce < m.VMMessage().Nonce { // not going to be here
return nil, nil, nil return nil, nil, nil
} }
+13 -31
View File
@@ -138,24 +138,6 @@ func PreCommitInfo(ctx context.Context, sm *StateManager, maddr address.Address,
return *i, nil return *i, nil
} }
func MinerSectorInfo(ctx context.Context, sm *StateManager, maddr address.Address, sid abi.SectorNumber, ts *types.TipSet) (*miner.SectorOnChainInfo, error) {
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
}
sectorInfo, ok, err := mas.GetSector(sm.cs.Store(ctx), sid)
if err != nil {
return nil, err
}
if !ok {
return nil, xerrors.New("sector not found")
}
return sectorInfo, nil
}
func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address, filter *abi.BitField, filterOut bool) ([]*api.ChainSectorInfo, error) { func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address, filter *abi.BitField, filterOut bool) ([]*api.ChainSectorInfo, error) {
var mas miner.State var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts) _, err := sm.LoadActorState(ctx, maddr, &mas, ts)
@@ -266,27 +248,27 @@ func GetMinerDeadlines(ctx context.Context, sm *StateManager, ts *types.TipSet,
return mas.LoadDeadlines(sm.cs.Store(ctx)) return mas.LoadDeadlines(sm.cs.Store(ctx))
} }
func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*abi.BitField, error) { func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]abi.SectorNumber, error) {
var mas miner.State var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts) _, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil { if err != nil {
return nil, xerrors.Errorf("(get faults) failed to load miner actor state: %w", err) return nil, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
} }
return mas.Faults, nil faults, err := mas.Faults.All(miner.SectorsMax)
}
func GetMinerRecoveries(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*abi.BitField, error) {
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil { if err != nil {
return nil, xerrors.Errorf("(get recoveries) failed to load miner actor state: %w", err) return nil, xerrors.Errorf("reading fault bit set: %w", err)
} }
return mas.Recoveries, nil out := make([]abi.SectorNumber, len(faults))
for i, fault := range faults {
out[i] = abi.SectorNumber(fault)
}
return out, nil
} }
func GetStorageDeal(ctx context.Context, sm *StateManager, dealID abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) { func GetStorageDeal(ctx context.Context, sm *StateManager, dealId abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) {
var state market.State var state market.State
if _, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts); err != nil { if _, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts); err != nil {
return nil, err return nil, err
@@ -298,7 +280,7 @@ func GetStorageDeal(ctx context.Context, sm *StateManager, dealID abi.DealID, ts
} }
var dp market.DealProposal var dp market.DealProposal
if err := da.Get(ctx, uint64(dealID), &dp); err != nil { if err := da.Get(ctx, uint64(dealId), &dp); err != nil {
return nil, err return nil, err
} }
@@ -307,7 +289,7 @@ func GetStorageDeal(ctx context.Context, sm *StateManager, dealID abi.DealID, ts
return nil, err return nil, err
} }
st, found, err := sa.Get(dealID) st, found, err := sa.Get(dealId)
if err != nil { if err != nil {
return nil, err return nil, err
} }
-161
View File
@@ -1,161 +0,0 @@
package store
import (
"context"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/abi"
lru "github.com/hashicorp/golang-lru"
"golang.org/x/xerrors"
)
type ChainIndex struct {
skipCache *lru.ARCCache
loadTipSet loadTipSetFunc
skipLength abi.ChainEpoch
}
type loadTipSetFunc func(types.TipSetKey) (*types.TipSet, error)
func NewChainIndex(lts loadTipSetFunc) *ChainIndex {
sc, _ := lru.NewARC(8192)
return &ChainIndex{
skipCache: sc,
loadTipSet: lts,
skipLength: 20,
}
}
type lbEntry struct {
ts *types.TipSet
parentHeight abi.ChainEpoch
targetHeight abi.ChainEpoch
target types.TipSetKey
}
func (ci *ChainIndex) GetTipsetByHeight(ctx context.Context, from *types.TipSet, to abi.ChainEpoch) (*types.TipSet, error) {
if from.Height()-to <= ci.skipLength {
return ci.walkBack(from, to)
}
rounded, err := ci.roundDown(from)
if err != nil {
return nil, err
}
cur := rounded.Key()
for {
cval, ok := ci.skipCache.Get(cur)
if !ok {
fc, err := ci.fillCache(cur)
if err != nil {
return nil, err
}
cval = fc
}
lbe := cval.(*lbEntry)
if lbe.ts.Height() == to || lbe.parentHeight < to {
return lbe.ts, nil
} else if to > lbe.targetHeight {
return ci.walkBack(lbe.ts, to)
}
cur = lbe.target
}
}
func (ci *ChainIndex) GetTipsetByHeightWithoutCache(from *types.TipSet, to abi.ChainEpoch) (*types.TipSet, error) {
return ci.walkBack(from, to)
}
func (ci *ChainIndex) fillCache(tsk types.TipSetKey) (*lbEntry, error) {
ts, err := ci.loadTipSet(tsk)
if err != nil {
return nil, err
}
if ts.Height() == 0 {
return &lbEntry{
ts: ts,
parentHeight: 0,
}, nil
}
// will either be equal to ts.Height, or at least > ts.Parent.Height()
rheight := ci.roundHeight(ts.Height())
parent, err := ci.loadTipSet(ts.Parents())
if err != nil {
return nil, err
}
rheight -= ci.skipLength
var skipTarget *types.TipSet
if parent.Height() < rheight {
skipTarget = parent
} else {
skipTarget, err = ci.walkBack(parent, rheight)
if err != nil {
return nil, xerrors.Errorf("fillCache walkback: %w", err)
}
}
lbe := &lbEntry{
ts: ts,
parentHeight: parent.Height(),
targetHeight: skipTarget.Height(),
target: skipTarget.Key(),
}
ci.skipCache.Add(tsk, lbe)
return lbe, nil
}
// floors to nearest skipLength multiple
func (ci *ChainIndex) roundHeight(h abi.ChainEpoch) abi.ChainEpoch {
return (h/ci.skipLength) * ci.skipLength
}
func (ci *ChainIndex) roundDown(ts *types.TipSet) (*types.TipSet, error) {
target := ci.roundHeight(ts.Height())
rounded, err := ci.walkBack(ts, target)
if err != nil {
return nil, err
}
return rounded, nil
}
func (ci *ChainIndex) walkBack(from *types.TipSet, to abi.ChainEpoch) (*types.TipSet, error) {
if to > from.Height() {
return nil, xerrors.Errorf("looking for tipset with height greater than start point")
}
if to == from.Height() {
return from, nil
}
ts := from
for {
pts, err := ci.loadTipSet(ts.Parents())
if err != nil {
return nil, err
}
if to > pts.Height() {
// in case pts is lower than the epoch we're looking for (null blocks)
// return a tipset above that height
return ts, nil
}
if to == pts.Height() {
return pts, nil
}
ts = pts
}
}
-80
View File
@@ -1,80 +0,0 @@
package store_test
import (
"bytes"
"context"
"testing"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types/mock"
"github.com/filecoin-project/specs-actors/actors/abi"
datastore "github.com/ipfs/go-datastore"
syncds "github.com/ipfs/go-datastore/sync"
blockstore "github.com/ipfs/go-ipfs-blockstore"
"github.com/stretchr/testify/assert"
)
func TestIndexSeeks(t *testing.T) {
cg, err := gen.NewGenerator()
if err != nil {
t.Fatal(err)
}
gencar, err := cg.GenesisCar()
if err != nil {
t.Fatal(err)
}
gen := cg.Genesis()
ctx := context.TODO()
nbs := blockstore.NewBlockstore(syncds.MutexWrap(datastore.NewMapDatastore()))
cs := store.NewChainStore(nbs, syncds.MutexWrap(datastore.NewMapDatastore()), nil)
_, err = cs.Import(bytes.NewReader(gencar))
if err != nil {
t.Fatal(err)
}
cur := mock.TipSet(gen)
if err := cs.PutTipSet(ctx, mock.TipSet(gen)); err != nil {
t.Fatal(err)
}
cs.SetGenesis(gen)
// Put 113 blocks from genesis
for i := 0; i < 113; i++ {
nextts := mock.TipSet(mock.MkBlock(cur, 1, 1))
if err := cs.PutTipSet(ctx, nextts); err != nil {
t.Fatal(err)
}
cur = nextts
}
// Put 50 null epochs + 1 block
skip := mock.MkBlock(cur, 1, 1)
skip.Height += 50
skipts := mock.TipSet(skip)
if err := cs.PutTipSet(ctx, skipts); err != nil {
t.Fatal(err)
}
ts, err := cs.GetTipsetByHeight(ctx, skip.Height-10, skipts, false)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, abi.ChainEpoch(164), ts.Height())
for i := 0; i <= 113; i++ {
ts3, err := cs.GetTipsetByHeight(ctx, abi.ChainEpoch(i), skipts, false)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, abi.ChainEpoch(i), ts3.Height())
}
}
+38 -54
View File
@@ -62,8 +62,6 @@ type ChainStore struct {
tstLk sync.Mutex tstLk sync.Mutex
tipsets map[abi.ChainEpoch][]cid.Cid tipsets map[abi.ChainEpoch][]cid.Cid
cindex *ChainIndex
reorgCh chan<- reorg reorgCh chan<- reorg
headChangeNotifs []func(rev, app []*types.TipSet) error headChangeNotifs []func(rev, app []*types.TipSet) error
@@ -86,10 +84,6 @@ func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls runtime.Sys
vmcalls: vmcalls, vmcalls: vmcalls,
} }
ci := NewChainIndex(cs.LoadTipSet)
cs.cindex = ci
cs.reorgCh = cs.reorgWorker(context.TODO()) cs.reorgCh = cs.reorgWorker(context.TODO())
hcnf := func(rev, app []*types.TipSet) error { hcnf := func(rev, app []*types.TipSet) error {
@@ -393,7 +387,7 @@ func (cs *ChainStore) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error) {
return ts, nil return ts, nil
} }
// IsAncestorOf returns true if 'a' is an ancestor of 'b' // returns true if 'a' is an ancestor of 'b'
func (cs *ChainStore) IsAncestorOf(a, b *types.TipSet) (bool, error) { func (cs *ChainStore) IsAncestorOf(a, b *types.TipSet) (bool, error) {
if b.Height() <= a.Height() { if b.Height() <= a.Height() {
return false, nil return false, nil
@@ -901,50 +895,39 @@ func DrawRandomness(rbase []byte, pers crypto.DomainSeparationTag, round abi.Cha
return nil, xerrors.Errorf("deriving randomness: %w", err) return nil, xerrors.Errorf("deriving randomness: %w", err)
} }
VRFDigest := blake2b.Sum256(rbase) VRFDigest := blake2b.Sum256(rbase)
_, err := h.Write(VRFDigest[:]) h.Write(VRFDigest[:])
if err != nil {
return nil, xerrors.Errorf("hashing VRFDigest: %w", err)
}
if err := binary.Write(h, binary.BigEndian, round); err != nil { if err := binary.Write(h, binary.BigEndian, round); err != nil {
return nil, xerrors.Errorf("deriving randomness: %w", err) return nil, xerrors.Errorf("deriving randomness: %w", err)
} }
_, err = h.Write(entropy) h.Write(entropy)
if err != nil {
return nil, xerrors.Errorf("hashing entropy: %w", err)
}
return h.Sum(nil), nil return h.Sum(nil), nil
} }
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) { func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) (out []byte, err error) {
_, span := trace.StartSpan(ctx, "store.GetRandomness") _, span := trace.StartSpan(ctx, "store.GetRandomness")
defer span.End() defer span.End()
span.AddAttributes(trace.Int64Attribute("round", int64(round))) span.AddAttributes(trace.Int64Attribute("round", int64(round)))
ts, err := cs.LoadTipSet(types.NewTipSetKey(blks...)) //defer func() {
if err != nil { //log.Infof("getRand %v %d %d %x -> %x", blks, pers, round, entropy, out)
return nil, err //}()
for {
nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
if err != nil {
return nil, err
}
mtb := nts.MinTicketBlock()
// if at (or just past -- for null epochs) appropriate epoch
// or at genesis (works for negative epochs)
if nts.Height() <= round || mtb.Height == 0 {
return DrawRandomness(nts.MinTicketBlock().Ticket.VRFProof, pers, round, entropy)
}
blks = mtb.Parents
} }
if round > ts.Height() {
return nil, xerrors.Errorf("cannot draw randomness from the future")
}
searchHeight := round
if searchHeight < 0 {
searchHeight = 0
}
randTs, err := cs.GetTipsetByHeight(ctx, searchHeight, ts, true)
if err != nil {
return nil, err
}
mtb := randTs.MinTicketBlock()
// if at (or just past -- for null epochs) appropriate epoch
// or at genesis (works for negative epochs)
return DrawRandomness(mtb.Ticket.VRFProof, pers, round, entropy)
} }
// GetTipsetByHeight returns the tipset on the chain behind 'ts' at the given // GetTipsetByHeight returns the tipset on the chain behind 'ts' at the given
@@ -957,7 +940,7 @@ func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h abi.ChainEpoch, t
} }
if h > ts.Height() { if h > ts.Height() {
return nil, xerrors.Errorf("looking for tipset with height greater than start point") return nil, xerrors.Errorf("looking for tipset with height less than start point")
} }
if h == ts.Height() { if h == ts.Height() {
@@ -968,24 +951,24 @@ func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h abi.ChainEpoch, t
log.Warnf("expensive call to GetTipsetByHeight, seeking %d levels", ts.Height()-h) log.Warnf("expensive call to GetTipsetByHeight, seeking %d levels", ts.Height()-h)
} }
lbts, err := cs.cindex.GetTipsetByHeight(ctx, ts, h) for {
if err != nil { pts, err := cs.LoadTipSet(ts.Parents())
return nil, err
}
if lbts.Height() < h {
log.Warnf("chain index returned the wrong tipset at height %d, using slow retrieval", h)
lbts, err = cs.cindex.GetTipsetByHeightWithoutCache(ts, h)
if err != nil { if err != nil {
return nil, err return nil, err
} }
}
if lbts.Height() == h || !prev { if h > pts.Height() {
return lbts, nil if prev {
} return pts, nil
}
return ts, nil
}
if h == pts.Height() {
return pts, nil
}
return cs.LoadTipSet(lbts.Parents()) ts = pts
}
} }
func recurseLinks(bs blockstore.Blockstore, root cid.Cid, in []cid.Cid) ([]cid.Cid, error) { func recurseLinks(bs blockstore.Blockstore, root cid.Cid, in []cid.Cid) ([]cid.Cid, error) {
@@ -1165,6 +1148,7 @@ func (cr *chainRand) GetRandomness(ctx context.Context, pers crypto.DomainSepara
func (cs *ChainStore) GetTipSetFromKey(tsk types.TipSetKey) (*types.TipSet, error) { func (cs *ChainStore) GetTipSetFromKey(tsk types.TipSetKey) (*types.TipSet, error) {
if tsk.IsEmpty() { if tsk.IsEmpty() {
return cs.GetHeaviestTipSet(), nil return cs.GetHeaviestTipSet(), nil
} else {
return cs.LoadTipSet(tsk)
} }
return cs.LoadTipSet(tsk)
} }
+1 -3
View File
@@ -12,7 +12,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/abi/big" "github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power" "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/gen"
@@ -26,7 +25,6 @@ func init() {
abi.RegisteredProof_StackedDRG2KiBSeal: {}, abi.RegisteredProof_StackedDRG2KiBSeal: {},
} }
power.ConsensusMinerMinPower = big.NewInt(2048) power.ConsensusMinerMinPower = big.NewInt(2048)
verifreg.MinVerifiedDealSize = big.NewInt(256)
} }
func BenchmarkGetRandomness(b *testing.B) { func BenchmarkGetRandomness(b *testing.B) {
@@ -55,7 +53,7 @@ func BenchmarkGetRandomness(b *testing.B) {
b.Fatal(err) b.Fatal(err)
} }
bds, err := lr.Datastore("/chain") bds, err := lr.Datastore("/blocks")
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
+17 -197
View File
@@ -1,45 +1,30 @@
package sub package sub
import ( import (
"bytes"
"context" "context"
"fmt"
"sync"
"time" "time"
"golang.org/x/xerrors" "golang.org/x/xerrors"
address "github.com/filecoin-project/go-address"
amt "github.com/filecoin-project/go-amt-ipld/v2"
miner "github.com/filecoin-project/specs-actors/actors/builtin/miner"
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore"
bstore "github.com/ipfs/go-ipfs-blockstore"
cbor "github.com/ipfs/go-ipld-cbor"
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"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub "github.com/libp2p/go-libp2p-pubsub"
cbg "github.com/whyrusleeping/cbor-gen"
"go.opencensus.io/stats" "go.opencensus.io/stats"
"go.opencensus.io/tag" "go.opencensus.io/tag"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain"
"github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/bufbstore"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/metrics"
) )
var log = logging.Logger("sub") var log = logging.Logger("sub")
func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *chain.Syncer, cmgr connmgr.ConnManager) { func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *chain.Syncer, cmgr connmgr.ConnManager, bv *BlockValidator) {
for { for {
msg, err := bsub.Next(ctx) msg, err := bsub.Next(ctx)
if err != nil { if err != nil {
@@ -57,7 +42,8 @@ func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *cha
return return
} }
src := msg.GetFrom() //nolint:golint
src := peer.ID(msg.GetFrom())
go func() { go func() {
log.Infof("New block over pubsub: %s", blk.Cid()) log.Infof("New block over pubsub: %s", blk.Cid())
@@ -66,13 +52,15 @@ func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *cha
log.Debug("about to fetch messages for block from pubsub") log.Debug("about to fetch messages for block from pubsub")
bmsgs, err := s.Bsync.FetchMessagesByCids(context.TODO(), blk.BlsMessages) bmsgs, err := s.Bsync.FetchMessagesByCids(context.TODO(), blk.BlsMessages)
if err != nil { if err != nil {
log.Errorf("failed to fetch all bls messages for block received over pubusb: %s; source: %s", err, src) log.Errorf("failed to fetch all bls messages for block received over pubusb: %s; flagging source %s", err, src)
bv.flagPeer(src)
return return
} }
smsgs, err := s.Bsync.FetchSignedMessagesByCids(context.TODO(), blk.SecpkMessages) smsgs, err := s.Bsync.FetchSignedMessagesByCids(context.TODO(), blk.SecpkMessages)
if err != nil { if err != nil {
log.Errorf("failed to fetch all secpk messages for block received over pubusb: %s; source: %s", err, src) log.Errorf("failed to fetch all secpk messages for block received over pubusb: %s; flagging source %s", err, src)
bv.flagPeer(src)
return return
} }
@@ -101,25 +89,15 @@ type BlockValidator struct {
recvBlocks *blockReceiptCache recvBlocks *blockReceiptCache
blacklist func(peer.ID) blacklist func(peer.ID)
// necessary for block validation
chain *store.ChainStore
stmgr *stmgr.StateManager
mx sync.Mutex
keycache map[string]address.Address
} }
func NewBlockValidator(chain *store.ChainStore, stmgr *stmgr.StateManager, blacklist func(peer.ID)) *BlockValidator { func NewBlockValidator(blacklist func(peer.ID)) *BlockValidator {
p, _ := lru.New2Q(4096) p, _ := lru.New2Q(4096)
return &BlockValidator{ return &BlockValidator{
peers: p, peers: p,
killThresh: 10, killThresh: 10,
blacklist: blacklist, blacklist: blacklist,
recvBlocks: newBlockReceiptCache(), recvBlocks: newBlockReceiptCache(),
chain: chain,
stmgr: stmgr,
keycache: make(map[string]address.Address),
} }
} }
@@ -142,191 +120,35 @@ func (bv *BlockValidator) flagPeer(p peer.ID) {
} }
func (bv *BlockValidator) Validate(ctx context.Context, pid peer.ID, msg *pubsub.Message) pubsub.ValidationResult { func (bv *BlockValidator) Validate(ctx context.Context, pid peer.ID, msg *pubsub.Message) pubsub.ValidationResult {
// track validation time
begin := time.Now()
defer func() {
end := time.Now()
log.Infof("block validation time: %s", end.Sub(begin))
}()
stats.Record(ctx, metrics.BlockReceived.M(1)) stats.Record(ctx, metrics.BlockReceived.M(1))
recordFailure := func(what string) {
ctx, _ = tag.New(ctx, tag.Insert(metrics.FailureType, what))
stats.Record(ctx, metrics.BlockValidationFailure.M(1))
bv.flagPeer(pid)
}
// make sure the block can be decoded
blk, err := types.DecodeBlockMsg(msg.GetData()) blk, err := types.DecodeBlockMsg(msg.GetData())
if err != nil { if err != nil {
log.Error("got invalid block over pubsub: ", err) log.Error("got invalid block over pubsub: ", err)
recordFailure("invalid") ctx, _ = tag.New(ctx, tag.Insert(metrics.FailureType, "invalid"))
stats.Record(ctx, metrics.BlockValidationFailure.M(1))
bv.flagPeer(pid)
return pubsub.ValidationReject return pubsub.ValidationReject
} }
// check the message limit constraints
if len(blk.BlsMessages)+len(blk.SecpkMessages) > build.BlockMessageLimit { if len(blk.BlsMessages)+len(blk.SecpkMessages) > build.BlockMessageLimit {
log.Warnf("received block with too many messages over pubsub") log.Warnf("received block with too many messages over pubsub")
recordFailure("too_many_messages") ctx, _ = tag.New(ctx, tag.Insert(metrics.FailureType, "too_many_messages"))
stats.Record(ctx, metrics.BlockValidationFailure.M(1))
bv.flagPeer(pid)
return pubsub.ValidationReject return pubsub.ValidationReject
} }
// make sure we have a signature
if blk.Header.BlockSig == nil {
log.Warnf("received block without a signature over pubsub")
recordFailure("missing_signature")
return pubsub.ValidationReject
}
// validate the block meta: the Message CID in the header must match the included messages
err = bv.validateMsgMeta(ctx, blk)
if err != nil {
log.Warnf("error validating message metadata: %s", err)
recordFailure("invalid_block_meta")
return pubsub.ValidationReject
}
// we want to ensure that it is a block from a known miner; we reject blocks from unknown miners
// to prevent spam attacks.
// the logic works as follows: we lookup the miner in the chain for its key.
// if we can find it then it's a known miner and we can validate the signature.
// if we can't find it, we check whether we are (near) synced in the chain.
// if we are not synced we cannot validate the block and we must ignore it.
// if we are synced and the miner is unknown, then the block is rejcected.
key, err := bv.getMinerWorkerKey(ctx, blk)
if err != nil {
if bv.isChainNearSynced() {
log.Warnf("received block message from unknown miner over pubsub; rejecting message")
recordFailure("unknown_miner")
return pubsub.ValidationReject
} else {
log.Warnf("cannot validate block message; unknown miner in unsynced chain")
return pubsub.ValidationIgnore
}
}
err = sigs.CheckBlockSignature(ctx, blk.Header, key)
if err != nil {
log.Errorf("block signature verification failed: %s", err)
recordFailure("signature_verification_failed")
return pubsub.ValidationReject
}
// it's a good block! make sure we've only seen it once
if bv.recvBlocks.add(blk.Header.Cid()) > 0 { if bv.recvBlocks.add(blk.Header.Cid()) > 0 {
// TODO: once these changes propagate to the network, we can consider // TODO: once these changes propagate to the network, we can consider
// dropping peers who send us the same block multiple times // dropping peers who send us the same block multiple times
return pubsub.ValidationIgnore return pubsub.ValidationIgnore
} }
// all good, accept the block
msg.ValidatorData = blk msg.ValidatorData = blk
stats.Record(ctx, metrics.BlockValidationSuccess.M(1)) stats.Record(ctx, metrics.BlockValidationSuccess.M(1))
return pubsub.ValidationAccept return pubsub.ValidationAccept
} }
func (bv *BlockValidator) isChainNearSynced() bool {
ts := bv.chain.GetHeaviestTipSet()
timestamp := ts.MinTimestamp()
now := time.Now().UnixNano()
cutoff := uint64(now) - uint64(6*time.Hour)
return timestamp > cutoff
}
func (bv *BlockValidator) validateMsgMeta(ctx context.Context, msg *types.BlockMsg) error {
var bcids, scids []cbg.CBORMarshaler
for _, m := range msg.BlsMessages {
c := cbg.CborCid(m)
bcids = append(bcids, &c)
}
for _, m := range msg.SecpkMessages {
c := cbg.CborCid(m)
scids = append(scids, &c)
}
// TODO there has to be a simpler way to do this without the blockstore dance
bs := cbor.NewCborStore(bstore.NewBlockstore(dstore.NewMapDatastore()))
bmroot, err := amt.FromArray(ctx, bs, bcids)
if err != nil {
return err
}
smroot, err := amt.FromArray(ctx, bs, scids)
if err != nil {
return err
}
mrcid, err := bs.Put(ctx, &types.MsgMeta{
BlsMessages: bmroot,
SecpkMessages: smroot,
})
if err != nil {
return err
}
if msg.Header.Messages != mrcid {
return fmt.Errorf("messages didn't match root cid in header")
}
return nil
}
func (bv *BlockValidator) getMinerWorkerKey(ctx context.Context, msg *types.BlockMsg) (address.Address, error) {
addr := msg.Header.Miner
bv.mx.Lock()
key, ok := bv.keycache[addr.String()]
bv.mx.Unlock()
if ok {
return key, nil
}
// TODO I have a feeling all this can be simplified by cleverer DI to use the API
ts := bv.chain.GetHeaviestTipSet()
st, _, err := bv.stmgr.TipSetState(ctx, ts)
if err != nil {
return address.Undef, err
}
buf := bufbstore.NewBufferedBstore(bv.chain.Blockstore())
cst := cbor.NewCborStore(buf)
state, err := state.LoadStateTree(cst, st)
if err != nil {
return address.Undef, err
}
act, err := state.GetActor(addr)
if err != nil {
return address.Undef, err
}
blk, err := bv.chain.Blockstore().Get(act.Head)
if err != nil {
return address.Undef, err
}
aso := blk.RawData()
var mst miner.State
err = mst.UnmarshalCBOR(bytes.NewReader(aso))
if err != nil {
return address.Undef, err
}
worker := mst.Info.Worker
key, err = bv.stmgr.ResolveToKeyAddress(ctx, worker, ts)
if err != nil {
return address.Undef, err
}
bv.mx.Lock()
bv.keycache[addr.String()] = key
bv.mx.Unlock()
return key, nil
}
type blockReceiptCache struct { type blockReceiptCache struct {
blocks *lru.TwoQueueCache blocks *lru.TwoQueueCache
} }
@@ -375,12 +197,10 @@ func (mv *MessageValidator) Validate(ctx context.Context, pid peer.ID, msg *pubs
tag.Insert(metrics.FailureType, "add"), tag.Insert(metrics.FailureType, "add"),
) )
stats.Record(ctx, metrics.MessageValidationFailure.M(1)) stats.Record(ctx, metrics.MessageValidationFailure.M(1))
switch { if xerrors.Is(err, messagepool.ErrBroadcastAnyway) {
case xerrors.Is(err, messagepool.ErrBroadcastAnyway): return pubsub.ValidationAccept
return pubsub.ValidationIgnore
default:
return pubsub.ValidationReject
} }
return pubsub.ValidationIgnore
} }
stats.Record(ctx, metrics.MessageValidationSuccess.M(1)) stats.Record(ctx, metrics.MessageValidationSuccess.M(1))
return pubsub.ValidationAccept return pubsub.ValidationAccept
+41 -9
View File
@@ -31,6 +31,7 @@ import (
amt "github.com/filecoin-project/go-amt-ipld/v2" amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/sector-storage/ffiwrapper" "github.com/filecoin-project/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/power" "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
@@ -526,7 +527,7 @@ func blockSanityChecks(h *types.BlockHeader) error {
return nil return nil
} }
// ValidateBlock should match up with 'Semantical Validation' in validation.md in the spec // Should match up with 'Semantical Validation' in validation.md in the spec
func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) error { func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) error {
ctx, span := trace.StartSpan(ctx, "validateBlock") ctx, span := trace.StartSpan(ctx, "validateBlock")
defer span.End() defer span.End()
@@ -665,7 +666,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
}) })
blockSigCheck := async.Err(func() error { blockSigCheck := async.Err(func() error {
if err := sigs.CheckBlockSignature(ctx, h, waddr); err != nil { if err := sigs.CheckBlockSignature(h, ctx, waddr); err != nil {
return xerrors.Errorf("check block signature failed: %w", err) return xerrors.Errorf("check block signature failed: %w", err)
} }
return nil return nil
@@ -841,13 +842,44 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
return xerrors.Errorf("failed to load base state tree: %w", err) return xerrors.Errorf("failed to load base state tree: %w", err)
} }
checkMsg := func(msg types.ChainMsg) error { checkMsg := func(m *types.Message) error {
m := msg.VMMessage()
// Phase 1: syntactic validation, as defined in the spec // Phase 1: syntactic validation, as defined in the spec
minGas := vm.PricelistByEpoch(baseTs.Height()).OnChainMessage(msg.ChainLength())
if err := m.ValidForBlockInclusion(minGas); err != nil { if m.Version != 0 {
return err return xerrors.New("'Version' unsupported")
}
if m.To == address.Undef {
return xerrors.New("'To' address cannot be empty")
}
if m.From == address.Undef {
return xerrors.New("'From' address cannot be empty")
}
if m.Value.LessThan(big.Zero()) {
return xerrors.New("'Value' field cannot be negative")
}
if m.Value.GreaterThan(types.TotalFilecoinInt) {
return xerrors.New("'Value' field cannot be greater than total filecoin supply")
}
if len(m.Params) != 0 && m.Method == 0 {
return xerrors.New("'Params' field should be empty if no 'Method' is being called")
}
if m.GasPrice.LessThan(big.Zero()) {
return xerrors.New("'GasPrice' field cannot be negative")
}
if m.GasLimit > build.BlockGasLimit {
return xerrors.New("'GasLimit' field cannot be greater than a block's gas limit")
}
// since prices might vary with time, this is technically semantic validation
if m.GasLimit < vm.PricelistByEpoch(baseTs.Height()).OnChainMessage(m.ChainLength()) {
return xerrors.New("'GasLimit' field cannot be less than the cost of storing a message on chain")
} }
// Phase 2: (Partial) semantic validation: // Phase 2: (Partial) semantic validation:
@@ -887,7 +919,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
var secpkCids []cbg.CBORMarshaler var secpkCids []cbg.CBORMarshaler
for i, m := range b.SecpkMessages { for i, m := range b.SecpkMessages {
if err := checkMsg(m); err != nil { if err := checkMsg(&m.Message); err != nil {
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err) return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
} }
+2 -4
View File
@@ -17,7 +17,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/abi/big" "github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power" "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
@@ -38,7 +37,6 @@ func init() {
abi.RegisteredProof_StackedDRG2KiBSeal: {}, abi.RegisteredProof_StackedDRG2KiBSeal: {},
} }
power.ConsensusMinerMinPower = big.NewInt(2048) power.ConsensusMinerMinPower = big.NewInt(2048)
verifreg.MinVerifiedDealSize = big.NewInt(256)
} }
const source = 0 const source = 0
@@ -417,7 +415,7 @@ func TestSyncBadTimestamp(t *testing.T) {
a1 := tu.mineOnBlock(base, 0, nil, false, true) a1 := tu.mineOnBlock(base, 0, nil, false, true)
tu.g.Timestamper = nil tu.g.Timestamper = nil
require.NoError(t, tu.g.ResyncBankerNonce(a1.TipSet())) tu.g.ResyncBankerNonce(a1.TipSet())
fmt.Println("After mine bad block!") fmt.Println("After mine bad block!")
tu.printHeads() tu.printHeads()
@@ -479,7 +477,7 @@ func TestSyncFork(t *testing.T) {
a := tu.mineOnBlock(a1, p1, []int{0}, true, false) a := tu.mineOnBlock(a1, p1, []int{0}, true, false)
a = tu.mineOnBlock(a, p1, []int{0}, true, false) a = tu.mineOnBlock(a, p1, []int{0}, true, false)
require.NoError(t, tu.g.ResyncBankerNonce(a1.TipSet())) tu.g.ResyncBankerNonce(a1.TipSet())
// chain B will now be heaviest // chain B will now be heaviest
b := tu.mineOnBlock(base, p2, []int{1}, true, false) b := tu.mineOnBlock(base, p2, []int{1}, true, false)
b = tu.mineOnBlock(b, p2, []int{1}, true, false) b = tu.mineOnBlock(b, p2, []int{1}, true, false)
+4 -15
View File
@@ -69,13 +69,10 @@ type BlockHeader struct {
BlockSig *crypto.Signature // 13 BlockSig *crypto.Signature // 13
ForkSignaling uint64 // 14 ForkSignaling uint64 // 14
// internal
validated bool // true if the signature has been validated
} }
func (blk *BlockHeader) ToStorageBlock() (block.Block, error) { func (b *BlockHeader) ToStorageBlock() (block.Block, error) {
data, err := blk.Serialize() data, err := b.Serialize()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -89,8 +86,8 @@ func (blk *BlockHeader) ToStorageBlock() (block.Block, error) {
return block.NewBlockWithCid(data, c) return block.NewBlockWithCid(data, c)
} }
func (blk *BlockHeader) Cid() cid.Cid { func (b *BlockHeader) Cid() cid.Cid {
sb, err := blk.ToStorageBlock() sb, err := b.ToStorageBlock()
if err != nil { if err != nil {
panic(err) // Not sure i'm entirely comfortable with this one, needs to be checked panic(err) // Not sure i'm entirely comfortable with this one, needs to be checked
} }
@@ -127,14 +124,6 @@ func (blk *BlockHeader) SigningBytes() ([]byte, error) {
return blkcopy.Serialize() return blkcopy.Serialize()
} }
func (blk *BlockHeader) SetValidated() {
blk.validated = true
}
func (blk *BlockHeader) IsValidated() bool {
return blk.validated
}
type MsgMeta struct { type MsgMeta struct {
BlsMessages cid.Cid BlsMessages cid.Cid
SecpkMessages cid.Cid SecpkMessages cid.Cid
+1 -60
View File
@@ -2,16 +2,13 @@ package types
import ( import (
"bytes" "bytes"
"encoding/hex"
"fmt" "fmt"
"reflect" "reflect"
"testing" "testing"
cid "github.com/ipfs/go-cid"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
cid "github.com/ipfs/go-cid"
) )
func testBlockHeader(t testing.TB) *BlockHeader { func testBlockHeader(t testing.TB) *BlockHeader {
@@ -66,62 +63,6 @@ func TestBlockHeaderSerialization(t *testing.T) {
} }
} }
func TestInteropBH(t *testing.T) {
newAddr, err := address.NewSecp256k1Address([]byte("address0"))
if err != nil {
t.Fatal(err)
}
mcid, err := cid.Parse("bafy2bzaceaxyj7xq27gc2747adjcirpxx52tt7owqx6z6kckun7tqivvoym4y")
if err != nil {
t.Fatal(err)
}
posts := []abi.PoStProof{
{abi.RegisteredProof_StackedDRG2KiBWinningPoSt, []byte{0x07}},
}
bh := &BlockHeader{
Miner: newAddr,
Ticket: &Ticket{[]byte{0x01, 0x02, 0x03}},
ElectionProof: &ElectionProof{[]byte{0x0a, 0x0b}},
BeaconEntries: []BeaconEntry{
{
Round: 5,
Data: []byte{0x0c},
//prevRound: 0,
},
},
Height: 2,
Messages: mcid,
ParentMessageReceipts: mcid,
Parents: []cid.Cid{mcid},
ParentWeight: NewInt(1000),
ForkSignaling: 3,
ParentStateRoot: mcid,
Timestamp: 1,
WinPoStProof: posts,
BlockSig: &crypto.Signature{
Type: crypto.SigTypeBLS,
Data: []byte{0x3},
},
BLSAggregate: &crypto.Signature{},
}
bhsb, err := bh.SigningBytes()
if err != nil {
t.Fatal(err)
}
// acquired from go-filecoin
gfc := "8f5501d04cb15021bf6bd003073d79e2238d4e61f1ad22814301020381420a0b818205410c818209410781d82a5827000171a0e402202f84fef0d7cc2d7f9f00d22445f7bf7539fdd685fd9f284aa37f3822b57619cc430003e802d82a5827000171a0e402202f84fef0d7cc2d7f9f00d22445f7bf7539fdd685fd9f284aa37f3822b57619ccd82a5827000171a0e402202f84fef0d7cc2d7f9f00d22445f7bf7539fdd685fd9f284aa37f3822b57619ccd82a5827000171a0e402202f84fef0d7cc2d7f9f00d22445f7bf7539fdd685fd9f284aa37f3822b57619cc410001f603"
if gfc != hex.EncodeToString(bhsb) {
t.Fatal("not equal!")
}
}
func BenchmarkBlockHeaderMarshal(b *testing.B) { func BenchmarkBlockHeaderMarshal(b *testing.B) {
bh := testBlockHeader(b) bh := testBlockHeader(b)
+3 -6
View File
@@ -1,12 +1,9 @@
package types package types
import "time"
type ExecutionResult struct { type ExecutionResult struct {
Msg *Message Msg *Message
MsgRct *MessageReceipt MsgRct *MessageReceipt
Error string Error string
Duration time.Duration
Subcalls []*ExecutionResult Subcalls []*ExecutionResult
} }
+10 -46
View File
@@ -4,13 +4,10 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
block "github.com/ipfs/go-block-format" block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash" "github.com/multiformats/go-multihash"
xerrors "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
) )
@@ -41,16 +38,20 @@ type Message struct {
Params []byte Params []byte
} }
func (m *Message) Caller() address.Address { func (t *Message) BlockMiner() address.Address {
return m.From panic("implement me")
} }
func (m *Message) Receiver() address.Address { func (t *Message) Caller() address.Address {
return m.To return t.From
} }
func (m *Message) ValueReceived() abi.TokenAmount { func (t *Message) Receiver() address.Address {
return m.Value return t.To
}
func (t *Message) ValueReceived() abi.TokenAmount {
return t.Value
} }
func DecodeMessage(b []byte) (*Message, error) { func DecodeMessage(b []byte) (*Message, error) {
@@ -120,40 +121,3 @@ func (m *Message) VMMessage() *Message {
func (m *Message) Equals(o *Message) bool { func (m *Message) Equals(o *Message) bool {
return m.Cid() == o.Cid() return m.Cid() == o.Cid()
} }
func (m *Message) ValidForBlockInclusion(minGas int64) error {
if m.Version != 0 {
return xerrors.New("'Version' unsupported")
}
if m.To == address.Undef {
return xerrors.New("'To' address cannot be empty")
}
if m.From == address.Undef {
return xerrors.New("'From' address cannot be empty")
}
if m.Value.LessThan(big.Zero()) {
return xerrors.New("'Value' field cannot be negative")
}
if m.Value.GreaterThan(TotalFilecoinInt) {
return xerrors.New("'Value' field cannot be greater than total filecoin supply")
}
if m.GasPrice.LessThan(big.Zero()) {
return xerrors.New("'GasPrice' field cannot be negative")
}
if m.GasLimit > build.BlockGasLimit {
return xerrors.New("'GasLimit' field cannot be greater than a block's gas limit")
}
// since prices might vary with time, this is technically semantic validation
if m.GasLimit < minGas {
return xerrors.New("'GasLimit' field cannot be less than the cost of storing a message on chain")
}
return nil
}
+1 -6
View File
@@ -49,11 +49,6 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
panic(err) panic(err)
} }
pstateRoot := c
if parents != nil {
pstateRoot = parents.Blocks()[0].ParentStateRoot
}
var pcids []cid.Cid var pcids []cid.Cid
var height abi.ChainEpoch var height abi.ChainEpoch
weight := types.NewInt(weightInc) weight := types.NewInt(weightInc)
@@ -77,7 +72,7 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
ParentWeight: weight, ParentWeight: weight,
Messages: c, Messages: c,
Height: height, Height: height,
ParentStateRoot: pstateRoot, ParentStateRoot: c,
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")}, BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")},
} }
} }
+8 -8
View File
@@ -9,12 +9,12 @@ import (
"github.com/multiformats/go-multihash" "github.com/multiformats/go-multihash"
) )
func (sm *SignedMessage) ToStorageBlock() (block.Block, error) { func (m *SignedMessage) ToStorageBlock() (block.Block, error) {
if sm.Signature.Type == crypto.SigTypeBLS { if m.Signature.Type == crypto.SigTypeBLS {
return sm.Message.ToStorageBlock() return m.Message.ToStorageBlock()
} }
data, err := sm.Serialize() data, err := m.Serialize()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -28,12 +28,12 @@ func (sm *SignedMessage) ToStorageBlock() (block.Block, error) {
return block.NewBlockWithCid(data, c) return block.NewBlockWithCid(data, c)
} }
func (sm *SignedMessage) Cid() cid.Cid { func (m *SignedMessage) Cid() cid.Cid {
if sm.Signature.Type == crypto.SigTypeBLS { if m.Signature.Type == crypto.SigTypeBLS {
return sm.Message.Cid() return m.Message.Cid()
} }
sb, err := sm.ToStorageBlock() sb, err := m.ToStorageBlock()
if err != nil { if err != nil {
panic(err) panic(err)
} }
+2 -2
View File
@@ -23,6 +23,8 @@ type TipSet struct {
height abi.ChainEpoch height abi.ChainEpoch
} }
// why didnt i just export the fields? Because the struct has methods with the
// same names already
type ExpTipSet struct { type ExpTipSet struct {
Cids []cid.Cid Cids []cid.Cid
Blocks []*BlockHeader Blocks []*BlockHeader
@@ -30,8 +32,6 @@ type ExpTipSet struct {
} }
func (ts *TipSet) MarshalJSON() ([]byte, error) { func (ts *TipSet) MarshalJSON() ([]byte, error) {
// why didnt i just export the fields? Because the struct has methods with the
// same names already
return json.Marshal(ExpTipSet{ return json.Marshal(ExpTipSet{
Cids: ts.cids, Cids: ts.cids,
Blocks: ts.blks, Blocks: ts.blks,
+3 -3
View File
@@ -61,9 +61,9 @@ func TestTipSetKey(t *testing.T) {
t.Run("JSON", func(t *testing.T) { t.Run("JSON", func(t *testing.T) {
k0 := NewTipSetKey() k0 := NewTipSetKey()
verifyJSON(t, "[]", k0) verifyJson(t, "[]", k0)
k3 := NewTipSetKey(c1, c2, c3) k3 := NewTipSetKey(c1, c2, c3)
verifyJSON(t, `[`+ verifyJson(t, `[`+
`{"/":"bafy2bzacecesrkxghscnq7vatble2hqdvwat6ed23vdu4vvo3uuggsoaya7ki"},`+ `{"/":"bafy2bzacecesrkxghscnq7vatble2hqdvwat6ed23vdu4vvo3uuggsoaya7ki"},`+
`{"/":"bafy2bzacebxfyh2fzoxrt6kcgc5dkaodpcstgwxxdizrww225vrhsizsfcg4g"},`+ `{"/":"bafy2bzacebxfyh2fzoxrt6kcgc5dkaodpcstgwxxdizrww225vrhsizsfcg4g"},`+
`{"/":"bafy2bzacedwviarjtjraqakob5pslltmuo5n3xev3nt5zylezofkbbv5jclyu"}`+ `{"/":"bafy2bzacedwviarjtjraqakob5pslltmuo5n3xev3nt5zylezofkbbv5jclyu"}`+
@@ -71,7 +71,7 @@ func TestTipSetKey(t *testing.T) {
}) })
} }
func verifyJSON(t *testing.T, expected string, k TipSetKey) { func verifyJson(t *testing.T, expected string, k TipSetKey) {
bytes, err := json.Marshal(k) bytes, err := json.Marshal(k)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, expected, string(bytes)) assert.Equal(t, expected, string(bytes))
+5 -6
View File
@@ -9,10 +9,10 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/puppet" "github.com/filecoin-project/specs-actors/actors/puppet"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
vtypes "github.com/filecoin-project/chain-validation/chain/types" vtypes "github.com/filecoin-project/chain-validation/chain/types"
vdrivers "github.com/filecoin-project/chain-validation/drivers"
vstate "github.com/filecoin-project/chain-validation/state" vstate "github.com/filecoin-project/chain-validation/state"
"github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/stmgr"
@@ -24,13 +24,12 @@ import (
// Applier applies messages to state trees and storage. // Applier applies messages to state trees and storage.
type Applier struct { type Applier struct {
stateWrapper *StateWrapper stateWrapper *StateWrapper
syscalls runtime.Syscalls
} }
var _ vstate.Applier = &Applier{} var _ vstate.Applier = &Applier{}
func NewApplier(sw *StateWrapper, syscalls runtime.Syscalls) *Applier { func NewApplier(sw *StateWrapper) *Applier {
return &Applier{sw, syscalls} return &Applier{sw}
} }
func (a *Applier) ApplyMessage(epoch abi.ChainEpoch, message *vtypes.Message) (vtypes.ApplyMessageResult, error) { func (a *Applier) ApplyMessage(epoch abi.ChainEpoch, message *vtypes.Message) (vtypes.ApplyMessageResult, error) {
@@ -66,7 +65,7 @@ func (a *Applier) ApplySignedMessage(epoch abi.ChainEpoch, msg *vtypes.SignedMes
} }
func (a *Applier) ApplyTipSetMessages(epoch abi.ChainEpoch, blocks []vtypes.BlockMessagesInfo, rnd vstate.RandomnessSource) (vtypes.ApplyTipSetResult, error) { func (a *Applier) ApplyTipSetMessages(epoch abi.ChainEpoch, blocks []vtypes.BlockMessagesInfo, rnd vstate.RandomnessSource) (vtypes.ApplyTipSetResult, error) {
cs := store.NewChainStore(a.stateWrapper.bs, a.stateWrapper.ds, a.syscalls) cs := store.NewChainStore(a.stateWrapper.bs, a.stateWrapper.ds, vdrivers.NewChainValidationSyscalls())
sm := stmgr.NewStateManager(cs) sm := stmgr.NewStateManager(cs)
var bms []stmgr.BlockMessages var bms []stmgr.BlockMessages
@@ -135,7 +134,7 @@ func (a *Applier) applyMessage(epoch abi.ChainEpoch, lm types.ChainMsg) (vtypes.
ctx := context.TODO() ctx := context.TODO()
base := a.stateWrapper.Root() base := a.stateWrapper.Root()
lotusVM, err := vm.NewVM(base, epoch, &vmRand{}, a.stateWrapper.bs, a.syscalls) lotusVM, err := vm.NewVM(base, epoch, &vmRand{}, a.stateWrapper.bs, vdrivers.NewChainValidationSyscalls())
// need to modify the VM invoker to add the puppet actor // need to modify the VM invoker to add the puppet actor
chainValInvoker := vm.NewInvoker() chainValInvoker := vm.NewInvoker()
chainValInvoker.Register(puppet.PuppetActorCodeID, puppet.Actor{}, puppet.State{}) chainValInvoker.Register(puppet.PuppetActorCodeID, puppet.Actor{}, puppet.State{})
+16 -3
View File
@@ -1,9 +1,11 @@
package validation package validation
import ( import (
"github.com/filecoin-project/specs-actors/actors/runtime" "context"
vstate "github.com/filecoin-project/chain-validation/state" vstate "github.com/filecoin-project/chain-validation/state"
"github.com/filecoin-project/specs-actors/actors/abi"
acrypto "github.com/filecoin-project/specs-actors/actors/crypto"
) )
type Factories struct { type Factories struct {
@@ -16,15 +18,26 @@ func NewFactories() *Factories {
return &Factories{} return &Factories{}
} }
func (f *Factories) NewStateAndApplier(syscalls runtime.Syscalls) (vstate.VMWrapper, vstate.Applier) { func (f *Factories) NewStateAndApplier() (vstate.VMWrapper, vstate.Applier) {
st := NewState() st := NewState()
return st, NewApplier(st, syscalls) return st, NewApplier(st)
} }
func (f *Factories) NewKeyManager() vstate.KeyManager { func (f *Factories) NewKeyManager() vstate.KeyManager {
return newKeyManager() return newKeyManager()
} }
type fakeRandSrc struct {
}
func (r fakeRandSrc) Randomness(_ context.Context, _ acrypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) (abi.Randomness, error) {
return abi.Randomness("sausages"), nil
}
func (f *Factories) NewRandomnessSource() vstate.RandomnessSource {
return &fakeRandSrc{}
}
func (f *Factories) NewValidationConfig() vstate.ValidationConfig { func (f *Factories) NewValidationConfig() vstate.ValidationConfig {
trackGas := true trackGas := true
checkExit := true checkExit := true
+2 -7
View File
@@ -7,7 +7,6 @@ import (
"os" "os"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@@ -174,18 +173,14 @@ func WriteJsonToFile(fname string, obj interface{}) error {
if err != nil { if err != nil {
return err return err
} }
defer fi.Close() //nolint:errcheck defer fi.Close()
out, err := json.MarshalIndent(obj, "", " ") out, err := json.MarshalIndent(obj, "", " ")
if err != nil { if err != nil {
return err return err
} }
_, err = fi.Write(out) fi.Write(out)
if err != nil {
return xerrors.Errorf("writing json: %w", err)
}
return nil return nil
} }
+1 -40
View File
@@ -1,15 +1,11 @@
package vectors package vectors
import ( import (
"bytes"
"encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/filecoin-project/lotus/chain/types"
) )
func LoadVector(t *testing.T, f string, out interface{}) { func LoadVector(t *testing.T, f string, out interface{}) {
@@ -46,40 +42,5 @@ func TestBlockHeaderVectors(t *testing.T) {
} }
func TestMessageSigningVectors(t *testing.T) { func TestMessageSigningVectors(t *testing.T) {
var msvs []MessageSigningVector // TODO:
LoadVector(t, "message_signing.json", &msvs)
for i, msv := range msvs {
smsg := &types.SignedMessage{
Message: *msv.Unsigned,
Signature: *msv.Signature,
}
if smsg.Cid().String() != msv.Cid {
t.Fatalf("cid of message in vector %d mismatches", i)
}
// TODO: check signature
}
}
func TestUnsignedMessageVectors(t *testing.T) {
var msvs []UnsignedMessageVector
LoadVector(t, "unsigned_messages.json", &msvs)
for i, msv := range msvs {
b, err := msv.Message.Serialize()
if err != nil {
t.Fatal(err)
}
dec, err := hex.DecodeString(msv.HexCbor)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(b, dec) {
t.Fatalf("serialization vector %d mismatches bytes", i)
}
}
} }
-6
View File
@@ -3,7 +3,6 @@ package vm
import ( import (
"fmt" "fmt"
"github.com/filecoin-project/go-address"
addr "github.com/filecoin-project/go-address" addr "github.com/filecoin-project/go-address"
"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"
@@ -144,8 +143,3 @@ func (ps pricedSyscalls) VerifyConsensusFault(h1 []byte, h2 []byte, extra []byte
ps.chargeGas(ps.pl.OnVerifyConsensusFault()) ps.chargeGas(ps.pl.OnVerifyConsensusFault())
return ps.under.VerifyConsensusFault(h1, h2, extra) return ps.under.VerifyConsensusFault(h1, h2, extra)
} }
func (ps pricedSyscalls) BatchVerifySeals(inp map[address.Address][]abi.SealVerifyInfo) (map[address.Address][]bool, error) {
ps.chargeGas(0) // TODO: this is only called by the cron actor. Should we even charge gas?
return ps.under.BatchVerifySeals(inp)
}
+8 -6
View File
@@ -32,7 +32,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/actors/aerrors"
) )
type Invoker struct { type invoker struct {
builtInCode map[cid.Cid]nativeCode builtInCode map[cid.Cid]nativeCode
builtInState map[cid.Cid]reflect.Type builtInState map[cid.Cid]reflect.Type
} }
@@ -40,8 +40,8 @@ type Invoker struct {
type invokeFunc func(rt runtime.Runtime, params []byte) ([]byte, aerrors.ActorError) type invokeFunc func(rt runtime.Runtime, params []byte) ([]byte, aerrors.ActorError)
type nativeCode []invokeFunc type nativeCode []invokeFunc
func NewInvoker() *Invoker { func NewInvoker() *invoker {
inv := &Invoker{ inv := &invoker{
builtInCode: make(map[cid.Cid]nativeCode), builtInCode: make(map[cid.Cid]nativeCode),
builtInState: make(map[cid.Cid]reflect.Type), builtInState: make(map[cid.Cid]reflect.Type),
} }
@@ -62,7 +62,7 @@ func NewInvoker() *Invoker {
return inv return inv
} }
func (inv *Invoker) Invoke(codeCid cid.Cid, rt runtime.Runtime, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) { func (inv *invoker) Invoke(codeCid cid.Cid, rt runtime.Runtime, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) {
code, ok := inv.builtInCode[codeCid] code, ok := inv.builtInCode[codeCid]
if !ok { if !ok {
@@ -76,7 +76,7 @@ func (inv *Invoker) Invoke(codeCid cid.Cid, rt runtime.Runtime, method abi.Metho
} }
func (inv *Invoker) Register(c cid.Cid, instance Invokee, state interface{}) { func (inv *invoker) Register(c cid.Cid, instance Invokee, state interface{}) {
code, err := inv.transform(instance) code, err := inv.transform(instance)
if err != nil { if err != nil {
panic(xerrors.Errorf("%s: %w", string(c.Hash()), err)) panic(xerrors.Errorf("%s: %w", string(c.Hash()), err))
@@ -89,7 +89,9 @@ type Invokee interface {
Exports() []interface{} Exports() []interface{}
} }
func (*Invoker) transform(instance Invokee) (nativeCode, error) { var tAError = reflect.TypeOf((*aerrors.ActorError)(nil)).Elem()
func (*invoker) transform(instance Invokee) (nativeCode, error) {
itype := reflect.TypeOf(instance) itype := reflect.TypeOf(instance)
exports := instance.Exports() exports := instance.Exports()
for i, m := range exports { for i, m := range exports {
+1 -1
View File
@@ -76,7 +76,7 @@ func (basicContract) InvokeSomething10(rt runtime.Runtime, params *basicParams)
} }
func TestInvokerBasic(t *testing.T) { func TestInvokerBasic(t *testing.T) {
inv := Invoker{} inv := invoker{}
code, err := inv.transform(basicContract{}) code, err := inv.transform(basicContract{})
assert.NoError(t, err) assert.NoError(t, err)
+1 -2
View File
@@ -2,7 +2,6 @@ package vm
import ( import (
"context" "context"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/specs-actors/actors/abi/big" "github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
@@ -28,7 +27,7 @@ func init() {
var EmptyObjectCid cid.Cid var EmptyObjectCid cid.Cid
// TryCreateAccountActor creates account actors from only BLS/SECP256K1 addresses. // Creates account actors from only BLS/SECP256K1 addresses.
func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, aerrors.ActorError) { func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, aerrors.ActorError) {
addrID, err := rt.state.RegisterNewAddress(addr) addrID, err := rt.state.RegisterNewAddress(addr)
if err != nil { if err != nil {
+55 -63
View File
@@ -5,8 +5,6 @@ import (
"context" "context"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"time"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big" "github.com/filecoin-project/specs-actors/actors/abi/big"
@@ -107,8 +105,8 @@ type notFoundErr interface {
IsNotFound() bool IsNotFound() bool
} }
func (rt *Runtime) Get(c cid.Cid, o vmr.CBORUnmarshaler) bool { func (rs *Runtime) Get(c cid.Cid, o vmr.CBORUnmarshaler) bool {
if err := rt.cst.Get(context.TODO(), c, o); err != nil { if err := rs.cst.Get(context.TODO(), c, o); err != nil {
var nfe notFoundErr var nfe notFoundErr
if xerrors.As(err, &nfe) && nfe.IsNotFound() { if xerrors.As(err, &nfe) && nfe.IsNotFound() {
if xerrors.As(err, new(cbor.SerializationError)) { if xerrors.As(err, new(cbor.SerializationError)) {
@@ -122,8 +120,8 @@ func (rt *Runtime) Get(c cid.Cid, o vmr.CBORUnmarshaler) bool {
return true return true
} }
func (rt *Runtime) Put(x vmr.CBORMarshaler) cid.Cid { func (rs *Runtime) Put(x vmr.CBORMarshaler) cid.Cid {
c, err := rt.cst.Put(context.TODO(), x) c, err := rs.cst.Put(context.TODO(), x)
if err != nil { if err != nil {
if xerrors.As(err, new(cbor.SerializationError)) { if xerrors.As(err, new(cbor.SerializationError)) {
panic(aerrors.Newf(exitcode.ErrSerialization, "failed to marshal cbor object %s", err)) panic(aerrors.Newf(exitcode.ErrSerialization, "failed to marshal cbor object %s", err))
@@ -135,7 +133,7 @@ func (rt *Runtime) Put(x vmr.CBORMarshaler) cid.Cid {
var _ vmr.Runtime = (*Runtime)(nil) var _ vmr.Runtime = (*Runtime)(nil)
func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) { func (rs *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
if ar, ok := r.(aerrors.ActorError); ok { if ar, ok := r.(aerrors.ActorError); ok {
@@ -150,8 +148,8 @@ func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.Act
ret := f() ret := f()
if !rt.callerValidated { if !rs.callerValidated {
rt.Abortf(exitcode.SysErrorIllegalActor, "Caller MUST be validated during method execution") rs.Abortf(exitcode.SysErrorIllegalActor, "Caller MUST be validated during method execution")
} }
switch ret := ret.(type) { switch ret := ret.(type) {
@@ -172,25 +170,25 @@ func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.Act
} }
} }
func (rt *Runtime) Message() vmr.Message { func (rs *Runtime) Message() vmr.Message {
return rt.vmsg return rs.vmsg
} }
func (rt *Runtime) ValidateImmediateCallerAcceptAny() { func (rs *Runtime) ValidateImmediateCallerAcceptAny() {
rt.abortIfAlreadyValidated() rs.abortIfAlreadyValidated()
return return
} }
func (rt *Runtime) CurrentBalance() abi.TokenAmount { func (rs *Runtime) CurrentBalance() abi.TokenAmount {
b, err := rt.GetBalance(rt.Message().Receiver()) b, err := rs.GetBalance(rs.Message().Receiver())
if err != nil { if err != nil {
rt.Abortf(err.RetCode(), "get current balance: %v", err) rs.Abortf(exitcode.ExitCode(err.RetCode()), "get current balance: %v", err)
} }
return b return b
} }
func (rt *Runtime) GetActorCodeCID(addr address.Address) (ret cid.Cid, ok bool) { func (rs *Runtime) GetActorCodeCID(addr address.Address) (ret cid.Cid, ok bool) {
act, err := rt.state.GetActor(addr) act, err := rs.state.GetActor(addr)
if err != nil { if err != nil {
if xerrors.Is(err, types.ErrActorNotFound) { if xerrors.Is(err, types.ErrActorNotFound) {
return cid.Undef, false return cid.Undef, false
@@ -210,8 +208,8 @@ func (rt *Runtime) GetRandomness(personalization crypto.DomainSeparationTag, ran
return res return res
} }
func (rt *Runtime) Store() vmr.Store { func (rs *Runtime) Store() vmr.Store {
return rt return rs
} }
func (rt *Runtime) NewActorAddress() address.Address { func (rt *Runtime) NewActorAddress() address.Address {
@@ -236,12 +234,12 @@ func (rt *Runtime) NewActorAddress() address.Address {
return addr return addr
} }
func (rt *Runtime) CreateActor(codeID cid.Cid, address address.Address) { func (rt *Runtime) CreateActor(codeId cid.Cid, address address.Address) {
if !builtin.IsBuiltinActor(codeID) { if !builtin.IsBuiltinActor(codeId) {
rt.Abortf(exitcode.SysErrorIllegalArgument, "Can only create built-in actors.") rt.Abortf(exitcode.SysErrorIllegalArgument, "Can only create built-in actors.")
} }
if builtin.IsSingletonActor(codeID) { if builtin.IsSingletonActor(codeId) {
rt.Abortf(exitcode.SysErrorIllegalArgument, "Can only have one instance of singleton actors.") rt.Abortf(exitcode.SysErrorIllegalArgument, "Can only have one instance of singleton actors.")
} }
@@ -253,7 +251,7 @@ func (rt *Runtime) CreateActor(codeID cid.Cid, address address.Address) {
rt.ChargeGas(rt.Pricelist().OnCreateActor()) rt.ChargeGas(rt.Pricelist().OnCreateActor())
err = rt.state.SetActor(address, &types.Actor{ err = rt.state.SetActor(address, &types.Actor{
Code: codeID, Code: codeId,
Head: EmptyObjectCid, Head: EmptyObjectCid,
Nonce: 0, Nonce: 0,
Balance: big.Zero(), Balance: big.Zero(),
@@ -273,9 +271,7 @@ func (rt *Runtime) DeleteActor(addr address.Address) {
panic(aerrors.Fatalf("failed to get actor: %s", err)) panic(aerrors.Fatalf("failed to get actor: %s", err))
} }
if !act.Balance.IsZero() { if !act.Balance.IsZero() {
if err := rt.vm.transfer(rt.Message().Receiver(), builtin.BurntFundsActorAddr, act.Balance); err != nil { rt.vm.transfer(rt.Message().Receiver(), builtin.BurntFundsActorAddr, act.Balance)
panic(aerrors.Fatalf("failed to transfer balance to burnt funds actor: %s", err))
}
} }
if err := rt.state.DeleteActor(rt.Message().Receiver()); err != nil { if err := rt.state.DeleteActor(rt.Message().Receiver()); err != nil {
@@ -283,12 +279,12 @@ func (rt *Runtime) DeleteActor(addr address.Address) {
} }
} }
func (rt *Runtime) Syscalls() vmr.Syscalls { func (rs *Runtime) Syscalls() vmr.Syscalls {
// TODO: Make sure this is wrapped in something that charges gas for each of the calls // TODO: Make sure this is wrapped in something that charges gas for each of the calls
return rt.sys return rs.sys
} }
func (rt *Runtime) StartSpan(name string) vmr.TraceSpan { func (rs *Runtime) StartSpan(name string) vmr.TraceSpan {
panic("implement me") panic("implement me")
} }
@@ -308,12 +304,12 @@ func (rt *Runtime) Context() context.Context {
return rt.ctx return rt.ctx
} }
func (rt *Runtime) Abortf(code exitcode.ExitCode, msg string, args ...interface{}) { func (rs *Runtime) Abortf(code exitcode.ExitCode, msg string, args ...interface{}) {
log.Error("Abortf: ", fmt.Sprintf(msg, args...)) log.Error("Abortf: ", fmt.Sprintf(msg, args...))
panic(aerrors.NewfSkip(2, code, msg, args...)) panic(aerrors.NewfSkip(2, code, msg, args...))
} }
func (rt *Runtime) AbortStateMsg(msg string) { func (rs *Runtime) AbortStateMsg(msg string) {
panic(aerrors.NewfSkip(3, 101, msg)) panic(aerrors.NewfSkip(3, 101, msg))
} }
@@ -331,8 +327,8 @@ func (rt *Runtime) ValidateImmediateCallerType(ts ...cid.Cid) {
rt.Abortf(exitcode.SysErrForbidden, "caller cid type %q was not one of %v", callerCid, ts) rt.Abortf(exitcode.SysErrForbidden, "caller cid type %q was not one of %v", callerCid, ts)
} }
func (rt *Runtime) CurrEpoch() abi.ChainEpoch { func (rs *Runtime) CurrEpoch() abi.ChainEpoch {
return rt.height return rs.height
} }
type dumbWrapperType struct { type dumbWrapperType struct {
@@ -343,32 +339,31 @@ func (dwt *dumbWrapperType) Into(um vmr.CBORUnmarshaler) error {
return um.UnmarshalCBOR(bytes.NewReader(dwt.val)) return um.UnmarshalCBOR(bytes.NewReader(dwt.val))
} }
func (rt *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMarshaler, value abi.TokenAmount) (vmr.SendReturn, exitcode.ExitCode) { func (rs *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMarshaler, value abi.TokenAmount) (vmr.SendReturn, exitcode.ExitCode) {
if !rt.allowInternal { if !rs.allowInternal {
rt.Abortf(exitcode.SysErrorIllegalActor, "runtime.Send() is currently disallowed") rs.Abortf(exitcode.SysErrorIllegalActor, "runtime.Send() is currently disallowed")
} }
var params []byte var params []byte
if m != nil { if m != nil {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if err := m.MarshalCBOR(buf); err != nil { if err := m.MarshalCBOR(buf); err != nil {
rt.Abortf(exitcode.SysErrInvalidParameters, "failed to marshal input parameters: %s", err) rs.Abortf(exitcode.SysErrInvalidParameters, "failed to marshal input parameters: %s", err)
} }
params = buf.Bytes() params = buf.Bytes()
} }
ret, err := rt.internalSend(rt.Message().Receiver(), to, method, value, params) ret, err := rs.internalSend(rs.Message().Receiver(), to, method, types.BigInt(value), params)
if err != nil { if err != nil {
if err.IsFatal() { if err.IsFatal() {
panic(err) panic(err)
} }
log.Warnf("vmctx send failed: to: %s, method: %d: ret: %d, err: %s", to, method, ret, err) log.Warnf("vmctx send failed: to: %s, method: %d: ret: %d, err: %s", to, method, ret, err)
return nil, err.RetCode() return nil, exitcode.ExitCode(err.RetCode())
} }
return &dumbWrapperType{ret}, 0 return &dumbWrapperType{ret}, 0
} }
func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum, value types.BigInt, params []byte) ([]byte, aerrors.ActorError) { func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum, value types.BigInt, params []byte) ([]byte, aerrors.ActorError) {
start := time.Now()
ctx, span := trace.StartSpan(rt.ctx, "vmc.Send") ctx, span := trace.StartSpan(rt.ctx, "vmc.Send")
defer span.End() defer span.End()
if span.IsRecordingEvents() { if span.IsRecordingEvents() {
@@ -402,15 +397,14 @@ func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum,
} }
mr := types.MessageReceipt{ mr := types.MessageReceipt{
ExitCode: aerrors.RetCode(errSend), ExitCode: exitcode.ExitCode(aerrors.RetCode(errSend)),
Return: ret, Return: ret,
GasUsed: 0, GasUsed: 0,
} }
er := types.ExecutionResult{ er := types.ExecutionResult{
Msg: msg, Msg: msg,
MsgRct: &mr, MsgRct: &mr,
Duration: time.Since(start),
} }
if errSend != nil { if errSend != nil {
@@ -425,48 +419,46 @@ func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum,
return ret, errSend return ret, errSend
} }
func (rt *Runtime) State() vmr.StateHandle { func (rs *Runtime) State() vmr.StateHandle {
return &shimStateHandle{rt: rt} return &shimStateHandle{rs: rs}
} }
type shimStateHandle struct { type shimStateHandle struct {
rt *Runtime rs *Runtime
} }
func (ssh *shimStateHandle) Create(obj vmr.CBORMarshaler) { func (ssh *shimStateHandle) Create(obj vmr.CBORMarshaler) {
c := ssh.rt.Put(obj) c := ssh.rs.Put(obj)
// TODO: handle error below ssh.rs.stateCommit(EmptyObjectCid, c)
ssh.rt.stateCommit(EmptyObjectCid, c)
} }
func (ssh *shimStateHandle) Readonly(obj vmr.CBORUnmarshaler) { func (ssh *shimStateHandle) Readonly(obj vmr.CBORUnmarshaler) {
act, err := ssh.rt.state.GetActor(ssh.rt.Message().Receiver()) act, err := ssh.rs.state.GetActor(ssh.rs.Message().Receiver())
if err != nil { if err != nil {
ssh.rt.Abortf(exitcode.SysErrorIllegalArgument, "failed to get actor for Readonly state: %s", err) ssh.rs.Abortf(exitcode.SysErrorIllegalArgument, "failed to get actor for Readonly state: %s", err)
} }
ssh.rt.Get(act.Head, obj) ssh.rs.Get(act.Head, obj)
} }
func (ssh *shimStateHandle) Transaction(obj vmr.CBORer, f func() interface{}) interface{} { func (ssh *shimStateHandle) Transaction(obj vmr.CBORer, f func() interface{}) interface{} {
if obj == nil { if obj == nil {
ssh.rt.Abortf(exitcode.SysErrorIllegalActor, "Must not pass nil to Transaction()") ssh.rs.Abortf(exitcode.SysErrorIllegalActor, "Must not pass nil to Transaction()")
} }
act, err := ssh.rt.state.GetActor(ssh.rt.Message().Receiver()) act, err := ssh.rs.state.GetActor(ssh.rs.Message().Receiver())
if err != nil { if err != nil {
ssh.rt.Abortf(exitcode.SysErrorIllegalActor, "failed to get actor for Transaction: %s", err) ssh.rs.Abortf(exitcode.SysErrorIllegalActor, "failed to get actor for Transaction: %s", err)
} }
baseState := act.Head baseState := act.Head
ssh.rt.Get(baseState, obj) ssh.rs.Get(baseState, obj)
ssh.rt.allowInternal = false ssh.rs.allowInternal = false
out := f() out := f()
ssh.rt.allowInternal = true ssh.rs.allowInternal = true
c := ssh.rt.Put(obj) c := ssh.rs.Put(obj)
// TODO: handle error below ssh.rs.stateCommit(baseState, c)
ssh.rt.stateCommit(baseState, c)
return out return out
} }
+17 -37
View File
@@ -4,8 +4,6 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
goruntime "runtime"
"sync"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@@ -185,7 +183,7 @@ func (ss *syscallShim) VerifyBlockSig(blk *types.BlockHeader) error {
return err return err
} }
if err := sigs.CheckBlockSignature(ss.ctx, blk, waddr); err != nil { if err := sigs.CheckBlockSignature(blk, ss.ctx, waddr); err != nil {
return err return err
} }
@@ -203,6 +201,20 @@ func (ss *syscallShim) VerifyPoSt(proof abi.WindowPoStVerifyInfo) error {
return nil return nil
} }
func cidToCommD(c cid.Cid) [32]byte {
b := c.Bytes()
var out [32]byte
copy(out[:], b[len(b)-32:])
return out
}
func cidToCommR(c cid.Cid) [32]byte {
b := c.Bytes()
var out [32]byte
copy(out[:], b[len(b)-32:])
return out
}
func (ss *syscallShim) VerifySeal(info abi.SealVerifyInfo) error { func (ss *syscallShim) VerifySeal(info abi.SealVerifyInfo) error {
//_, span := trace.StartSpan(ctx, "ValidatePoRep") //_, span := trace.StartSpan(ctx, "ValidatePoRep")
//defer span.End() //defer span.End()
@@ -213,10 +225,10 @@ func (ss *syscallShim) VerifySeal(info abi.SealVerifyInfo) error {
} }
ticket := []byte(info.Randomness) ticket := []byte(info.Randomness)
proof := info.Proof proof := []byte(info.OnChain.Proof)
seed := []byte(info.InteractiveRandomness) seed := []byte(info.InteractiveRandomness)
log.Debugf("Verif r:%x; d:%x; m:%s; t:%x; s:%x; N:%d; p:%x", info.SealedCID, info.UnsealedCID, miner, ticket, seed, info.SectorID.Number, proof) log.Debugf("Verif r:%x; d:%x; m:%s; t:%x; s:%x; N:%d; p:%x", info.OnChain.SealedCID, info.UnsealedCID, miner, ticket, seed, info.SectorID.Number, proof)
//func(ctx context.Context, maddr address.Address, ssize abi.SectorSize, commD, commR, ticket, proof, seed []byte, sectorID abi.SectorNumber) //func(ctx context.Context, maddr address.Address, ssize abi.SectorSize, commD, commR, ticket, proof, seed []byte, sectorID abi.SectorNumber)
ok, err := ss.verifier.VerifySeal(info) ok, err := ss.verifier.VerifySeal(info)
@@ -240,35 +252,3 @@ func (ss *syscallShim) VerifySignature(sig crypto.Signature, addr address.Addres
return sigs.Verify(&sig, kaddr, input) return sigs.Verify(&sig, kaddr, input)
} }
func (ss *syscallShim) BatchVerifySeals(inp map[address.Address][]abi.SealVerifyInfo) (map[address.Address][]bool, error) {
out := make(map[address.Address][]bool)
sema := make(chan struct{}, goruntime.NumCPU())
var wg sync.WaitGroup
for addr, seals := range inp {
results := make([]bool, len(seals))
out[addr] = results
for i, s := range seals {
wg.Add(1)
go func(ma address.Address, ix int, svi abi.SealVerifyInfo, res []bool) {
defer wg.Done()
sema <- struct{}{}
if err := ss.VerifySeal(svi); err != nil {
log.Warnw("seal verify in batch failed", "miner", ma, "index", ix, "err", err)
res[ix] = false
} else {
res[ix] = true
}
<-sema
}(addr, i, s, results)
}
}
wg.Wait()
return out, nil
}
-2
View File
@@ -41,7 +41,6 @@ func init() {
func TestChainValidationMessageSuite(t *testing.T) { func TestChainValidationMessageSuite(t *testing.T) {
f := factory.NewFactories() f := factory.NewFactories()
for _, testCase := range suites.MessageTestCases() { for _, testCase := range suites.MessageTestCases() {
testCase := testCase
if TestSuiteSkipper.Skip(testCase) { if TestSuiteSkipper.Skip(testCase) {
continue continue
} }
@@ -54,7 +53,6 @@ func TestChainValidationMessageSuite(t *testing.T) {
func TestChainValidationTipSetSuite(t *testing.T) { func TestChainValidationTipSetSuite(t *testing.T) {
f := factory.NewFactories() f := factory.NewFactories()
for _, testCase := range suites.TipSetTestCases() { for _, testCase := range suites.TipSetTestCases() {
testCase := testCase
if TestSuiteSkipper.Skip(testCase) { if TestSuiteSkipper.Skip(testCase) {
continue continue
} }
+17 -31
View File
@@ -131,7 +131,7 @@ type VM struct {
cst *cbor.BasicIpldStore cst *cbor.BasicIpldStore
buf *bufbstore.BufferedBS buf *bufbstore.BufferedBS
blockHeight abi.ChainEpoch blockHeight abi.ChainEpoch
inv *Invoker inv *invoker
rand Rand rand Rand
Syscalls runtime.Syscalls Syscalls runtime.Syscalls
@@ -210,7 +210,7 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
if types.BigCmp(msg.Value, types.NewInt(0)) != 0 { if types.BigCmp(msg.Value, types.NewInt(0)) != 0 {
if err := vm.transfer(msg.From, msg.To, msg.Value); err != nil { if err := vm.transfer(msg.From, msg.To, msg.Value); err != nil {
return nil, aerrors.Wrap(err, "failed to transfer funds"), nil return nil, aerrors.Absorb(err, 1, "failed to transfer funds"), nil
} }
} }
@@ -246,7 +246,7 @@ func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*Ap
ret, actorErr, rt := vm.send(ctx, msg, nil, 0) ret, actorErr, rt := vm.send(ctx, msg, nil, 0)
return &ApplyRet{ return &ApplyRet{
MessageReceipt: types.MessageReceipt{ MessageReceipt: types.MessageReceipt{
ExitCode: aerrors.RetCode(actorErr), ExitCode: exitcode.ExitCode(aerrors.RetCode(actorErr)),
Return: ret, Return: ret,
GasUsed: 0, GasUsed: 0,
}, },
@@ -415,7 +415,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
return &ApplyRet{ return &ApplyRet{
MessageReceipt: types.MessageReceipt{ MessageReceipt: types.MessageReceipt{
ExitCode: errcode, ExitCode: exitcode.ExitCode(errcode),
Return: ret, Return: ret,
GasUsed: gasUsed, GasUsed: gasUsed,
}, },
@@ -454,7 +454,7 @@ func (vm *VM) Flush(ctx context.Context) (cid.Cid, error) {
return root, nil return root, nil
} }
// MutateState usage: MutateState(ctx, idAddr, func(cst cbor.IpldStore, st *ActorStateType) error {...}) // vm.MutateState(idAddr, func(cst cbor.IpldStore, st *ActorStateType) error {...})
func (vm *VM) MutateState(ctx context.Context, addr address.Address, fn interface{}) error { func (vm *VM) MutateState(ctx context.Context, addr address.Address, fn interface{}) error {
act, err := vm.cstate.GetActor(addr) act, err := vm.cstate.GetActor(addr)
if err != nil { if err != nil {
@@ -591,7 +591,7 @@ func (vm *VM) Invoke(act *types.Actor, rt *Runtime, method abi.MethodNum, params
return ret, nil return ret, nil
} }
func (vm *VM) SetInvoker(i *Invoker) { func (vm *VM) SetInvoker(i *invoker) {
vm.inv = i vm.inv = i
} }
@@ -602,50 +602,36 @@ func (vm *VM) incrementNonce(addr address.Address) error {
}) })
} }
func (vm *VM) transfer(from, to address.Address, amt types.BigInt) aerrors.ActorError { func (vm *VM) transfer(from, to address.Address, amt types.BigInt) error {
if from == to { if from == to {
return nil return nil
} }
fromID, err := vm.cstate.LookupID(from)
if err != nil {
return aerrors.Fatalf("transfer failed when resolving sender address: %s", err)
}
toID, err := vm.cstate.LookupID(to)
if err != nil {
return aerrors.Fatalf("transfer failed when resolving receiver address: %s", err)
}
if fromID == toID {
return nil
}
if amt.LessThan(types.NewInt(0)) { if amt.LessThan(types.NewInt(0)) {
return aerrors.Newf(exitcode.SysErrForbidden, "attempted to transfer negative value: %s", amt) return xerrors.Errorf("attempted to transfer negative value")
} }
f, err := vm.cstate.GetActor(fromID) f, err := vm.cstate.GetActor(from)
if err != nil { if err != nil {
return aerrors.Fatalf("transfer failed when retrieving sender actor: %s", err) return xerrors.Errorf("transfer failed when retrieving sender actor")
} }
t, err := vm.cstate.GetActor(toID) t, err := vm.cstate.GetActor(to)
if err != nil { if err != nil {
return aerrors.Fatalf("transfer failed when retrieving receiver actor: %s", err) return xerrors.Errorf("transfer failed when retrieving receiver actor")
} }
if err := deductFunds(f, amt); err != nil { if err := deductFunds(f, amt); err != nil {
return aerrors.Newf(exitcode.SysErrInsufficientFunds, "transfer failed when deducting funds: %s", err) return err
} }
depositFunds(t, amt) depositFunds(t, amt)
if err := vm.cstate.SetActor(fromID, f); err != nil { if err := vm.cstate.SetActor(from, f); err != nil {
return aerrors.Fatalf("transfer failed when setting receiver actor: %s", err) return err
} }
if err := vm.cstate.SetActor(toID, t); err != nil { if err := vm.cstate.SetActor(to, t); err != nil {
return aerrors.Fatalf("transfer failed when setting sender actor: %s", err) return err
} }
return nil return nil
+6 -24
View File
@@ -12,8 +12,8 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" // enable bls signatures _ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" // enable secp signatures _ "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/lib/sigs" "github.com/filecoin-project/lotus/lib/sigs"
@@ -22,11 +22,10 @@ import (
var log = logging.Logger("wallet") var log = logging.Logger("wallet")
const ( const (
KNamePrefix = "wallet-" KNamePrefix = "wallet-"
KTrashPrefix = "trash-" KDefault = "default"
KDefault = "default" KTBLS = "bls"
KTBLS = "bls" KTSecp256k1 = "secp256k1"
KTSecp256k1 = "secp256k1"
) )
type Wallet struct { type Wallet struct {
@@ -231,23 +230,6 @@ func (w *Wallet) HasKey(addr address.Address) (bool, error) {
return k != nil, nil return k != nil, nil
} }
func (w *Wallet) DeleteKey(addr address.Address) error {
k, err := w.findKey(addr)
if err != nil {
return xerrors.Errorf("failed to delete key %s : %w", addr, err)
}
if err := w.keystore.Put(KTrashPrefix+k.Address.String(), k.KeyInfo); err != nil {
return xerrors.Errorf("failed to mark key %s as trashed: %w", addr, err)
}
if err := w.keystore.Delete(KNamePrefix + k.Address.String()); err != nil {
return xerrors.Errorf("failed to delete key %s: %w", addr, err)
}
return nil
}
type Key struct { type Key struct {
types.KeyInfo types.KeyInfo
+3 -5
View File
@@ -3,10 +3,8 @@ package cli
import ( import (
"fmt" "fmt"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/go-jsonrpc/auth"
"github.com/filecoin-project/lotus/api/apistruct" "github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/node/repo"
@@ -47,7 +45,7 @@ var authCreateAdminToken = &cli.Command{
perm := cctx.String("perm") perm := cctx.String("perm")
idx := 0 idx := 0
for i, p := range apistruct.AllPermissions { for i, p := range apistruct.AllPermissions {
if auth.Permission(perm) == p { if perm == p {
idx = i + 1 idx = i + 1
} }
} }
@@ -95,7 +93,7 @@ var authApiInfoToken = &cli.Command{
perm := cctx.String("perm") perm := cctx.String("perm")
idx := 0 idx := 0
for i, p := range apistruct.AllPermissions { for i, p := range apistruct.AllPermissions {
if auth.Permission(perm) == p { if perm == p {
idx = i + 1 idx = i + 1
} }
} }
+3 -16
View File
@@ -18,14 +18,13 @@ import (
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/account" "github.com/filecoin-project/specs-actors/actors/builtin/account"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power" "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
"github.com/urfave/cli/v2"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
@@ -442,8 +441,7 @@ var chainGetCmd = &cli.Command{
- /ipfs/[cid]/@Hi:123 - get varint elem 123 from hamt - /ipfs/[cid]/@Hi:123 - get varint elem 123 from hamt
- /ipfs/[cid]/@Hu:123 - get uvarint elem 123 from hamt - /ipfs/[cid]/@Hu:123 - get uvarint elem 123 from hamt
- /ipfs/[cid]/@Ha:t01 - get element under Addr(t01).Bytes - /ipfs/[cid]/@Ha:t01 - get element under Addr(t01).Bytes
- /ipfs/[cid]/@A:10 - get 10th amt element - /ipfs/[cid]/@A:10 - get 10th amt element
- .../@Ha:t01/@state - get pretty map-based actor state
List of --as-type types: List of --as-type types:
- raw - raw
@@ -523,12 +521,6 @@ var chainGetCmd = &cli.Command{
cbu = new(power.CronEvent) cbu = new(power.CronEvent)
case "account-state": case "account-state":
cbu = new(account.State) cbu = new(account.State)
case "miner-state":
cbu = new(miner.State)
case "power-state":
cbu = new(power.State)
case "market-state":
cbu = new(market.State)
default: default:
return fmt.Errorf("unknown type: %q", t) return fmt.Errorf("unknown type: %q", t)
} }
@@ -805,12 +797,7 @@ var chainExportCmd = &cli.Command{
if err != nil { if err != nil {
return err return err
} }
defer func() { defer fi.Close()
err := fi.Close()
if err != nil {
fmt.Printf("error closing output file: %+v", err)
}
}()
ts, err := LoadTipSet(ctx, cctx, api) ts, err := LoadTipSet(ctx, cctx, api)
if err != nil { if err != nil {
+18 -89
View File
@@ -8,11 +8,9 @@ import (
"text/tabwriter" "text/tabwriter"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/ipfs/go-cidutil/cidenc"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
"github.com/multiformats/go-multibase"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-fil-markets/storagemarket"
@@ -23,32 +21,6 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
var CidBaseFlag = cli.StringFlag{
Name: "cid-base",
Hidden: true,
Value: "base32",
Usage: "Multibase encoding used for version 1 CIDs in output.",
DefaultText: "base32",
}
// GetCidEncoder returns an encoder using the `cid-base` flag if provided, or
// the default (Base32) encoder if not.
func GetCidEncoder(cctx *cli.Context) (cidenc.Encoder, error) {
val := cctx.String("cid-base")
e := cidenc.Encoder{Base: multibase.MustNewEncoder(multibase.Base32)}
if val != "" {
var err error
e.Base, err = multibase.EncoderByName(val)
if err != nil {
return e, err
}
}
return e, nil
}
var clientCmd = &cli.Command{ var clientCmd = &cli.Command{
Name: "client", Name: "client",
Usage: "Make deals, store data, retrieve data", Usage: "Make deals, store data, retrieve data",
@@ -74,7 +46,6 @@ var clientImportCmd = &cli.Command{
Name: "car", Name: "car",
Usage: "import from a car file instead of a regular file", Usage: "import from a car file instead of a regular file",
}, },
&CidBaseFlag,
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
@@ -96,14 +67,7 @@ var clientImportCmd = &cli.Command{
if err != nil { if err != nil {
return err return err
} }
fmt.Println(c.String())
encoder, err := GetCidEncoder(cctx)
if err != nil {
return err
}
fmt.Println(encoder.Encode(c))
return nil return nil
}, },
} }
@@ -112,9 +76,6 @@ var clientCommPCmd = &cli.Command{
Name: "commP", Name: "commP",
Usage: "calculate the piece-cid (commP) of a CAR file", Usage: "calculate the piece-cid (commP) of a CAR file",
ArgsUsage: "[inputFile minerAddress]", ArgsUsage: "[inputFile minerAddress]",
Flags: []cli.Flag{
&CidBaseFlag,
},
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
@@ -133,16 +94,11 @@ var clientCommPCmd = &cli.Command{
} }
ret, err := api.ClientCalcCommP(ctx, cctx.Args().Get(0), miner) ret, err := api.ClientCalcCommP(ctx, cctx.Args().Get(0), miner)
if err != nil { if err != nil {
return err return err
} }
fmt.Println("CID: ", ret.Root)
encoder, err := GetCidEncoder(cctx)
if err != nil {
return err
}
fmt.Println("CID: ", encoder.Encode(ret.Root))
fmt.Println("Piece size: ", ret.Size) fmt.Println("Piece size: ", ret.Size)
return nil return nil
}, },
@@ -181,9 +137,6 @@ var clientCarGenCmd = &cli.Command{
var clientLocalCmd = &cli.Command{ var clientLocalCmd = &cli.Command{
Name: "local", Name: "local",
Usage: "List locally imported data", Usage: "List locally imported data",
Flags: []cli.Flag{
&CidBaseFlag,
},
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
@@ -196,14 +149,8 @@ var clientLocalCmd = &cli.Command{
if err != nil { if err != nil {
return err return err
} }
encoder, err := GetCidEncoder(cctx)
if err != nil {
return err
}
for _, v := range list { for _, v := range list {
fmt.Printf("%s %s %d %s\n", encoder.Encode(v.Key), v.FilePath, v.Size, v.Status) fmt.Printf("%s %s %d %s\n", v.Key, v.FilePath, v.Size, v.Status)
} }
return nil return nil
}, },
@@ -231,7 +178,6 @@ var clientDealCmd = &cli.Command{
Usage: "specify the epoch that the deal should start at", Usage: "specify the epoch that the deal should start at",
Value: -1, Value: -1,
}, },
&CidBaseFlag,
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
@@ -317,13 +263,7 @@ var clientDealCmd = &cli.Command{
return err return err
} }
encoder, err := GetCidEncoder(cctx) fmt.Println(proposal)
if err != nil {
return err
}
fmt.Println(encoder.Encode(*proposal))
return nil return nil
}, },
} }
@@ -444,7 +384,7 @@ var clientRetrieveCmd = &cli.Command{
return nil return nil
} }
ref := &lapi.FileRef{ ref := lapi.FileRef{
Path: cctx.Args().Get(1), Path: cctx.Args().Get(1),
IsCAR: cctx.Bool("car"), IsCAR: cctx.Bool("car"),
} }
@@ -506,11 +446,11 @@ var clientQueryAskCmd = &cli.Command{
return xerrors.Errorf("failed to get peerID for miner: %w", err) return xerrors.Errorf("failed to get peerID for miner: %w", err)
} }
if peer.ID(mi.PeerId) == peer.ID("SETME") { if mi.PeerId == peer.ID("SETME") {
return fmt.Errorf("the miner hasn't initialized yet") return fmt.Errorf("the miner hasn't initialized yet")
} }
pid = peer.ID(mi.PeerId) pid = mi.PeerId
} }
ask, err := api.ClientQueryAsk(ctx, pid, maddr) ask, err := api.ClientQueryAsk(ctx, pid, maddr)
@@ -561,27 +501,16 @@ var clientListDeals = &cli.Command{
} }
var deals []deal var deals []deal
for _, v := range localDeals { for idx := range localDeals {
if v.DealID == 0 { onChain, err := api.StateMarketStorageDeal(ctx, localDeals[idx].DealID, head.Key())
deals = append(deals, deal{ if err != nil {
LocalDeal: v, return err
OnChainDealState: market.DealState{
SectorStartEpoch: -1,
LastUpdatedEpoch: -1,
SlashEpoch: -1,
},
})
} else {
onChain, err := api.StateMarketStorageDeal(ctx, v.DealID, head.Key())
if err != nil {
return err
}
deals = append(deals, deal{
LocalDeal: v,
OnChainDealState: onChain.State,
})
} }
deals = append(deals, deal{
LocalDeal: localDeals[idx],
OnChainDealState: onChain.State,
})
} }
w := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0) w := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0)
+19 -25
View File
@@ -13,13 +13,12 @@ import (
"github.com/mitchellh/go-homedir" "github.com/mitchellh/go-homedir"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr-net" manet "github.com/multiformats/go-multiaddr-net"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/client" "github.com/filecoin-project/lotus/api/client"
"github.com/filecoin-project/lotus/lib/jsonrpc"
"github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/node/repo"
) )
@@ -211,33 +210,28 @@ func ReqContext(cctx *cli.Context) context.Context {
} }
var CommonCommands = []*cli.Command{ var CommonCommands = []*cli.Command{
netCmd,
authCmd, authCmd,
fetchParamCmd,
netCmd,
versionCmd,
logCmd, logCmd,
waitApiCmd, waitApiCmd,
fetchParamCmd,
versionCmd,
} }
var Commands = []*cli.Command{ var Commands = []*cli.Command{
withCategory("basic", sendCmd), authCmd,
withCategory("basic", walletCmd), chainCmd,
withCategory("basic", clientCmd), clientCmd,
withCategory("basic", multisigCmd), fetchParamCmd,
withCategory("basic", paychCmd), mpoolCmd,
withCategory("developer", authCmd), multisigCmd,
withCategory("developer", mpoolCmd), netCmd,
withCategory("developer", stateCmd), paychCmd,
withCategory("developer", chainCmd), sendCmd,
withCategory("developer", logCmd), stateCmd,
withCategory("developer", waitApiCmd), syncCmd,
withCategory("developer", fetchParamCmd),
withCategory("network", netCmd),
withCategory("network", syncCmd),
versionCmd, versionCmd,
} walletCmd,
logCmd,
func withCategory(cat string, cmd *cli.Command) *cli.Command { waitApiCmd,
cmd.Category = cat
return cmd
} }
+1 -1
View File
@@ -3,8 +3,8 @@ package cli
import ( import (
"fmt" "fmt"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
) )
var logCmd = &cli.Command{ var logCmd = &cli.Command{
+1 -1
View File
@@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"sort" "sort"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
+5 -9
View File
@@ -17,13 +17,12 @@ import (
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
"github.com/ipfs/go-hamt-ipld" "github.com/ipfs/go-hamt-ipld"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"github.com/urfave/cli/v2"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apibstore" "github.com/filecoin-project/lotus/api/apibstore"
"github.com/filecoin-project/lotus/build"
types "github.com/filecoin-project/lotus/chain/types" types "github.com/filecoin-project/lotus/chain/types"
) )
@@ -118,7 +117,7 @@ var msigCreateCmd = &cli.Command{
} }
// wait for it to get mined into a block // wait for it to get mined into a block
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) wait, err := api.StateWaitMsg(ctx, msgCid)
if err != nil { if err != nil {
return err return err
} }
@@ -207,10 +206,7 @@ var msigInspectCmd = &cli.Command{
tx := pending[txid] tx := pending[txid]
fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%d\t%x\n", txid, state(tx), tx.To, types.FIL(tx.Value), tx.Method, tx.Params) fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%d\t%x\n", txid, state(tx), tx.To, types.FIL(tx.Value), tx.Method, tx.Params)
} }
if err := w.Flush(); err != nil { w.Flush()
return xerrors.Errorf("flushing output: %+v", err)
}
} }
return nil return nil
@@ -337,7 +333,7 @@ var msigProposeCmd = &cli.Command{
fmt.Println("send proposal in message: ", msgCid) fmt.Println("send proposal in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) wait, err := api.StateWaitMsg(ctx, msgCid)
if err != nil { if err != nil {
return err return err
} }
@@ -453,7 +449,7 @@ var msigApproveCmd = &cli.Command{
fmt.Println("sent approval in message: ", msgCid) fmt.Println("sent approval in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) wait, err := api.StateWaitMsg(ctx, msgCid)
if err != nil { if err != nil {
return err return err
} }
+2 -26
View File
@@ -7,7 +7,7 @@ import (
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
"github.com/urfave/cli/v2" "gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/lotus/lib/addrutil" "github.com/filecoin-project/lotus/lib/addrutil"
) )
@@ -21,7 +21,6 @@ var netCmd = &cli.Command{
netListen, netListen,
netId, netId,
netFindPeer, netFindPeer,
netScores,
}, },
} }
@@ -45,30 +44,7 @@ var netPeers = &cli.Command{
}) })
for _, peer := range peers { for _, peer := range peers {
fmt.Printf("%s, %s\n", peer.ID, peer.Addrs) fmt.Println(peer)
}
return nil
},
}
var netScores = &cli.Command{
Name: "scores",
Usage: "Print peers' pubsub scores",
Action: func(cctx *cli.Context) error {
api, closer, err := GetAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
scores, err := api.NetPubsubScores(ctx)
if err != nil {
return err
}
for _, peer := range scores {
fmt.Printf("%s, %f\n", peer.ID, peer.Score)
} }
return nil return nil
+2 -3
View File
@@ -3,8 +3,8 @@ package cli
import ( import (
"github.com/docker/go-units" "github.com/docker/go-units"
paramfetch "github.com/filecoin-project/go-paramfetch" paramfetch "github.com/filecoin-project/go-paramfetch"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
) )
@@ -24,8 +24,7 @@ var fetchParamCmd = &cli.Command{
return err return err
} }
sectorSize := uint64(sectorSizeInt) sectorSize := uint64(sectorSizeInt)
err = paramfetch.GetParams(build.ParametersJson(), sectorSize)
err = paramfetch.GetParams(ReqContext(cctx), build.ParametersJSON(), sectorSize)
if err != nil { if err != nil {
return xerrors.Errorf("fetching proof parameters: %w", err) return xerrors.Errorf("fetching proof parameters: %w", err)
} }
+3 -4
View File
@@ -4,11 +4,10 @@ import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/builtin/paych" "github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/urfave/cli/v2" "gopkg.in/urfave/cli.v2"
types "github.com/filecoin-project/lotus/chain/types" types "github.com/filecoin-project/lotus/chain/types"
) )
@@ -362,7 +361,7 @@ var paychVoucherSubmitCmd = &cli.Command{
return err return err
} }
mwait, err := api.StateWaitMsg(ctx, mcid, build.MessageConfidence) mwait, err := api.StateWaitMsg(ctx, mcid)
if err != nil { if err != nil {
return err return err
} }
@@ -371,7 +370,7 @@ var paychVoucherSubmitCmd = &cli.Command{
return fmt.Errorf("message execution failed (exit code %d)", mwait.Receipt.ExitCode) return fmt.Errorf("message execution failed (exit code %d)", mwait.Receipt.ExitCode)
} }
fmt.Println("channel updated successfully") fmt.Println("channel updated succesfully")
return nil return nil
}, },
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/urfave/cli/v2" "gopkg.in/urfave/cli.v2"
) )
var sendCmd = &cli.Command{ var sendCmd = &cli.Command{
+18 -94
View File
@@ -6,7 +6,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"reflect" "reflect"
"sort"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@@ -15,9 +14,9 @@ import (
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
"github.com/multiformats/go-multihash" "github.com/multiformats/go-multihash"
"github.com/urfave/cli/v2"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
@@ -35,7 +34,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"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/miner" "github.com/filecoin-project/lotus/miner"
) )
@@ -393,7 +391,7 @@ var stateReplaySetCmd = &cli.Command{
ts, err = types.NewTipSet(headers) ts, err = types.NewTipSet(headers)
} else { } else {
r, err := api.StateWaitMsg(ctx, mcid, build.MessageConfidence) r, err := api.StateWaitMsg(ctx, mcid)
if err != nil { if err != nil {
return xerrors.Errorf("finding message in chain: %w", err) return xerrors.Errorf("finding message in chain: %w", err)
} }
@@ -495,12 +493,6 @@ var stateGetDealSetCmd = &cli.Command{
var stateListMinersCmd = &cli.Command{ var stateListMinersCmd = &cli.Command{
Name: "list-miners", Name: "list-miners",
Usage: "list all miners in the network", Usage: "list all miners in the network",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "sort-by",
Usage: "criteria to sort miners by (none, num-deals)",
},
},
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
@@ -520,26 +512,6 @@ var stateListMinersCmd = &cli.Command{
return err return err
} }
switch cctx.String("sort-by") {
case "num-deals":
ndm, err := getDealsCounts(ctx, api)
if err != nil {
return err
}
sort.Slice(miners, func(i, j int) bool {
return ndm[miners[i]] > ndm[miners[j]]
})
for i := 0; i < 50 && i < len(miners); i++ {
fmt.Printf("%s %d\n", miners[i], ndm[miners[i]])
}
return nil
default:
return fmt.Errorf("unrecognized sorting order")
case "", "none":
}
for _, m := range miners { for _, m := range miners {
fmt.Println(m.String()) fmt.Println(m.String())
} }
@@ -548,22 +520,6 @@ var stateListMinersCmd = &cli.Command{
}, },
} }
func getDealsCounts(ctx context.Context, lapi api.FullNode) (map[address.Address]int, error) {
allDeals, err := lapi.StateMarketDeals(ctx, types.EmptyTSK)
if err != nil {
return nil, err
}
out := make(map[address.Address]int)
for _, d := range allDeals {
if d.State.SectorStartEpoch != -1 {
out[d.Proposal.Provider]++
}
}
return out, nil
}
var stateListActorsCmd = &cli.Command{ var stateListActorsCmd = &cli.Command{
Name: "list-actors", Name: "list-actors",
Usage: "list all actors in the network", Usage: "list all actors in the network",
@@ -936,7 +892,7 @@ var stateComputeStateCmd = &cli.Command{
return c.Code, nil return c.Code, nil
} }
return computeStateHtml(ts, stout, getCode) return computeStateHtml(stout, getCode)
} }
fmt.Println("computed state cid: ", stout.Root) fmt.Println("computed state cid: ", stout.Root)
@@ -965,7 +921,7 @@ func codeStr(c cid.Cid) string {
return string(cmh.Digest) return string(cmh.Digest)
} }
func computeStateHtml(ts *types.TipSet, o *api.ComputeStateOutput, getCode func(addr address.Address) (cid.Cid, error)) error { func computeStateHtml(o *api.ComputeStateOutput, getCode func(addr address.Address) (cid.Cid, error)) error {
fmt.Printf(`<html> fmt.Printf(`<html>
<head> <head>
<style> <style>
@@ -991,10 +947,8 @@ func computeStateHtml(ts *types.TipSet, o *api.ComputeStateOutput, getCode func(
</style> </style>
</head> </head>
<body> <body>
<div>Tipset: <b>%s</b></div>
<div>Height: %d</div>
<div>State CID: <b>%s</b></div> <div>State CID: <b>%s</b></div>
<div>Calls</div>`, ts.Key(), ts.Height(), o.Root) <div>Calls</div>`, o.Root)
for _, ir := range o.Trace { for _, ir := range o.Trace {
toCode, err := getCode(ir.Msg.To) toCode, err := getCode(ir.Msg.To)
@@ -1042,7 +996,7 @@ func computeStateHtml(ts *types.TipSet, o *api.ComputeStateOutput, getCode func(
if len(ir.InternalExecutions) > 0 { if len(ir.InternalExecutions) > 0 {
fmt.Println("<div>Internal executions:</div>") fmt.Println("<div>Internal executions:</div>")
if err := printInternalExecutionsHtml(cid.String(), ir.InternalExecutions, getCode); err != nil { if err := printInternalExecutionsHtml(ir.InternalExecutions, getCode); err != nil {
return err return err
} }
} }
@@ -1054,10 +1008,8 @@ func computeStateHtml(ts *types.TipSet, o *api.ComputeStateOutput, getCode func(
return nil return nil
} }
func printInternalExecutionsHtml(hashName string, trace []*types.ExecutionResult, getCode func(addr address.Address) (cid.Cid, error)) error { func printInternalExecutionsHtml(trace []*types.ExecutionResult, getCode func(addr address.Address) (cid.Cid, error)) error {
for i, im := range trace { for _, im := range trace {
hashName := fmt.Sprintf("%s-r%d", hashName, i)
toCode, err := getCode(im.Msg.To) toCode, err := getCode(im.Msg.To)
if err != nil { if err != nil {
return xerrors.Errorf("getting code for %s: %w", toCode, err) return xerrors.Errorf("getting code for %s: %w", toCode, err)
@@ -1085,21 +1037,18 @@ func printInternalExecutionsHtml(hashName string, trace []*types.ExecutionResult
ret = `, Return</div><div><pre class="ret">` + ret + `</pre></div>` ret = `, Return</div><div><pre class="ret">` + ret + `</pre></div>`
} }
slow := im.Duration > 10*time.Millisecond fmt.Printf(`<div class="exec">
veryslow := im.Duration > 50*time.Millisecond <div><h4 class="call">%s:%s</h4></div>
fmt.Printf(`<div class="exec" id="%s">
<div><a href="#%s"><h4 class="call">%s:%s</h4></a></div>
<div><b>%s</b> -&gt; <b>%s</b> (%s FIL), M%d</div> <div><b>%s</b> -&gt; <b>%s</b> (%s FIL), M%d</div>
%s %s
<div><span class="slow-%t-%t">Took %s</span>, <span class="exit%d">Exit: <b>%d</b></span>%s <div><span class="exit%d">Exit: <b>%d</b></span>%s
`, hashName, hashName, codeStr(toCode), methods[toCode][im.Msg.Method].name, im.Msg.From, im.Msg.To, types.FIL(im.Msg.Value), im.Msg.Method, params, slow, veryslow, im.Duration, im.MsgRct.ExitCode, im.MsgRct.ExitCode, ret) `, codeStr(toCode), methods[toCode][im.Msg.Method].name, im.Msg.From, im.Msg.To, types.FIL(im.Msg.Value), im.Msg.Method, params, im.MsgRct.ExitCode, im.MsgRct.ExitCode, ret)
if im.MsgRct.ExitCode != 0 { if im.MsgRct.ExitCode != 0 {
fmt.Printf(`<div class="error">Error: <pre>%s</pre></div>`, im.Error) fmt.Printf(`<div class="error">Error: <pre>%s</pre></div>`, im.Error)
} }
if len(im.Subcalls) > 0 { if len(im.Subcalls) > 0 {
fmt.Println("<div>Subcalls:</div>") fmt.Println("<div>Subcalls:</div>")
if err := printInternalExecutionsHtml(hashName, im.Subcalls, getCode); err != nil { if err := printInternalExecutionsHtml(im.Subcalls, getCode); err != nil {
return err return err
} }
} }
@@ -1159,44 +1108,19 @@ var stateWaitMsgCmd = &cli.Command{
return err return err
} }
mw, err := api.StateWaitMsg(ctx, msg, build.MessageConfidence) mw, err := api.StateWaitMsg(ctx, msg)
if err != nil { if err != nil {
return err return err
} }
m, err := api.ChainGetMessage(ctx, msg) fmt.Printf("message was executed in tipset: %s", mw.TipSet.Cids())
if err != nil { fmt.Printf("Exit Code: %d", mw.Receipt.ExitCode)
return err fmt.Printf("Gas Used: %d", mw.Receipt.GasUsed)
} fmt.Printf("Return: %x", mw.Receipt.Return)
fmt.Printf("message was executed in tipset: %s\n", mw.TipSet.Cids())
fmt.Printf("Exit Code: %d\n", mw.Receipt.ExitCode)
fmt.Printf("Gas Used: %d\n", mw.Receipt.GasUsed)
fmt.Printf("Return: %x\n", mw.Receipt.Return)
if err := printReceiptReturn(ctx, api, m, mw.Receipt); err != nil {
return err
}
return nil return nil
}, },
} }
func printReceiptReturn(ctx context.Context, api api.FullNode, m *types.Message, r types.MessageReceipt) error {
act, err := api.StateGetActor(ctx, m.To, types.EmptyTSK)
if err != nil {
return err
}
jret, err := jsonReturn(act.Code, m.Method, r.Return)
if err != nil {
return err
}
fmt.Println(jret)
return nil
}
var stateSearchMsgCmd = &cli.Command{ var stateSearchMsgCmd = &cli.Command{
Name: "search-msg", Name: "search-msg",
Usage: "Search to see whether a message has appeared on chain", Usage: "Search to see whether a message has appeared on chain",
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
"github.com/urfave/cli/v2" "gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
+2 -4
View File
@@ -3,7 +3,7 @@ package cli
import ( import (
"fmt" "fmt"
"github.com/urfave/cli/v2" "gopkg.in/urfave/cli.v2"
) )
var versionCmd = &cli.Command{ var versionCmd = &cli.Command{
@@ -23,9 +23,7 @@ var versionCmd = &cli.Command{
if err != nil { if err != nil {
return err return err
} }
fmt.Println("Daemon: ", v) fmt.Println(v)
fmt.Print("Local: ")
cli.VersionPrinter(cctx) cli.VersionPrinter(cctx)
return nil return nil
}, },
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/urfave/cli/v2" "gopkg.in/urfave/cli.v2"
) )
var waitApiCmd = &cli.Command{ var waitApiCmd = &cli.Command{
+1 -27
View File
@@ -15,7 +15,7 @@ import (
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/urfave/cli/v2" "gopkg.in/urfave/cli.v2"
) )
var walletCmd = &cli.Command{ var walletCmd = &cli.Command{
@@ -31,7 +31,6 @@ var walletCmd = &cli.Command{
walletSetDefault, walletSetDefault,
walletSign, walletSign,
walletVerify, walletVerify,
walletDelete,
}, },
} }
@@ -376,28 +375,3 @@ var walletVerify = &cli.Command{
} }
}, },
} }
var walletDelete = &cli.Command{
Name: "delete",
Usage: "Delete an account from the wallet",
ArgsUsage: "<address> ",
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() || cctx.NArg() != 1 {
return fmt.Errorf("must specify address to delete")
}
addr, err := address.NewFromString(cctx.Args().First())
if err != nil {
return err
}
return api.WalletDelete(ctx, addr)
},
}
+3 -2
View File
@@ -14,7 +14,7 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli" lcli "github.com/filecoin-project/lotus/cli"
"github.com/urfave/cli/v2" "gopkg.in/urfave/cli.v2"
) )
func main() { func main() {
@@ -53,7 +53,8 @@ var runCmd = &cli.Command{
defer closer() defer closer()
ctx := lcli.ReqContext(cctx) ctx := lcli.ReqContext(cctx)
return sendSmallFundsTxs(ctx, api, addr, 5) sendSmallFundsTxs(ctx, api, addr, 5)
return nil
}, },
} }
+5 -19
View File
@@ -15,8 +15,6 @@ import (
"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"
"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/filecoin-project/sector-storage/ffiwrapper" "github.com/filecoin-project/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@@ -24,7 +22,7 @@ import (
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
badger "github.com/ipfs/go-ds-badger2" badger "github.com/ipfs/go-ds-badger2"
blockstore "github.com/ipfs/go-ipfs-blockstore" blockstore "github.com/ipfs/go-ipfs-blockstore"
"github.com/urfave/cli/v2" "gopkg.in/urfave/cli.v2"
) )
type TipSetExec struct { type TipSetExec struct {
@@ -55,7 +53,7 @@ var importBenchCmd = &cli.Command{
if err != nil { if err != nil {
return err return err
} }
defer cfi.Close() //nolint:errcheck // read only file defer cfi.Close()
tdir, err := ioutil.TempDir("", "lotus-import-bench") tdir, err := ioutil.TempDir("", "lotus-import-bench")
if err != nil { if err != nil {
@@ -67,11 +65,6 @@ var importBenchCmd = &cli.Command{
return err return err
} }
bs := blockstore.NewBlockstore(bds) bs := blockstore.NewBlockstore(bds)
cbs, err := blockstore.CachedBlockstore(context.TODO(), bs, blockstore.DefaultCacheOpts())
if err != nil {
return err
}
bs = cbs
ds := datastore.NewMapDatastore() ds := datastore.NewMapDatastore()
cs := store.NewChainStore(bs, ds, vm.Syscalls(ffiwrapper.ProofVerifier)) cs := store.NewChainStore(bs, ds, vm.Syscalls(ffiwrapper.ProofVerifier))
stm := stmgr.NewStateManager(cs) stm := stmgr.NewStateManager(cs)
@@ -80,7 +73,7 @@ var importBenchCmd = &cli.Command{
if err != nil { if err != nil {
return err return err
} }
defer prof.Close() //nolint:errcheck defer prof.Close()
if err := pprof.StartCPUProfile(prof); err != nil { if err := pprof.StartCPUProfile(prof); err != nil {
return err return err
@@ -118,14 +111,7 @@ var importBenchCmd = &cli.Command{
cur := tschain[i] cur := tschain[i]
log.Infof("computing state (height: %d, ts=%s)", cur.Height(), cur.Cids()) log.Infof("computing state (height: %d, ts=%s)", cur.Height(), cur.Cids())
if cur.ParentState() != lastState { if cur.ParentState() != lastState {
lastTrace := out[len(out)-1].Trace return xerrors.Errorf("tipset chain had state mismatch at height %d", cur.Height())
d, err := json.MarshalIndent(lastTrace, "", " ")
if err != nil {
panic(err)
}
fmt.Println("TRACE")
fmt.Println(string(d))
return xerrors.Errorf("tipset chain had state mismatch at height %d (%s != %s)", cur.Height(), cur.ParentState(), lastState)
} }
start := time.Now() start := time.Now()
st, trace, err := stm.ExecutionTrace(context.TODO(), cur) st, trace, err := stm.ExecutionTrace(context.TODO(), cur)
@@ -146,7 +132,7 @@ var importBenchCmd = &cli.Command{
if err != nil { if err != nil {
return err return err
} }
defer ibj.Close() //nolint:errcheck defer ibj.Close()
if err := json.NewEncoder(ibj).Encode(out); err != nil { if err := json.NewEncoder(ibj).Encode(out); err != nil {
return err return err
+23 -23
View File
@@ -15,12 +15,11 @@ import (
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"github.com/minio/blake2b-simd" "github.com/minio/blake2b-simd"
"github.com/mitchellh/go-homedir" "github.com/mitchellh/go-homedir"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
paramfetch "github.com/filecoin-project/go-paramfetch" paramfetch "github.com/filecoin-project/go-paramfetch"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/sector-storage/ffiwrapper" "github.com/filecoin-project/sector-storage/ffiwrapper"
"github.com/filecoin-project/sector-storage/ffiwrapper/basicfs" "github.com/filecoin-project/sector-storage/ffiwrapper/basicfs"
"github.com/filecoin-project/sector-storage/stores" "github.com/filecoin-project/sector-storage/stores"
@@ -79,7 +78,7 @@ func main() {
app := &cli.App{ app := &cli.App{
Name: "lotus-bench", Name: "lotus-bench",
Usage: "Benchmark performance of lotus on your hardware", Usage: "Benchmark performance of lotus on your hardware",
Version: build.UserVersion(), Version: build.UserVersion,
Commands: []*cli.Command{ Commands: []*cli.Command{
proveCmd, proveCmd,
sealBenchCmd, sealBenchCmd,
@@ -142,10 +141,7 @@ var sealBenchCmd = &cli.Command{
}, },
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
if c.Bool("no-gpu") { if c.Bool("no-gpu") {
err := os.Setenv("BELLMAN_NO_GPU", "1") os.Setenv("BELLMAN_NO_GPU", "1")
if err != nil {
return xerrors.Errorf("setting no-gpu flag: %w", err)
}
} }
robench := c.String("benchmark-existing-sectorbuilder") robench := c.String("benchmark-existing-sectorbuilder")
@@ -158,10 +154,7 @@ var sealBenchCmd = &cli.Command{
return err return err
} }
err = os.MkdirAll(sdir, 0775) //nolint:gosec os.MkdirAll(sdir, 0775)
if err != nil {
return xerrors.Errorf("creating sectorbuilder dir: %w", err)
}
tsdir, err := ioutil.TempDir(sdir, "bench") tsdir, err := ioutil.TempDir(sdir, "bench")
if err != nil { if err != nil {
@@ -216,7 +209,7 @@ var sealBenchCmd = &cli.Command{
// Only fetch parameters if actually needed // Only fetch parameters if actually needed
if !c.Bool("skip-commit2") { if !c.Bool("skip-commit2") {
if err := paramfetch.GetParams(lcli.ReqContext(c), build.ParametersJSON(), uint64(sectorSize)); err != nil { if err := paramfetch.GetParams(build.ParametersJson(), uint64(sectorSize)); err != nil {
return xerrors.Errorf("getting params: %w", err) return xerrors.Errorf("getting params: %w", err)
} }
} }
@@ -534,11 +527,16 @@ func runSeals(sb *ffiwrapper.Sealer, sbfs *basicfs.Provider, numSectors int, mid
if !skipc2 { if !skipc2 {
svi := abi.SealVerifyInfo{ svi := abi.SealVerifyInfo{
SectorID: abi.SectorID{Miner: mid, Number: i}, SectorID: abi.SectorID{Miner: mid, Number: i},
SealedCID: cids.Sealed, OnChain: abi.OnChainSealVerifyInfo{
RegisteredProof: sb.SealProofType(), SealedCID: cids.Sealed,
Proof: proof, InteractiveEpoch: seed.Epoch,
DealIDs: nil, RegisteredProof: sb.SealProofType(),
Proof: proof,
DealIDs: nil,
SectorNumber: i,
SealRandEpoch: 0,
},
Randomness: ticket, Randomness: ticket,
InteractiveRandomness: seed.Value, InteractiveRandomness: seed.Value,
UnsealedCID: cids.Unsealed, UnsealedCID: cids.Unsealed,
@@ -569,10 +567,15 @@ func runSeals(sb *ffiwrapper.Sealer, sbfs *basicfs.Provider, numSectors int, mid
} }
} }
err := sb.UnsealPiece(context.TODO(), abi.SectorID{Miner: mid, Number: 1}, 0, abi.UnpaddedPieceSize(sectorSize), ticket, cids.Unsealed) // TODO: RM unsealed sector first
rc, err := sb.ReadPieceFromSealedSector(context.TODO(), abi.SectorID{Miner: mid, Number: 1}, 0, abi.UnpaddedPieceSize(sectorSize), ticket, cids.Unsealed)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
if err := rc.Close(); err != nil {
return nil, nil, err
}
} }
unseal := time.Now() unseal := time.Now()
@@ -601,10 +604,7 @@ var proveCmd = &cli.Command{
}, },
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
if c.Bool("no-gpu") { if c.Bool("no-gpu") {
err := os.Setenv("BELLMAN_NO_GPU", "1") os.Setenv("BELLMAN_NO_GPU", "1")
if err != nil {
return xerrors.Errorf("setting no-gpu flag: %w", err)
}
} }
if !c.Args().Present() { if !c.Args().Present() {
@@ -621,7 +621,7 @@ var proveCmd = &cli.Command{
return xerrors.Errorf("unmarshalling input file: %w", err) return xerrors.Errorf("unmarshalling input file: %w", err)
} }
if err := paramfetch.GetParams(lcli.ReqContext(c), build.ParametersJSON(), c2in.SectorSize); err != nil { if err := paramfetch.GetParams(build.ParametersJson(), c2in.SectorSize); err != nil {
return xerrors.Errorf("getting params: %w", err) return xerrors.Errorf("getting params: %w", err)
} }
+1 -1
View File
@@ -21,7 +21,7 @@ func subBlocks(ctx context.Context, api aapi.FullNode, st *storage) {
bh.Cid(): bh, bh.Cid(): bh,
}, false) }, false)
if err != nil { if err != nil {
log.Errorf("%+v", err) //log.Errorf("%+v", err)
} }
} }
} }
+1 -7
View File
@@ -6,7 +6,7 @@ import (
"strconv" "strconv"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/urfave/cli/v2" "gopkg.in/urfave/cli.v2"
) )
var dotCmd = &cli.Command{ var dotCmd = &cli.Command{
@@ -20,13 +20,7 @@ var dotCmd = &cli.Command{
} }
minH, err := strconv.ParseInt(cctx.Args().Get(0), 10, 32) minH, err := strconv.ParseInt(cctx.Args().Get(0), 10, 32)
if err != nil {
return err
}
tosee, err := strconv.ParseInt(cctx.Args().Get(1), 10, 32) tosee, err := strconv.ParseInt(cctx.Args().Get(1), 10, 32)
if err != nil {
return err
}
maxH := minH + tosee maxH := minH + tosee
res, err := st.db.Query(`select block, parent, b.miner, b.height, p.height from block_parents res, err := st.db.Query(`select block, parent, b.miner, b.height, p.height from block_parents
+4 -4
View File
@@ -7,8 +7,8 @@ import (
"os" "os"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"gopkg.in/urfave/cli.v2"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
lcli "github.com/filecoin-project/lotus/cli" lcli "github.com/filecoin-project/lotus/cli"
@@ -17,7 +17,7 @@ import (
var log = logging.Logger("chainwatch") var log = logging.Logger("chainwatch")
func main() { func main() {
_ = logging.SetLogLevel("*", "INFO") logging.SetLogLevel("*", "INFO")
log.Info("Starting chainwatch") log.Info("Starting chainwatch")
@@ -29,7 +29,7 @@ func main() {
app := &cli.App{ app := &cli.App{
Name: "lotus-chainwatch", Name: "lotus-chainwatch",
Usage: "Devnet token distribution utility", Usage: "Devnet token distribution utility",
Version: build.UserVersion(), Version: build.UserVersion,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: "repo", Name: "repo",
@@ -86,7 +86,7 @@ var runCmd = &cli.Command{
if err != nil { if err != nil {
return err return err
} }
defer st.close() //nolint:errcheck defer st.close()
runSyncer(ctx, api, st, maxBatch) runSyncer(ctx, api, st, maxBatch)
-8
View File
@@ -653,14 +653,6 @@ create temp table b (like blocks excluding constraints) on commit drop;
eprof = bh.ElectionProof.VRFProof eprof = bh.ElectionProof.VRFProof
} }
if bh.Ticket == nil {
log.Warnf("got a block with nil ticket")
bh.Ticket = &types.Ticket{
VRFProof: []byte{},
}
}
if _, err := stmt2.Exec( if _, err := stmt2.Exec(
bh.Cid().String(), bh.Cid().String(),
bh.ParentWeight.String(), bh.ParentWeight.String(),

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