Compare commits

...
Author SHA1 Message Date
Łukasz Magiera 194f56377e Merge pull request #4565 from filecoin-project/feat/shed-msg-decode
shed: Commad to decode messages
2020-10-23 22:35:24 +02:00
Łukasz Magiera 2023615f55 Merge pull request #4563 from filecoin-project/steb/post-lookback
Use older randomness for the PoSt commit on specs-actors version 2
2020-10-23 22:21:51 +02:00
Łukasz Magiera 067de4508b shed: Commad to decode messages 2020-10-23 22:17:46 +02:00
Łukasz Magiera 74bf4c5e71 Merge pull request #4556 from filecoin-project/fix/marketwithdraw-miner
Make wallet market withdraw usable with miner addresses
2020-10-23 22:15:28 +02:00
Jakub Sztandera 099bb2cbaa Merge pull request #4561 from filecoin-project/fix/timedbs-flaky
Fix flaky TestTimedBSSimple
2020-10-23 22:14:32 +02:00
Łukasz Magiera e395559f75 Merge pull request #4564 from filecoin-project/fix/chain-import-flake
Fix flaky TestChainExportImportFull
2020-10-23 22:00:03 +02:00
Łukasz Magiera b7b6ab779a Make wallet market withdraw usable with miner addresses 2020-10-23 21:54:41 +02:00
Steven Allen 109b326ae2 Use older randomness for the PoSt commit on specs-actors version 2
After the upgrade, we're allowed to use randomness up to the challenge epoch.
This safe-guards us against very large reorgs where a miner computes a PoSt very
quickly.
2020-10-23 12:45:11 -07:00
Jakub Sztandera c7e6c8eacc Fix flaky TestChainExportImportFull
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-23 21:45:08 +02:00
Jakub Sztandera 9fbd2a50ff Fix lint
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-23 20:50:17 +02:00
Jakub Sztandera ea69386519 Fix flaky TestTimedBSSimple
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-23 20:46:06 +02:00
Łukasz Magiera 8124fe98c7 Merge pull request #4559 from filecoin-project/fix/beyond-genesis
Fix random test failures
2020-10-23 19:52:10 +02:00
Jakub Sztandera 16a911bc39 Fix random test failures
If block 1 was a null block then blockSet would include genesis which
would lead to us trying to load parent of a genesis block.

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-23 19:33:30 +02:00
Łukasz Magiera c81db5a21c Merge pull request #4420 from filecoin-project/deps/drand-v1.2.0
Chore: update drand to v1.2.0
2020-10-23 18:25:00 +02:00
Łukasz Magiera dbcba6477e Merge pull request #4263 from filecoin-project/feat/lite-market-client
lite-mode - market storage and retrieval clients
2020-10-23 17:23:06 +02:00
Łukasz Magiera 36816fb4f3 Fix list-asks, deals with non-genesis miners in lite-mode 2020-10-23 17:08:21 +02:00
Łukasz Magiera 1ec8252412 Merge pull request #4497 from filecoin-project/feat/lite-market-client-cli
lotus-lite: CLI tests for `lotus client` commands
2020-10-23 16:18:23 +02:00
Łukasz Magiera 91fae36b86 Merge pull request #4554 from filecoin-project/tvx-simulate-2
tvx simulate command; tvx extract --ignore-sanity-checks
2020-10-23 15:58:22 +02:00
Łukasz Magiera 623ffebe62 Merge pull request #4555 from filecoin-project/feat/walletlist-id-market
wallet list: Add market balance and ID address flags
2020-10-23 15:35:03 +02:00
Dirk McCormick 906286fdbe feat: lite-mode - CLI tests for lotus client commands 2020-10-23 15:02:49 +02:00
Dirk McCormick 92942d44d1 feat: lite-mode - market storage and retrieval clients 2020-10-23 15:02:26 +02:00
Łukasz Magiera 9caa6ae69c wallet list: Add market balance and ID address flags 2020-10-23 14:42:19 +02:00
Raúl Kripalani 39d9150175 fix tvx init. 2020-10-23 13:30:04 +01:00
Raúl Kripalani 5301c416bc tvx extract: --ignore-sanity-checks flag. 2020-10-23 10:47:22 +01:00
Raúl Kripalani 92395745d3 tvx simulate: execute raw message against height. 2020-10-23 10:46:32 +01:00
Łukasz Magiera 7d9e8f9d92 Merge pull request #4524 from filecoin-project/feat/withdraw-market-funds-cli
Add a market WithdrawBalance CLI
2020-10-23 11:33:38 +02:00
Łukasz Magiera 6842c03399 wallet cli: rename withdraw-market-funds -> market withdraw 2020-10-23 11:17:03 +02:00
Łukasz Magiera 2c3d80494f Merge pull request #4538 from filecoin-project/steb/test-cleanup-proofs
Cleanup test initialization and always validate VRFs in tests
2020-10-23 10:53:54 +02:00
Steven Allen 2cf770cc91 Merge pull request #4539 from filecoin-project/steb/fix-worker-key-lookback
Use the correct lookback for the worker key when creating blocks
2020-10-22 21:10:25 -07:00
Jakub Sztandera bfdb74bfee Merge pull request #4541 from filecoin-project/feat/maybe-fix-something
Fix chain sync stopping to sync
2020-10-23 02:10:43 +02:00
Jakub Sztandera 580a2f4dc6 Add option to join by common parents
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-23 01:35:26 +02:00
Jakub Sztandera c8fe21c1ef PopRelated aggretates the bucket
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-23 01:18:13 +02:00
Steven Allen 59cfabf8a4 don't resolve the worker key twice 2020-10-22 15:48:09 -07:00
Jakub Sztandera 810feee5a1 PopRelated should pop all
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-23 00:39:08 +02:00
Jakub Sztandera 24fc7d4cbd Add reproduction test and fix the issue
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-23 00:34:04 +02:00
Jakub Sztandera 5edfc527b0 More than one bucket
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-23 00:34:03 +02:00
Jakub Sztandera febc28f83f Add log and Insert
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-22 23:39:54 +02:00
Łukasz Magiera 0289c39850 Merge pull request #4516 from filecoin-project/feat/api-request-metrics-wrapper
Feat/api request metrics wrapper
2020-10-22 21:40:47 +02:00
Łukasz Magiera 29e334de54 Merge pull request #4511 from filecoin-project/steb/generalize-window-post
Manage sectors by size instead of proof type.
2020-10-22 21:27:48 +02:00
Łukasz Magiera f9723ca3c1 Merge pull request #4521 from filecoin-project/feat/fix-shed-ledger-list
Fix lotus-shed ledger list
2020-10-22 19:59:18 +02:00
Łukasz Magiera c17e8e778d Merge pull request #4526 from filecoin-project/wallet-4464
Delete wallet from local wallet cache
2020-10-22 19:50:01 +02:00
Łukasz Magiera b2510e5fc5 Merge pull request #4508 from filecoin-project/fix/actor-not-found-mininig-base
MinerGetBaseInfo: if miner is not found in lookback, check current
2020-10-22 19:45:43 +02:00
Łukasz Magiera 6c800bd0e3 Merge pull request #4501 from filecoin-project/feat/gateway-oni-needs
add some methods that oni needs
2020-10-22 19:44:47 +02:00
Łukasz Magiera 88ac85b6ae Merge pull request #4500 from filecoin-project/fix/mpool-push-atomicity
make push and addLocal atomic
2020-10-22 19:43:52 +02:00
Łukasz Magiera 6bdf9935bf Merge pull request #4475 from filecoin-project/fix/miner-init-createworker
miner: fix init --create-worker-key
2020-10-22 18:55:25 +02:00
Łukasz Magiera 29cda82eac Merge pull request #4449 from austinabell/austin/confcircsupplyfix
Fix circ supply default in conformance
2020-10-22 18:53:10 +02:00
Steven Allen b05613445e Sign blocks with the worker key from the correct lookback epoch 2020-10-22 09:26:58 -07:00
Steven Allen defeba5576 Fix lookback for worker key when computing ticket
We need to compute the ticket based on our worker key from the lookback epoch,
not the current epoch.
2020-10-22 09:26:58 -07:00
Steven Allen 4a550d12d4 Always validate VRFs, even when insecure post validation is enabled
We always generate them, we might as well validate them.
2020-10-22 09:19:46 -07:00
Steven Allen 70c39fe78c Fix global test options
Set BELLMAN_NO_GPU on init.
Set InsecurePoStValidation once in an obvious place.
2020-10-22 09:19:46 -07:00
Will Scott 9dc9bf5eb0 go mod tidy 2020-10-21 19:49:38 -07:00
Will Scott 035a762358 update drand to v1.2.1
* stop autowatching
* set user-agent
2020-10-21 16:49:59 -07:00
jennijuju 7f98be2920 Delete wallet from local wallet cache 2020-10-21 17:53:26 -04:00
Ingar Shu 7bdc7aa527 Add a market WithdrawBalance CLI 2020-10-21 14:09:39 -07:00
Jakub Sztandera f0d966a595 Fix lotus-shed ledger list
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-21 19:40:51 +02:00
lanzafame 7cbd4d49c3 gofmt 2020-10-21 18:39:57 +10:00
lanzafame 7a33d5bb34 register all apis with metric wrapper 2020-10-21 18:37:50 +10:00
lanzafame 3e767ca5c8 wrap api in metrics proxy 2020-10-21 18:27:13 +10:00
Steven Allen 00dcb1bce9 Manage sectors by size instead of proof type.
* We may have multiple sectors with the same size and different proof types, but all these management functions stay the same.
* This simplifies PoSt logic.
2020-10-20 18:30:56 -07:00
Jakub Sztandera 6530431995 MinerGetBaseInfo: if miner is not found in lookback, check current
If miner is found in current state, just return nil base info as miner
cannot mine if he is not found in the lookback.

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-20 23:54:35 +02:00
whyrusleeping abc3e783ff bump lookback cap to 24 hours 2020-10-20 10:09:21 -07:00
whyrusleeping 6bc56c549a add some methods that oni needs 2020-10-20 10:04:51 -07:00
vyzo 580980d149 make push and addLocal atomic 2020-10-20 19:13:17 +03:00
Łukasz Magiera 869d71446d miner: fix init --create-worker-key 2020-10-19 16:08:46 +02:00
austinabell 70e2170e3e Fix circ supply default in conformance 2020-10-16 21:14:36 -04:00
Hector Sanjuan 925606ff26 Chore: update drand to v1.2.0 2020-10-15 12:02:12 +02:00
78 changed files with 2056 additions and 558 deletions
+19 -1
View File
@@ -3,24 +3,42 @@ package api
import (
"context"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
)
type GatewayAPI interface {
ChainHasObj(context.Context, cid.Cid) (bool, error)
ChainHead(ctx context.Context) (*types.TipSet, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error)
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
ChainNotify(context.Context) (<-chan []*HeadChange, error)
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (DealCollateralBounds, error)
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (MarketBalance, error)
StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*MarketDeal, error)
StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error)
StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error)
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*MsgLookup, error)
}
+98 -34
View File
@@ -305,18 +305,18 @@ type StorageMinerStruct struct {
SealingSchedDiag func(context.Context) (interface{}, 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"`
StorageStat func(context.Context, stores.ID) (fsutil.FsStat, error) `perm:"admin"`
StorageAttach func(context.Context, stores.StorageInfo, fsutil.FsStat) error `perm:"admin"`
StorageDeclareSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType, bool) error `perm:"admin"`
StorageDropSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType) error `perm:"admin"`
StorageFindSector func(context.Context, abi.SectorID, stores.SectorFileType, abi.RegisteredSealProof, bool) ([]stores.SectorStorageInfo, error) `perm:"admin"`
StorageInfo func(context.Context, stores.ID) (stores.StorageInfo, error) `perm:"admin"`
StorageBestAlloc func(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredSealProof, sealing stores.PathType) ([]stores.StorageInfo, 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"`
StorageTryLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) (bool, 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"`
StorageStat func(context.Context, stores.ID) (fsutil.FsStat, error) `perm:"admin"`
StorageAttach func(context.Context, stores.StorageInfo, fsutil.FsStat) error `perm:"admin"`
StorageDeclareSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType, bool) error `perm:"admin"`
StorageDropSector func(context.Context, stores.ID, abi.SectorID, stores.SectorFileType) error `perm:"admin"`
StorageFindSector func(context.Context, abi.SectorID, stores.SectorFileType, abi.SectorSize, bool) ([]stores.SectorStorageInfo, error) `perm:"admin"`
StorageInfo func(context.Context, stores.ID) (stores.StorageInfo, error) `perm:"admin"`
StorageBestAlloc func(ctx context.Context, allocate stores.SectorFileType, ssize abi.SectorSize, sealing stores.PathType) ([]stores.StorageInfo, 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"`
StorageTryLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) (bool, error) `perm:"admin"`
DealsImportData func(ctx context.Context, dealPropCid cid.Cid, file string) error `perm:"write"`
DealsList func(ctx context.Context) ([]api.MarketDeal, error) `perm:"read"`
@@ -374,20 +374,32 @@ type WorkerStruct struct {
type GatewayStruct struct {
Internal struct {
// TODO: does the gateway need perms?
ChainHasObj func(context.Context, cid.Cid) (bool, error)
ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
ChainHead func(ctx context.Context) (*types.TipSet, error)
ChainReadObj func(context.Context, cid.Cid) ([]byte, error)
GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
MsigGetVested func(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateWaitMsg func(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
ChainGetBlockMessages func(ctx context.Context, c cid.Cid) (*api.BlockMessages, error)
ChainGetMessage func(ctx context.Context, mc cid.Cid) (*types.Message, error)
ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
ChainHasObj func(context.Context, cid.Cid) (bool, error)
ChainHead func(ctx context.Context) (*types.TipSet, error)
ChainNotify func(ctx context.Context) (<-chan []*api.HeadChange, error)
ChainReadObj func(context.Context, cid.Cid) ([]byte, error)
GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
MsigGetVested func(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateDealProviderCollateralBounds func(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error)
StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
StateGetReceipt func(ctx context.Context, c cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error)
StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateListMiners func(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
StateMinerInfo func(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error)
StateMinerProvingDeadline func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error)
StateMarketBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error)
StateMarketStorageDeal func(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error)
StateNetworkVersion func(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error)
StateVerifiedClientStatus func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
StateWaitMsg func(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
}
}
@@ -1224,8 +1236,8 @@ func (c *StorageMinerStruct) StorageDropSector(ctx context.Context, storageId st
return c.Internal.StorageDropSector(ctx, storageId, s, ft)
}
func (c *StorageMinerStruct) StorageFindSector(ctx context.Context, si abi.SectorID, types stores.SectorFileType, spt abi.RegisteredSealProof, allowFetch bool) ([]stores.SectorStorageInfo, error) {
return c.Internal.StorageFindSector(ctx, si, types, spt, allowFetch)
func (c *StorageMinerStruct) StorageFindSector(ctx context.Context, si abi.SectorID, types stores.SectorFileType, ssize abi.SectorSize, allowFetch bool) ([]stores.SectorStorageInfo, error) {
return c.Internal.StorageFindSector(ctx, si, types, ssize, allowFetch)
}
func (c *StorageMinerStruct) StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error) {
@@ -1244,8 +1256,8 @@ func (c *StorageMinerStruct) StorageInfo(ctx context.Context, id stores.ID) (sto
return c.Internal.StorageInfo(ctx, id)
}
func (c *StorageMinerStruct) StorageBestAlloc(ctx context.Context, allocate stores.SectorFileType, spt abi.RegisteredSealProof, pt stores.PathType) ([]stores.StorageInfo, error) {
return c.Internal.StorageBestAlloc(ctx, allocate, spt, pt)
func (c *StorageMinerStruct) StorageBestAlloc(ctx context.Context, allocate stores.SectorFileType, ssize abi.SectorSize, pt stores.PathType) ([]stores.StorageInfo, error) {
return c.Internal.StorageBestAlloc(ctx, allocate, ssize, pt)
}
func (c *StorageMinerStruct) StorageReportHealth(ctx context.Context, id stores.ID, report stores.HealthReport) error {
@@ -1450,12 +1462,12 @@ func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
return w.Internal.Closing(ctx)
}
func (g GatewayStruct) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) {
return g.Internal.ChainHasObj(ctx, c)
func (g GatewayStruct) ChainGetBlockMessages(ctx context.Context, c cid.Cid) (*api.BlockMessages, error) {
return g.Internal.ChainGetBlockMessages(ctx, c)
}
func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
return g.Internal.ChainHead(ctx)
func (g GatewayStruct) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
return g.Internal.ChainGetMessage(ctx, mc)
}
func (g GatewayStruct) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
@@ -1466,6 +1478,18 @@ func (g GatewayStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEp
return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
}
func (g GatewayStruct) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) {
return g.Internal.ChainHasObj(ctx, c)
}
func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
return g.Internal.ChainHead(ctx)
}
func (g GatewayStruct) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) {
return g.Internal.ChainNotify(ctx)
}
func (g GatewayStruct) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
return g.Internal.ChainReadObj(ctx, c)
}
@@ -1490,14 +1514,54 @@ func (g GatewayStruct) StateAccountKey(ctx context.Context, addr address.Address
return g.Internal.StateAccountKey(ctx, addr, tsk)
}
func (g GatewayStruct) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
return g.Internal.StateDealProviderCollateralBounds(ctx, size, verified, tsk)
}
func (g GatewayStruct) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
return g.Internal.StateGetActor(ctx, actor, ts)
}
func (g GatewayStruct) StateGetReceipt(ctx context.Context, c cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) {
return g.Internal.StateGetReceipt(ctx, c, tsk)
}
func (g GatewayStruct) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
return g.Internal.StateLookupID(ctx, addr, tsk)
}
func (g GatewayStruct) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
return g.Internal.StateListMiners(ctx, tsk)
}
func (g GatewayStruct) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
return g.Internal.StateMarketBalance(ctx, addr, tsk)
}
func (g GatewayStruct) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
return g.Internal.StateMarketStorageDeal(ctx, dealId, tsk)
}
func (g GatewayStruct) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) {
return g.Internal.StateMinerInfo(ctx, actor, tsk)
}
func (g GatewayStruct) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) {
return g.Internal.StateMinerProvingDeadline(ctx, addr, tsk)
}
func (g GatewayStruct) StateMinerPower(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*api.MinerPower, error) {
return g.Internal.StateMinerPower(ctx, addr, tsk)
}
func (g GatewayStruct) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) {
return g.Internal.StateNetworkVersion(ctx, tsk)
}
func (g GatewayStruct) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
return g.Internal.StateVerifiedClientStatus(ctx, addr, tsk)
}
func (g GatewayStruct) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
return g.Internal.StateWaitMsg(ctx, msg, confidence)
}
+1 -4
View File
@@ -3,7 +3,6 @@ package test
import (
"context"
"fmt"
"os"
"sync/atomic"
"testing"
"time"
@@ -17,8 +16,6 @@ import (
)
func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
for _, height := range []abi.ChainEpoch{
1, // before
162, // while sealing
@@ -92,7 +89,7 @@ func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeH
t.Fatal(err)
}
makeDeal(t, ctx, 6, client, miner, false, false)
MakeDeal(t, ctx, 6, client, miner, false, false)
// Validate upgrade
+31 -29
View File
@@ -16,15 +16,12 @@ import (
"github.com/ipfs/go-cid"
files "github.com/ipfs/go-ipfs-files"
logging "github.com/ipfs/go-log/v2"
"github.com/ipld/go-car"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
"github.com/filecoin-project/lotus/miner"
dag "github.com/ipfs/go-merkledag"
dstest "github.com/ipfs/go-merkledag/test"
unixfile "github.com/ipfs/go-unixfs/file"
@@ -34,18 +31,7 @@ import (
ipld "github.com/ipfs/go-ipld-format"
)
var MineNext = miner.MineReq{
InjectNulls: 0,
Done: func(bool, abi.ChainEpoch, error) {},
}
func init() {
logging.SetAllLoggers(logging.LevelInfo)
build.InsecurePoStValidation = true
}
func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport, fastRet bool) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, OneFull, OneMiner)
@@ -74,7 +60,7 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport
}
}()
makeDeal(t, ctx, 6, client, miner, carExport, fastRet)
MakeDeal(t, ctx, 6, client, miner, carExport, fastRet)
atomic.AddInt64(&mine, -1)
fmt.Println("shutting down mining")
@@ -82,7 +68,6 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport
}
func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, OneFull, OneMiner)
@@ -112,24 +97,21 @@ func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
}
}()
makeDeal(t, ctx, 6, client, miner, false, false)
makeDeal(t, ctx, 7, client, miner, false, false)
MakeDeal(t, ctx, 6, client, miner, false, false)
MakeDeal(t, ctx, 7, client, miner, false, false)
atomic.AddInt64(&mine, -1)
fmt.Println("shutting down mining")
<-done
}
func makeDeal(t *testing.T, ctx context.Context, rseed int, client *impl.FullNodeAPI, miner TestStorageNode, carExport, fastRet bool) {
data := make([]byte, 1600)
rand.New(rand.NewSource(int64(rseed))).Read(data)
r := bytes.NewReader(data)
fcid, err := client.ClientImportLocal(ctx, r)
func MakeDeal(t *testing.T, ctx context.Context, rseed int, client api.FullNode, miner TestStorageNode, carExport, fastRet bool) {
res, data, err := CreateClientFile(ctx, client, rseed)
if err != nil {
t.Fatal(err)
}
fcid := res.Root
fmt.Println("FILE CID: ", fcid)
deal := startDeal(t, ctx, miner, client, fcid, fastRet)
@@ -145,8 +127,29 @@ func makeDeal(t *testing.T, ctx context.Context, rseed int, client *impl.FullNod
testRetrieval(t, ctx, client, fcid, &info.PieceCID, carExport, data)
}
func CreateClientFile(ctx context.Context, client api.FullNode, rseed int) (*api.ImportRes, []byte, error) {
data := make([]byte, 1600)
rand.New(rand.NewSource(int64(rseed))).Read(data)
dir, err := ioutil.TempDir(os.TempDir(), "test-make-deal-")
if err != nil {
return nil, nil, err
}
path := filepath.Join(dir, "sourcefile.dat")
err = ioutil.WriteFile(path, data, 0644)
if err != nil {
return nil, nil, err
}
res, err := client.ClientImport(ctx, api.FileRef{Path: path})
if err != nil {
return nil, nil, err
}
return res, data, nil
}
func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, OneFull, OneMiner)
@@ -201,7 +204,6 @@ func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Durati
}
func TestSenondDealRetrieval(t *testing.T, b APIBuilder, blocktime time.Duration) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, OneFull, OneMiner)
@@ -276,7 +278,7 @@ func TestSenondDealRetrieval(t *testing.T, b APIBuilder, blocktime time.Duration
<-done
}
func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client *impl.FullNodeAPI, fcid cid.Cid, fastRet bool) *cid.Cid {
func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client api.FullNode, fcid cid.Cid, fastRet bool) *cid.Cid {
maddr, err := miner.ActorAddress(ctx)
if err != nil {
t.Fatal(err)
@@ -303,7 +305,7 @@ func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client
return deal
}
func waitDealSealed(t *testing.T, ctx context.Context, miner TestStorageNode, client *impl.FullNodeAPI, deal *cid.Cid, noseal bool) {
func waitDealSealed(t *testing.T, ctx context.Context, miner TestStorageNode, client api.FullNode, deal *cid.Cid, noseal bool) {
loop:
for {
di, err := client.ClientGetDealInfo(ctx, *deal)
@@ -376,7 +378,7 @@ func startSealingWaiting(t *testing.T, ctx context.Context, miner TestStorageNod
}
}
func testRetrieval(t *testing.T, ctx context.Context, client *impl.FullNodeAPI, fcid cid.Cid, piece *cid.Cid, carExport bool, data []byte) {
func testRetrieval(t *testing.T, ctx context.Context, client api.FullNode, fcid cid.Cid, piece *cid.Cid, carExport bool, data []byte) {
offers, err := client.ClientFindData(ctx, fcid, piece)
if err != nil {
t.Fatal(err)
-3
View File
@@ -5,7 +5,6 @@ import (
"context"
"fmt"
"math/rand"
"os"
"sync/atomic"
"testing"
"time"
@@ -88,8 +87,6 @@ func (ts *testSuite) testMiningReal(t *testing.T) {
}
func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExport bool) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
// test making a deal with a fresh miner, and see if it starts to mine
ctx := context.Background()
-3
View File
@@ -3,7 +3,6 @@ package test
import (
"context"
"fmt"
"os"
"sync/atomic"
"testing"
"time"
@@ -28,8 +27,6 @@ import (
)
func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, TwoFull, OneMiner)
+17
View File
@@ -2,12 +2,15 @@ package test
import (
"context"
"fmt"
"os"
"testing"
"time"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
logging "github.com/ipfs/go-log/v2"
"github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/assert"
@@ -22,6 +25,15 @@ import (
"github.com/filecoin-project/lotus/node"
)
func init() {
logging.SetAllLoggers(logging.LevelInfo)
err := os.Setenv("BELLMAN_NO_GPU", "1")
if err != nil {
panic(fmt.Sprintf("failed to set BELLMAN_NO_GPU env variable: %s", err))
}
build.InsecurePoStValidation = true
}
type TestNode struct {
api.FullNode
// ListenAddr is the address on which an API server is listening, if an
@@ -110,6 +122,11 @@ var FullNodeWithUpgradeAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
}
}
var MineNext = miner.MineReq{
InjectNulls: 0,
Done: func(bool, abi.ChainEpoch, error) {},
}
func (ts *testSuite) testVersion(t *testing.T) {
build.RunningNodeType = build.NodeFull
-8
View File
@@ -5,7 +5,6 @@ import (
"fmt"
"sync/atomic"
"os"
"strings"
"testing"
"time"
@@ -24,13 +23,6 @@ import (
"github.com/filecoin-project/lotus/node/impl"
)
func init() {
err := os.Setenv("BELLMAN_NO_GPU", "1")
if err != nil {
panic(fmt.Sprintf("failed to set BELLMAN_NO_GPU env variable: %s", err))
}
}
func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
+1 -1
View File
@@ -84,7 +84,7 @@ func VersionForType(nodeType NodeType) (Version, error) {
// semver versions of the rpc api exposed
var (
FullAPIVersion = newVer(0, 17, 0)
MinerAPIVersion = newVer(0, 15, 0)
MinerAPIVersion = newVer(0, 16, 0)
WorkerAPIVersion = newVer(0, 15, 0)
)
+6 -1
View File
@@ -65,6 +65,11 @@ type DrandBeacon struct {
localCache map[uint64]types.BeaconEntry
}
// DrandHTTPClient interface overrides the user agent used by drand
type DrandHTTPClient interface {
SetUserAgent(string)
}
func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes.DrandConfig) (*DrandBeacon, error) {
if genesisTs == 0 {
panic("what are you doing this cant be zero")
@@ -84,6 +89,7 @@ func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes
if err != nil {
return nil, xerrors.Errorf("could not create http drand client: %w", err)
}
hc.(DrandHTTPClient).SetUserAgent("drand-client-lotus/" + build.BuildVersion)
clients = append(clients, hc)
}
@@ -92,7 +98,6 @@ func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes
dclient.WithChainInfo(drandChain),
dclient.WithCacheSize(1024),
dclient.WithLogger(dlogger),
dclient.WithAutoWatch(),
}
if ps != nil {
+11 -1
View File
@@ -27,7 +27,17 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w api.WalletA
return nil, xerrors.Errorf("failed to load tipset state: %w", err)
}
worker, err := stmgr.GetMinerWorkerRaw(ctx, sm, st, bt.Miner)
lbts, err := stmgr.GetLookbackTipSetForRound(ctx, sm, pts, bt.Epoch)
if err != nil {
return nil, xerrors.Errorf("getting lookback miner actor state: %w", err)
}
lbst, _, err := sm.TipSetState(ctx, lbts)
if err != nil {
return nil, err
}
worker, err := stmgr.GetMinerWorkerRaw(ctx, sm, lbst, bt.Miner)
if err != nil {
return nil, xerrors.Errorf("failed to get miner worker: %w", err)
}
+37 -28
View File
@@ -432,9 +432,14 @@ func (mp *MessagePool) runLoop() {
}
}
func (mp *MessagePool) addLocal(m *types.SignedMessage, msgb []byte) error {
func (mp *MessagePool) addLocal(m *types.SignedMessage) error {
mp.localAddrs[m.Message.From] = struct{}{}
msgb, err := m.Serialize()
if err != nil {
return xerrors.Errorf("error serializing message: %w", err)
}
if err := mp.localMsgs.Put(datastore.NewKey(string(m.Cid().Bytes())), msgb); err != nil {
return xerrors.Errorf("persisting local message: %w", err)
}
@@ -507,11 +512,6 @@ func (mp *MessagePool) Push(m *types.SignedMessage) (cid.Cid, error) {
<-mp.addSema
}()
msgb, err := m.Serialize()
if err != nil {
return cid.Undef, err
}
mp.curTsLk.Lock()
publish, err := mp.addTs(m, mp.curTs, true, false)
if err != nil {
@@ -520,18 +520,19 @@ func (mp *MessagePool) Push(m *types.SignedMessage) (cid.Cid, error) {
}
mp.curTsLk.Unlock()
mp.lk.Lock()
if err := mp.addLocal(m, msgb); err != nil {
mp.lk.Unlock()
return cid.Undef, err
}
mp.lk.Unlock()
if publish {
msgb, err := m.Serialize()
if err != nil {
return cid.Undef, xerrors.Errorf("error serializing message: %w", err)
}
err = mp.api.PubSubPublish(build.MessagesTopic(mp.netName), msgb)
if err != nil {
return cid.Undef, xerrors.Errorf("error publishing message: %w", err)
}
}
return m.Cid(), err
return m.Cid(), nil
}
func (mp *MessagePool) checkMessage(m *types.SignedMessage) error {
@@ -670,7 +671,19 @@ func (mp *MessagePool) addTs(m *types.SignedMessage, curTs *types.TipSet, local,
return false, err
}
return publish, mp.addLocked(m, !local, untrusted)
err = mp.addLocked(m, !local, untrusted)
if err != nil {
return false, err
}
if local {
err = mp.addLocal(m)
if err != nil {
return false, xerrors.Errorf("error persisting local message: %w", err)
}
}
return publish, nil
}
func (mp *MessagePool) addLoaded(m *types.SignedMessage) error {
@@ -837,11 +850,6 @@ func (mp *MessagePool) PushUntrusted(m *types.SignedMessage) (cid.Cid, error) {
<-mp.addSema
}()
msgb, err := m.Serialize()
if err != nil {
return cid.Undef, err
}
mp.curTsLk.Lock()
publish, err := mp.addTs(m, mp.curTs, false, true)
if err != nil {
@@ -850,18 +858,19 @@ func (mp *MessagePool) PushUntrusted(m *types.SignedMessage) (cid.Cid, error) {
}
mp.curTsLk.Unlock()
mp.lk.Lock()
if err := mp.addLocal(m, msgb); err != nil {
mp.lk.Unlock()
return cid.Undef, err
}
mp.lk.Unlock()
if publish {
msgb, err := m.Serialize()
if err != nil {
return cid.Undef, xerrors.Errorf("error serializing message: %w", err)
}
err = mp.api.PubSubPublish(build.MessagesTopic(mp.netName), msgb)
if err != nil {
return cid.Undef, xerrors.Errorf("error publishing message: %w", err)
}
}
return m.Cid(), err
return m.Cid(), nil
}
func (mp *MessagePool) Remove(from address.Address, nonce uint64, applied bool) {
+2
View File
@@ -46,6 +46,8 @@ const LookbackNoLimit = abi.ChainEpoch(-1)
var log = logging.Logger("statemgr")
type StateManagerAPI interface {
Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error)
GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error)
LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error)
LookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
+9 -19
View File
@@ -255,25 +255,6 @@ func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *S
return out, nil
}
func StateMinerInfo(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*miner.MinerInfo, error) {
act, err := sm.LoadActor(ctx, maddr, ts)
if err != nil {
return nil, xerrors.Errorf("failed to load miner actor: %w", err)
}
mas, err := miner.Load(sm.cs.Store(ctx), act)
if err != nil {
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
}
mi, err := mas.Info()
if err != nil {
return nil, err
}
return &mi, err
}
func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (bool, error) {
act, err := sm.LoadActor(ctx, power.Address, ts)
if err != nil {
@@ -460,12 +441,21 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule
return nil, xerrors.Errorf("getting lookback miner actor state: %w", err)
}
// TODO: load the state instead of computing it?
lbst, _, err := sm.TipSetState(ctx, lbts)
if err != nil {
return nil, err
}
act, err := sm.LoadActorRaw(ctx, maddr, lbst)
if xerrors.Is(err, types.ErrActorNotFound) {
_, err := sm.LoadActor(ctx, maddr, ts)
if err != nil {
return nil, xerrors.Errorf("loading miner in current state: %w", err)
}
return nil, nil
}
if err != nil {
return nil, xerrors.Errorf("failed to load miner actor: %w", err)
}
+1 -1
View File
@@ -126,7 +126,7 @@ func TestChainExportImportFull(t *testing.T) {
}
buf := new(bytes.Buffer)
if err := cg.ChainStore().Export(context.TODO(), last, 100, false, buf); err != nil {
if err := cg.ChainStore().Export(context.TODO(), last, last.Height(), false, buf); err != nil {
t.Fatal(err)
}
+5 -3
View File
@@ -1396,6 +1396,11 @@ loop:
}
base := blockSet[len(blockSet)-1]
if base.Equals(known) {
blockSet = blockSet[:len(blockSet)-1]
base = blockSet[len(blockSet)-1]
}
if base.IsChildOf(known) {
// common case: receiving blocks that are building on top of our best tipset
return blockSet, nil
@@ -1731,9 +1736,6 @@ func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet) error
}
func VerifyElectionPoStVRF(ctx context.Context, worker address.Address, rand []byte, evrf []byte) error {
if build.InsecurePoStValidation {
return nil
}
return gen.VerifyVRF(ctx, worker, rand, evrf)
}
+38 -8
View File
@@ -2,7 +2,9 @@ package chain
import (
"context"
"os"
"sort"
"strings"
"sync"
"github.com/filecoin-project/lotus/chain/types"
@@ -11,6 +13,14 @@ import (
const BootstrapPeerThreshold = 2
var coalesceForksParents = false
func init() {
if os.Getenv("LOTUS_SYNC_REL_PARENT") == "yes" {
coalesceForksParents = true
}
}
const (
BSStateInit = 0
BSStateSelected = 1
@@ -152,6 +162,19 @@ func newSyncTargetBucket(tipsets ...*types.TipSet) *syncTargetBucket {
return &stb
}
func (sbs *syncBucketSet) String() string {
var bStrings []string
for _, b := range sbs.buckets {
var tsStrings []string
for _, t := range b.tips {
tsStrings = append(tsStrings, t.String())
}
bStrings = append(bStrings, "["+strings.Join(tsStrings, ",")+"]")
}
return "{" + strings.Join(bStrings, ";") + "}"
}
func (sbs *syncBucketSet) RelatedToAny(ts *types.TipSet) bool {
for _, b := range sbs.buckets {
if b.sameChainAs(ts) {
@@ -198,13 +221,17 @@ func (sbs *syncBucketSet) removeBucket(toremove *syncTargetBucket) {
}
func (sbs *syncBucketSet) PopRelated(ts *types.TipSet) *syncTargetBucket {
var bOut *syncTargetBucket
for _, b := range sbs.buckets {
if b.sameChainAs(ts) {
sbs.removeBucket(b)
return b
if bOut == nil {
bOut = &syncTargetBucket{}
}
bOut.tips = append(bOut.tips, b.tips...)
}
}
return nil
return bOut
}
func (sbs *syncBucketSet) Heaviest() *types.TipSet {
@@ -224,8 +251,7 @@ func (sbs *syncBucketSet) Empty() bool {
}
type syncTargetBucket struct {
tips []*types.TipSet
count int
tips []*types.TipSet
}
func (stb *syncTargetBucket) sameChainAs(ts *types.TipSet) bool {
@@ -239,12 +265,14 @@ func (stb *syncTargetBucket) sameChainAs(ts *types.TipSet) bool {
if ts.Parents() == t.Key() {
return true
}
if coalesceForksParents && ts.Parents() == t.Parents() {
return true
}
}
return false
}
func (stb *syncTargetBucket) add(ts *types.TipSet) {
stb.count++
for _, t := range stb.tips {
if t.Equals(ts) {
@@ -294,7 +322,6 @@ func (sm *syncManager) selectSyncTarget() (*types.TipSet, error) {
}
func (sm *syncManager) syncScheduler() {
for {
select {
case ts, ok := <-sm.incomingTipSets:
@@ -326,7 +353,8 @@ func (sm *syncManager) scheduleIncoming(ts *types.TipSet) {
var relatedToActiveSync bool
for _, acts := range sm.activeSyncs {
if ts.Equals(acts) {
break
// ignore, we are already syncing it
return
}
if ts.Parents() == acts.Key() {
@@ -376,7 +404,9 @@ func (sm *syncManager) scheduleProcessResult(res *syncResult) {
sm.nextSyncTarget = relbucket
sm.workerChan = sm.syncTargets
} else {
sm.syncQueue.buckets = append(sm.syncQueue.buckets, relbucket)
for _, t := range relbucket.tips {
sm.syncQueue.Insert(t)
}
}
return
}
+63
View File
@@ -67,6 +67,69 @@ func assertGetSyncOp(t *testing.T, c chan *syncOp, ts *types.TipSet) {
}
}
func TestSyncManagerEdgeCase(t *testing.T) {
ctx := context.Background()
a := mock.TipSet(mock.MkBlock(genTs, 1, 1))
t.Logf("a: %s", a)
b1 := mock.TipSet(mock.MkBlock(a, 1, 2))
t.Logf("b1: %s", b1)
b2 := mock.TipSet(mock.MkBlock(a, 2, 3))
t.Logf("b2: %s", b2)
c1 := mock.TipSet(mock.MkBlock(b1, 2, 4))
t.Logf("c1: %s", c1)
c2 := mock.TipSet(mock.MkBlock(b2, 1, 5))
t.Logf("c2: %s", c2)
d1 := mock.TipSet(mock.MkBlock(c1, 1, 6))
t.Logf("d1: %s", d1)
e1 := mock.TipSet(mock.MkBlock(d1, 1, 7))
t.Logf("e1: %s", e1)
runSyncMgrTest(t, "edgeCase", 1, func(t *testing.T, sm *syncManager, stc chan *syncOp) {
sm.SetPeerHead(ctx, "peer1", a)
assertGetSyncOp(t, stc, a)
sm.SetPeerHead(ctx, "peer1", b1)
sm.SetPeerHead(ctx, "peer1", b2)
// b1 and b2 are being processed
b1op := <-stc
b2op := <-stc
if !b1op.ts.Equals(b1) {
b1op, b2op = b2op, b1op
}
sm.SetPeerHead(ctx, "peer2", c2) // c2 is put into activeSyncTips at index 0
sm.SetPeerHead(ctx, "peer2", c1) // c1 is put into activeSyncTips at index 1
sm.SetPeerHead(ctx, "peer3", b2) // b2 is related to c2 and even though it is actively synced it is put into activeSyncTips index 0
sm.SetPeerHead(ctx, "peer1", a) // a is related to b2 and is put into activeSyncTips index 0
b1op.done() // b1 completes first, is related to a, so it pops activeSyncTips index 0
// even though correct one is index 1
b2op.done()
// b2 completes and is not related to c1, so it leaves activeSyncTips as it is
waitUntilAllWorkersAreDone(stc)
if len(sm.activeSyncTips.buckets) != 0 {
t.Errorf("activeSyncTips expected empty but got: %s", sm.activeSyncTips.String())
}
})
}
func waitUntilAllWorkersAreDone(stc chan *syncOp) {
for i := 0; i < 10; {
select {
case so := <-stc:
so.done()
default:
i++
time.Sleep(10 * time.Millisecond)
}
}
}
func TestSyncManager(t *testing.T) {
ctx := context.Background()
+6
View File
@@ -272,6 +272,7 @@ func (w *LocalWallet) WalletHas(ctx context.Context, addr address.Address) (bool
func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) error {
k, err := w.findKey(addr)
if err != nil {
return xerrors.Errorf("failed to delete key %s : %w", addr, err)
}
@@ -279,6 +280,9 @@ func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) er
return nil // already not there
}
w.lk.Lock()
defer w.lk.Unlock()
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)
}
@@ -295,6 +299,8 @@ func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) er
// TODO: Does this always error in the not-found case? Just ignoring an error return for now.
_ = w.keystore.Delete(KNamePrefix + tAddr)
delete(w.keys, addr)
return nil
}
+1 -1
View File
@@ -1291,7 +1291,7 @@ var chainDecodeParamsCmd = &cli.Command{
return xerrors.Errorf("getting actor: %w", err)
}
pstr, err := jsonParams(act.Code, abi.MethodNum(method), params)
pstr, err := JsonParams(act.Code, abi.MethodNum(method), params)
if err != nil {
return err
}
+39 -35
View File
@@ -343,6 +343,7 @@ var clientDealCmd = &cli.Command{
}
defer closer()
ctx := ReqContext(cctx)
afmt := NewAppFmt(cctx.App)
if cctx.NArg() != 4 {
return xerrors.New("expected 4 args: dataCid, miner, price, duration")
@@ -462,7 +463,7 @@ var clientDealCmd = &cli.Command{
return err
}
fmt.Println(encoder.Encode(*proposal))
afmt.Println(encoder.Encode(*proposal))
return nil
},
@@ -477,6 +478,7 @@ func interactiveDeal(cctx *cli.Context) error {
ctx := ReqContext(cctx)
ctx, cancel := context.WithCancel(ctx)
defer cancel()
afmt := NewAppFmt(cctx.App)
state := "import"
gib := types.NewInt(1 << 30)
@@ -517,10 +519,10 @@ func interactiveDeal(cctx *cli.Context) error {
}
printErr := func(err error) {
fmt.Printf("%s %s\n", color.RedString("Error:"), err.Error())
afmt.Printf("%s %s\n", color.RedString("Error:"), err.Error())
}
cs := readline.NewCancelableStdin(os.Stdin)
cs := readline.NewCancelableStdin(afmt.Stdin)
go func() {
<-ctx.Done()
cs.Close() // nolint:errcheck
@@ -537,7 +539,7 @@ uiLoop:
switch state {
case "import":
fmt.Print("Data CID (from " + color.YellowString("lotus client import") + "): ")
afmt.Print("Data CID (from " + color.YellowString("lotus client import") + "): ")
_cidStr, _, err := rl.ReadLine()
cidStr := string(_cidStr)
@@ -560,7 +562,7 @@ uiLoop:
state = "duration"
case "duration":
fmt.Print("Deal duration (days): ")
afmt.Print("Deal duration (days): ")
_daystr, _, err := rl.ReadLine()
daystr := string(_daystr)
@@ -605,7 +607,7 @@ uiLoop:
continue
}
fmt.Print("\nMake this a verified deal? (yes/no): ")
afmt.Print("\nMake this a verified deal? (yes/no): ")
_yn, _, err := rl.ReadLine()
yn := string(_yn)
@@ -619,13 +621,13 @@ uiLoop:
case "no":
verified = false
default:
fmt.Println("Type in full 'yes' or 'no'")
afmt.Println("Type in full 'yes' or 'no'")
continue
}
state = "miner"
case "miner":
fmt.Print("Miner Addresses (f0.. f0..), none to find: ")
afmt.Print("Miner Addresses (f0.. f0..), none to find: ")
_maddrsStr, _, err := rl.ReadLine()
maddrsStr := string(_maddrsStr)
@@ -664,11 +666,11 @@ uiLoop:
candidateAsks = append(candidateAsks, ask)
}
fmt.Printf("Found %d candidate asks\n", len(candidateAsks))
afmt.Printf("Found %d candidate asks\n", len(candidateAsks))
state = "find-budget"
case "find-budget":
fmt.Printf("Proposing from %s, Current Balance: %s\n", a, types.FIL(fromBal))
fmt.Print("Maximum budget (FIL): ") // TODO: Propose some default somehow?
afmt.Printf("Proposing from %s, Current Balance: %s\n", a, types.FIL(fromBal))
afmt.Print("Maximum budget (FIL): ") // TODO: Propose some default somehow?
_budgetStr, _, err := rl.ReadLine()
budgetStr := string(_budgetStr)
@@ -698,10 +700,10 @@ uiLoop:
}
}
candidateAsks = goodAsks
fmt.Printf("%d asks within budget\n", len(candidateAsks))
afmt.Printf("%d asks within budget\n", len(candidateAsks))
state = "find-count"
case "find-count":
fmt.Print("Deals to make (1): ")
afmt.Print("Deals to make (1): ")
dealcStr, _, err := rl.ReadLine()
if err != nil {
printErr(xerrors.Errorf("reading deal count: %w", err))
@@ -780,12 +782,12 @@ uiLoop:
case "confirm":
// TODO: do some more or epochs math (round to miner PP, deal start buffer)
fmt.Printf("-----\n")
fmt.Printf("Proposing from %s\n", a)
fmt.Printf("\tBalance: %s\n", types.FIL(fromBal))
fmt.Printf("\n")
fmt.Printf("Piece size: %s (Payload size: %s)\n", units.BytesSize(float64(ds.PieceSize)), units.BytesSize(float64(ds.PayloadSize)))
fmt.Printf("Duration: %s\n", dur)
afmt.Printf("-----\n")
afmt.Printf("Proposing from %s\n", a)
afmt.Printf("\tBalance: %s\n", types.FIL(fromBal))
afmt.Printf("\n")
afmt.Printf("Piece size: %s (Payload size: %s)\n", units.BytesSize(float64(ds.PieceSize)), units.BytesSize(float64(ds.PayloadSize)))
afmt.Printf("Duration: %s\n", dur)
pricePerGib := big.Zero()
for _, a := range ask {
@@ -804,7 +806,7 @@ uiLoop:
if len(ask) > 1 {
totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs)))
fmt.Printf("Miner %s (Power:%s) price: ~%s (%s per epoch)\n", color.YellowString(a.Miner.String()), color.GreenString(types.SizeStr(mpow.MinerPower.QualityAdjPower)), color.BlueString(types.FIL(totalPrice).String()), types.FIL(epochPrice))
afmt.Printf("Miner %s (Power:%s) price: ~%s (%s per epoch)\n", color.YellowString(a.Miner.String()), color.GreenString(types.SizeStr(mpow.MinerPower.QualityAdjPower)), color.BlueString(types.FIL(totalPrice).String()), types.FIL(epochPrice))
}
}
@@ -812,12 +814,12 @@ uiLoop:
epochPrice := types.BigDiv(types.BigMul(pricePerGib, types.NewInt(uint64(ds.PieceSize))), gib)
totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs)))
fmt.Printf("Total price: ~%s (%s per epoch)\n", color.CyanString(types.FIL(totalPrice).String()), types.FIL(epochPrice))
fmt.Printf("Verified: %v\n", verified)
afmt.Printf("Total price: ~%s (%s per epoch)\n", color.CyanString(types.FIL(totalPrice).String()), types.FIL(epochPrice))
afmt.Printf("Verified: %v\n", verified)
state = "accept"
case "accept":
fmt.Print("\nAccept (yes/no): ")
afmt.Print("\nAccept (yes/no): ")
_yn, _, err := rl.ReadLine()
yn := string(_yn)
@@ -830,7 +832,7 @@ uiLoop:
}
if yn != "yes" {
fmt.Println("Type in full 'yes' or 'no'")
afmt.Println("Type in full 'yes' or 'no'")
continue
}
@@ -861,7 +863,7 @@ uiLoop:
return err
}
fmt.Printf("Deal (%s) CID: %s\n", maddr, color.GreenString(encoder.Encode(*proposal)))
afmt.Printf("Deal (%s) CID: %s\n", maddr, color.GreenString(encoder.Encode(*proposal)))
}
return nil
@@ -975,6 +977,7 @@ var clientRetrieveCmd = &cli.Command{
}
defer closer()
ctx := ReqContext(cctx)
afmt := NewAppFmt(cctx.App)
var payer address.Address
if cctx.String("from") != "" {
@@ -1083,14 +1086,14 @@ var clientRetrieveCmd = &cli.Command{
select {
case evt, ok := <-updates:
if ok {
fmt.Printf("> Recv: %s, Paid %s, %s (%s)\n",
afmt.Printf("> Recv: %s, Paid %s, %s (%s)\n",
types.SizeStr(types.NewInt(evt.BytesReceived)),
types.FIL(evt.FundsSpent),
retrievalmarket.ClientEvents[evt.Event],
retrievalmarket.DealStatuses[evt.Status],
)
} else {
fmt.Println("Success")
afmt.Println("Success")
return nil
}
@@ -1269,8 +1272,9 @@ var clientQueryAskCmd = &cli.Command{
},
},
Action: func(cctx *cli.Context) error {
afmt := NewAppFmt(cctx.App)
if cctx.NArg() != 1 {
fmt.Println("Usage: query-ask [minerAddress]")
afmt.Println("Usage: query-ask [minerAddress]")
return nil
}
@@ -1311,23 +1315,23 @@ var clientQueryAskCmd = &cli.Command{
return err
}
fmt.Printf("Ask: %s\n", maddr)
fmt.Printf("Price per GiB: %s\n", types.FIL(ask.Price))
fmt.Printf("Verified Price per GiB: %s\n", types.FIL(ask.VerifiedPrice))
fmt.Printf("Max Piece size: %s\n", types.SizeStr(types.NewInt(uint64(ask.MaxPieceSize))))
afmt.Printf("Ask: %s\n", maddr)
afmt.Printf("Price per GiB: %s\n", types.FIL(ask.Price))
afmt.Printf("Verified Price per GiB: %s\n", types.FIL(ask.VerifiedPrice))
afmt.Printf("Max Piece size: %s\n", types.SizeStr(types.NewInt(uint64(ask.MaxPieceSize))))
size := cctx.Int64("size")
if size == 0 {
return nil
}
perEpoch := types.BigDiv(types.BigMul(ask.Price, types.NewInt(uint64(size))), types.NewInt(1<<30))
fmt.Printf("Price per Block: %s\n", types.FIL(perEpoch))
afmt.Printf("Price per Block: %s\n", types.FIL(perEpoch))
duration := cctx.Int64("duration")
if duration == 0 {
return nil
}
fmt.Printf("Total Price: %s\n", types.FIL(types.BigMul(perEpoch, types.NewInt(uint64(duration)))))
afmt.Printf("Total Price: %s\n", types.FIL(types.BigMul(perEpoch, types.NewInt(uint64(duration)))))
return nil
},
@@ -1410,7 +1414,7 @@ var clientListDeals = &cli.Command{
}
}
return outputStorageDeals(ctx, os.Stdout, api, localDeals, cctx.Bool("verbose"), cctx.Bool("color"), showFailed)
return outputStorageDeals(ctx, cctx.App.Writer, api, localDeals, cctx.Bool("verbose"), cctx.Bool("color"), showFailed)
},
}
+22
View File
@@ -0,0 +1,22 @@
package cli
import (
"context"
"os"
"testing"
"time"
clitest "github.com/filecoin-project/lotus/cli/test"
)
// TestClient does a basic test to exercise the client CLI
// commands
func TestClient(t *testing.T) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
clitest.QuietMiningLogs()
blocktime := 5 * time.Millisecond
ctx := context.Background()
clientNode, _ := clitest.StartOneNodeOneMiner(ctx, t, blocktime)
clitest.RunClientTest(t, Commands, clientNode)
}
+38 -5
View File
@@ -2,15 +2,16 @@ package cli
import (
"fmt"
"io"
"os"
"github.com/urfave/cli/v2"
ufcli "github.com/urfave/cli/v2"
"golang.org/x/xerrors"
)
type PrintHelpErr struct {
Err error
Ctx *cli.Context
Ctx *ufcli.Context
}
func (e *PrintHelpErr) Error() string {
@@ -26,11 +27,11 @@ func (e *PrintHelpErr) Is(o error) bool {
return ok
}
func ShowHelp(cctx *cli.Context, err error) error {
func ShowHelp(cctx *ufcli.Context, err error) error {
return &PrintHelpErr{Err: err, Ctx: cctx}
}
func RunApp(app *cli.App) {
func RunApp(app *ufcli.App) {
if err := app.Run(os.Args); err != nil {
if os.Getenv("LOTUS_DEV") != "" {
log.Warnf("%+v", err)
@@ -39,8 +40,40 @@ func RunApp(app *cli.App) {
}
var phe *PrintHelpErr
if xerrors.As(err, &phe) {
_ = cli.ShowCommandHelp(phe.Ctx, phe.Ctx.Command.Name)
_ = ufcli.ShowCommandHelp(phe.Ctx, phe.Ctx.Command.Name)
}
os.Exit(1)
}
}
type AppFmt struct {
app *ufcli.App
Stdin io.Reader
}
func NewAppFmt(a *ufcli.App) *AppFmt {
var stdin io.Reader
istdin, ok := a.Metadata["stdin"]
if ok {
stdin = istdin.(io.Reader)
} else {
stdin = os.Stdin
}
return &AppFmt{app: a, Stdin: stdin}
}
func (a *AppFmt) Print(args ...interface{}) {
fmt.Fprint(a.app.Writer, args...)
}
func (a *AppFmt) Println(args ...interface{}) {
fmt.Fprintln(a.app.Writer, args...)
}
func (a *AppFmt) Printf(fmtstr string, args ...interface{}) {
fmt.Fprintf(a.app.Writer, fmtstr, args...)
}
func (a *AppFmt) Scan(args ...interface{}) (int, error) {
return fmt.Fscan(a.Stdin, args...)
}
+2 -35
View File
@@ -6,50 +6,17 @@ import (
"testing"
"time"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api/test"
clitest "github.com/filecoin-project/lotus/cli/test"
builder "github.com/filecoin-project/lotus/node/test"
)
// TestMultisig does a basic test to exercise the multisig CLI
// commands
func TestMultisig(t *testing.T) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
clitest.QuietMiningLogs()
blocktime := 5 * time.Millisecond
ctx := context.Background()
nodes, _ := startNodes(ctx, t, blocktime)
clientNode := nodes[0]
clientNode, _ := clitest.StartOneNodeOneMiner(ctx, t, blocktime)
clitest.RunMultisigTest(t, Commands, clientNode)
}
func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration) ([]test.TestNode, []address.Address) {
n, sn := builder.RPCMockSbBuilder(t, test.OneFull, test.OneMiner)
full := n[0]
miner := sn[0]
// Get everyone connected
addrs, err := full.NetAddrsListen(ctx)
if err != nil {
t.Fatal(err)
}
if err := miner.NetConnect(ctx, addrs); err != nil {
t.Fatal(err)
}
// Start mining blocks
bm := test.NewBlockMiner(ctx, t, miner, blocktime)
bm.MineBlocks()
// Get the creator's address
creatorAddr, err := full.WalletDefaultAddress(ctx)
if err != nil {
t.Fatal(err)
}
// Create mock CLI
return n, []address.Address{creatorAddr}
}
+2 -2
View File
@@ -1211,7 +1211,7 @@ func ComputeStateHTMLTempl(w io.Writer, ts *types.TipSet, o *api.ComputeStateOut
"GetCode": getCode,
"GetMethod": getMethod,
"ToFil": toFil,
"JsonParams": jsonParams,
"JsonParams": JsonParams,
"JsonReturn": jsonReturn,
"IsSlow": isSlow,
"IsVerySlow": isVerySlow,
@@ -1298,7 +1298,7 @@ func sumGas(changes []*types.GasTrace) types.GasTrace {
return out
}
func jsonParams(code cid.Cid, method abi.MethodNum, params []byte) (string, error) {
func JsonParams(code cid.Cid, method abi.MethodNum, params []byte) (string, error) {
methodMeta, found := stmgr.MethodsMap[code][method]
if !found {
return "", fmt.Errorf("method %d not found on actor %s", method, code)
+115
View File
@@ -0,0 +1,115 @@
package test
import (
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strings"
"testing"
"time"
"github.com/filecoin-project/lotus/api/test"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/v2/actors/builtin"
"github.com/stretchr/testify/require"
lcli "github.com/urfave/cli/v2"
)
// RunClientTest exercises some of the client CLI commands
func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
// Create mock CLI
mockCLI := newMockCLI(t, cmds)
clientCLI := mockCLI.client(clientNode.ListenAddr)
// Get the miner address
addrs, err := clientNode.StateListMiners(ctx, types.EmptyTSK)
require.NoError(t, err)
require.Len(t, addrs, 1)
minerAddr := addrs[0]
fmt.Println("Miner:", minerAddr)
// client query-ask <miner addr>
cmd := []string{
"client", "query-ask", minerAddr.String(),
}
out := clientCLI.runCmd(cmd)
require.Regexp(t, regexp.MustCompile("Ask:"), out)
// Create a deal (non-interactive)
// client deal <cid> <miner addr> 1000000attofil <duration>
res, _, err := test.CreateClientFile(ctx, clientNode, 1)
require.NoError(t, err)
dataCid := res.Root
price := "1000000attofil"
duration := fmt.Sprintf("%d", build.MinDealDuration)
cmd = []string{
"client", "deal", dataCid.String(), minerAddr.String(), price, duration,
}
out = clientCLI.runCmd(cmd)
fmt.Println("client deal", out)
// Create a deal (interactive)
// client deal
// <cid>
// <duration> (in days)
// <miner addr>
// "no" (verified client)
// "yes" (confirm deal)
res, _, err = test.CreateClientFile(ctx, clientNode, 2)
require.NoError(t, err)
dataCid2 := res.Root
duration = fmt.Sprintf("%d", build.MinDealDuration/builtin.EpochsInDay)
cmd = []string{
"client", "deal",
}
interactiveCmds := []string{
dataCid2.String(),
duration,
minerAddr.String(),
"no",
"yes",
}
out = clientCLI.runInteractiveCmd(cmd, interactiveCmds)
fmt.Println("client deal:\n", out)
// Wait for provider to start sealing deal
dealStatus := ""
for dealStatus != "StorageDealSealing" {
// client list-deals
cmd = []string{"client", "list-deals"}
out = clientCLI.runCmd(cmd)
fmt.Println("list-deals:\n", out)
lines := strings.Split(out, "\n")
require.Len(t, lines, 2)
re := regexp.MustCompile(`\s+`)
parts := re.Split(lines[1], -1)
if len(parts) < 4 {
require.Fail(t, "bad list-deals output format")
}
dealStatus = parts[3]
fmt.Println(" Deal status:", dealStatus)
time.Sleep(time.Second)
}
// Retrieve the first file from the miner
// client retrieve <cid> <file path>
tmpdir, err := ioutil.TempDir(os.TempDir(), "test-cli-client")
require.NoError(t, err)
path := filepath.Join(tmpdir, "outfile.dat")
cmd = []string{
"client", "retrieve", dataCid.String(), path,
}
out = clientCLI.runCmd(cmd)
fmt.Println("retrieve:\n", out)
require.Regexp(t, regexp.MustCompile("Success"), out)
}
+9
View File
@@ -122,3 +122,12 @@ func (c *mockCLIClient) flagSet(cmd *lcli.Command) *flag.FlagSet {
}
return fs
}
func (c *mockCLIClient) runInteractiveCmd(cmd []string, interactive []string) string {
c.toStdin(strings.Join(interactive, "\n") + "\n")
return c.runCmd(cmd)
}
func (c *mockCLIClient) toStdin(s string) {
c.cctx.App.Metadata["stdin"] = bytes.NewBufferString(s)
}
-9
View File
@@ -10,19 +10,10 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api/test"
"github.com/filecoin-project/lotus/chain/types"
logging "github.com/ipfs/go-log/v2"
"github.com/stretchr/testify/require"
lcli "github.com/urfave/cli/v2"
)
func QuietMiningLogs() {
logging.SetLogLevel("miner", "ERROR")
logging.SetLogLevel("chainstore", "ERROR")
logging.SetLogLevel("chain", "ERROR")
logging.SetLogLevel("sub", "ERROR")
logging.SetLogLevel("storageminer", "ERROR")
}
func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) {
ctx := context.Background()
+41
View File
@@ -0,0 +1,41 @@
package test
import (
"context"
"testing"
"time"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api/test"
test2 "github.com/filecoin-project/lotus/node/test"
)
func StartOneNodeOneMiner(ctx context.Context, t *testing.T, blocktime time.Duration) (test.TestNode, address.Address) {
n, sn := test2.RPCMockSbBuilder(t, test.OneFull, test.OneMiner)
full := n[0]
miner := sn[0]
// Get everyone connected
addrs, err := full.NetAddrsListen(ctx)
if err != nil {
t.Fatal(err)
}
if err := miner.NetConnect(ctx, addrs); err != nil {
t.Fatal(err)
}
// Start mining blocks
bm := test.NewBlockMiner(ctx, t, miner, blocktime)
bm.MineBlocks()
// Get the full node's wallet address
fullAddr, err := full.WalletDefaultAddress(ctx)
if err != nil {
t.Fatal(err)
}
// Create mock CLI
return full, fullAddr
}
+12
View File
@@ -0,0 +1,12 @@
package test
import "github.com/ipfs/go-log/v2"
func QuietMiningLogs() {
_ = log.SetLogLevel("miner", "ERROR")
_ = log.SetLogLevel("chainstore", "ERROR")
_ = log.SetLogLevel("chain", "ERROR")
_ = log.SetLogLevel("sub", "ERROR")
_ = log.SetLogLevel("storageminer", "ERROR")
_ = log.SetLogLevel("pubsub", "ERROR")
}
+139
View File
@@ -13,9 +13,13 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/v2/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors"
types "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/tablewriter"
)
@@ -34,6 +38,7 @@ var walletCmd = &cli.Command{
walletSign,
walletVerify,
walletDelete,
walletMarket,
},
}
@@ -74,6 +79,16 @@ var walletList = &cli.Command{
Usage: "Only print addresses",
Aliases: []string{"a"},
},
&cli.BoolFlag{
Name: "id",
Usage: "Output ID addresses",
Aliases: []string{"i"},
},
&cli.BoolFlag{
Name: "market",
Usage: "Output market balances",
Aliases: []string{"m"},
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
@@ -93,7 +108,10 @@ var walletList = &cli.Command{
tw := tablewriter.New(
tablewriter.Col("Address"),
tablewriter.Col("ID"),
tablewriter.Col("Balance"),
tablewriter.Col("Market(Avail)"),
tablewriter.Col("Market(Locked)"),
tablewriter.Col("Nonce"),
tablewriter.Col("Default"),
tablewriter.NewLineCol("Error"))
@@ -126,6 +144,23 @@ var walletList = &cli.Command{
row["Default"] = "X"
}
if cctx.Bool("id") {
id, err := api.StateLookupID(ctx, addr, types.EmptyTSK)
if err != nil {
row["ID"] = "n/a"
} else {
row["ID"] = id
}
}
if cctx.Bool("market") {
mbal, err := api.StateMarketBalance(ctx, addr, types.EmptyTSK)
if err == nil {
row["Market(Avail)"] = types.FIL(types.BigSub(mbal.Escrow, mbal.Locked))
row["Market(Locked)"] = types.FIL(mbal.Locked)
}
}
tw.Write(row)
}
}
@@ -471,3 +506,107 @@ var walletDelete = &cli.Command{
return api.WalletDelete(ctx, addr)
},
}
var walletMarket = &cli.Command{
Name: "market",
Usage: "Interact with market balances",
Subcommands: []*cli.Command{
walletMarketWithdraw,
},
}
var walletMarketWithdraw = &cli.Command{
Name: "withdraw",
Usage: "Withdraw funds from the Storage Market Actor",
ArgsUsage: "[amount (FIL) optional, otherwise will withdraw max available]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
Usage: "Specify address to withdraw funds from, otherwise it will use the default wallet address",
Aliases: []string{"f"},
},
&cli.StringFlag{
Name: "address",
Usage: "Market address to withdraw from (account or miner actor address, defaults to --from address)",
Aliases: []string{"a"},
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return xerrors.Errorf("getting node API: %w", err)
}
defer closer()
ctx := ReqContext(cctx)
var from address.Address
if cctx.String("from") != "" {
from, err = address.NewFromString(cctx.String("from"))
if err != nil {
return xerrors.Errorf("parsing from address: %w", err)
}
} else {
from, err = api.WalletDefaultAddress(ctx)
if err != nil {
return xerrors.Errorf("getting default wallet address: %w", err)
}
}
addr := from
if cctx.String("address") != "" {
addr, err = address.NewFromString(cctx.String("address"))
if err != nil {
return xerrors.Errorf("parsing market address: %w", err)
}
}
bal, err := api.StateMarketBalance(ctx, addr, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("getting market balance for address %s: %w", addr.String(), err)
}
avail := big.Subtract(bal.Escrow, bal.Locked)
amt := avail
if cctx.Args().Present() {
f, err := types.ParseFIL(cctx.Args().First())
if err != nil {
return xerrors.Errorf("parsing 'amount' argument: %w", err)
}
amt = abi.TokenAmount(f)
}
if amt.GreaterThan(avail) {
return xerrors.Errorf("can't withdraw more funds than available; requested: %s; available: %s", types.FIL(amt), types.FIL(avail))
}
if avail.IsZero() {
return xerrors.Errorf("zero unlocked funds available to withdraw")
}
params, err := actors.SerializeParams(&market.WithdrawBalanceParams{
ProviderOrClientAddress: addr,
Amount: amt,
})
if err != nil {
return xerrors.Errorf("serializing params: %w", err)
}
fmt.Printf("Submitting WithdrawBalance message for amount %s for address %s\n", types.FIL(amt), from.String())
smsg, err := api.MpoolPushMessage(ctx, &types.Message{
To: builtin.StorageMarketActorAddr,
From: from,
Value: types.NewInt(0),
Method: builtin.MethodsMarket.WithdrawBalance,
Params: params,
}, nil)
if err != nil {
return xerrors.Errorf("submitting WithdrawBalance message: %w", err)
}
fmt.Printf("WithdrawBalance message cid: %s\n", smsg.Cid())
return nil
},
}
+99 -15
View File
@@ -10,6 +10,7 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
@@ -22,8 +23,8 @@ import (
)
const (
LookbackCap = time.Hour * 12
stateWaitLookbackLimit = abi.ChainEpoch(20)
LookbackCap = time.Hour * 24
StateWaitLookbackLimit = abi.ChainEpoch(20)
)
var (
@@ -33,19 +34,29 @@ var (
// gatewayDepsAPI defines the API methods that the GatewayAPI depends on
// (to make it easy to mock for tests)
type gatewayDepsAPI interface {
ChainHasObj(context.Context, cid.Cid) (bool, error)
ChainHead(ctx context.Context) (*types.TipSet, error)
Version(context.Context) (api.Version, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error)
ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error)
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
ChainHasObj(context.Context, cid.Cid) (bool, error)
ChainHead(ctx context.Context) (*types.TipSet, error)
ChainNotify(context.Context) (<-chan []*api.HeadChange, error)
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error)
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
MpoolPushUntrusted(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error)
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error)
StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error)
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error)
StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error)
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error)
@@ -56,22 +67,24 @@ type gatewayDepsAPI interface {
StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error)
StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error)
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error)
}
type GatewayAPI struct {
api gatewayDepsAPI
lookbackCap time.Duration
api gatewayDepsAPI
lookbackCap time.Duration
stateWaitLookbackLimit abi.ChainEpoch
}
// NewGatewayAPI creates a new GatewayAPI with the default lookback cap
func NewGatewayAPI(api gatewayDepsAPI) *GatewayAPI {
return newGatewayAPI(api, LookbackCap)
return newGatewayAPI(api, LookbackCap, StateWaitLookbackLimit)
}
// used by the tests
func newGatewayAPI(api gatewayDepsAPI, lookbackCap time.Duration) *GatewayAPI {
return &GatewayAPI{api: api, lookbackCap: lookbackCap}
func newGatewayAPI(api gatewayDepsAPI, lookbackCap time.Duration, stateWaitLookbackLimit abi.ChainEpoch) *GatewayAPI {
return &GatewayAPI{api: api, lookbackCap: lookbackCap, stateWaitLookbackLimit: stateWaitLookbackLimit}
}
func (a *GatewayAPI) checkTipsetKey(ctx context.Context, tsk types.TipSetKey) error {
@@ -114,6 +127,14 @@ func (a *GatewayAPI) checkTimestamp(at time.Time) error {
return nil
}
func (a *GatewayAPI) Version(ctx context.Context) (api.Version, error) {
return a.api.Version(ctx)
}
func (a *GatewayAPI) ChainGetBlockMessages(ctx context.Context, c cid.Cid) (*api.BlockMessages, error) {
return a.api.ChainGetBlockMessages(ctx, c)
}
func (a *GatewayAPI) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) {
return a.api.ChainHasObj(ctx, c)
}
@@ -124,6 +145,10 @@ func (a *GatewayAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
return a.api.ChainHead(ctx)
}
func (a *GatewayAPI) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
return a.api.ChainGetMessage(ctx, mc)
}
func (a *GatewayAPI) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
return a.api.ChainGetTipSet(ctx, tsk)
}
@@ -157,14 +182,18 @@ func (a *GatewayAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoc
return a.api.ChainGetTipSetByHeight(ctx, h, tsk)
}
func (a *GatewayAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
return a.api.ChainReadObj(ctx, c)
}
func (a *GatewayAPI) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) {
return a.api.ChainGetNode(ctx, p)
}
func (a *GatewayAPI) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) {
return a.api.ChainNotify(ctx)
}
func (a *GatewayAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
return a.api.ChainReadObj(ctx, c)
}
func (a *GatewayAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
@@ -205,6 +234,14 @@ func (a *GatewayAPI) StateAccountKey(ctx context.Context, addr address.Address,
return a.api.StateAccountKey(ctx, addr, tsk)
}
func (a *GatewayAPI) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return api.DealCollateralBounds{}, err
}
return a.api.StateDealProviderCollateralBounds(ctx, size, verified, tsk)
}
func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
@@ -213,6 +250,22 @@ func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, t
return a.api.StateGetActor(ctx, actor, tsk)
}
func (a *GatewayAPI) StateGetReceipt(ctx context.Context, c cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return a.api.StateGetReceipt(ctx, c, tsk)
}
func (a *GatewayAPI) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return a.api.StateListMiners(ctx, tsk)
}
func (a *GatewayAPI) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return address.Undef, err
@@ -221,8 +274,32 @@ func (a *GatewayAPI) StateLookupID(ctx context.Context, addr address.Address, ts
return a.api.StateLookupID(ctx, addr, tsk)
}
func (a *GatewayAPI) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return api.MarketBalance{}, err
}
return a.api.StateMarketBalance(ctx, addr, tsk)
}
func (a *GatewayAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return a.api.StateMarketStorageDeal(ctx, dealId, tsk)
}
func (a *GatewayAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return network.VersionMax, err
}
return a.api.StateNetworkVersion(ctx, tsk)
}
func (a *GatewayAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
return a.api.StateWaitMsgLimited(ctx, msg, confidence, stateWaitLookbackLimit)
return a.api.StateWaitMsgLimited(ctx, msg, confidence, a.stateWaitLookbackLimit)
}
func (a *GatewayAPI) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) {
@@ -288,6 +365,13 @@ func (a *GatewayAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSe
}
func (a *GatewayAPI) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return nil, err
}
return a.api.StateVerifiedClientStatus(ctx, addr, tsk)
}
func (a *GatewayAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return api.CirculatingSupply{}, err
+35 -4
View File
@@ -6,6 +6,9 @@ import (
"testing"
"time"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/build"
"github.com/stretchr/testify/require"
@@ -116,6 +119,38 @@ func (m *mockGatewayDepsAPI) ChainHasObj(context.Context, cid.Cid) (bool, error)
panic("implement me")
}
func (m *mockGatewayDepsAPI) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) StateNetworkVersion(ctx context.Context, key types.TipSetKey) (network.Version, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
m.lk.RLock()
defer m.lk.RUnlock()
@@ -165,10 +200,6 @@ func (m *mockGatewayDepsAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.C
return m.tipsets[h], nil
}
func (m *mockGatewayDepsAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
panic("implement me")
}
+107 -43
View File
@@ -25,12 +25,14 @@ import (
"github.com/filecoin-project/lotus/api/client"
"github.com/filecoin-project/lotus/api/test"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node"
builder "github.com/filecoin-project/lotus/node/test"
)
const maxLookbackCap = time.Duration(math.MaxInt64)
const maxStateWaitLookbackLimit = stmgr.LookbackNoLimit
func init() {
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
@@ -38,15 +40,19 @@ func init() {
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
}
// TestEndToEndWalletMsig tests that wallet and msig API calls can be made
// on a lite node that is connected through a gateway to a full API node
func TestEndToEndWalletMsig(t *testing.T) {
// TestWalletMsig tests that API calls to wallet and msig can be made on a lite
// node that is connected through a gateway to a full API node
func TestWalletMsig(t *testing.T) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
clitest.QuietMiningLogs()
blocktime := 5 * time.Millisecond
ctx := context.Background()
full, lite, closer := startNodes(ctx, t, blocktime, maxLookbackCap)
defer closer()
nodes := startNodes(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit)
defer nodes.closer()
lite := nodes.lite
full := nodes.full
// The full node starts with a wallet
fullWalletAddr, err := full.WalletDefaultAddress(ctx)
@@ -141,56 +147,83 @@ func TestEndToEndWalletMsig(t *testing.T) {
require.True(t, approveReturn.Applied)
}
// TestEndToEndMsigCLI tests that msig CLI calls can be made
// TestMsigCLI tests that msig CLI calls can be made
// on a lite node that is connected through a gateway to a full API node
func TestEndToEndMsigCLI(t *testing.T) {
func TestMsigCLI(t *testing.T) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
clitest.QuietMiningLogs()
blocktime := 5 * time.Millisecond
ctx := context.Background()
full, lite, closer := startNodes(ctx, t, blocktime, maxLookbackCap)
defer closer()
// The full node starts with a wallet
fullWalletAddr, err := full.WalletDefaultAddress(ctx)
require.NoError(t, err)
// Create a wallet on the lite node
liteWalletAddr, err := lite.WalletNew(ctx, types.KTSecp256k1)
require.NoError(t, err)
// Send some funds from the full node to the lite node
err = sendFunds(ctx, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18))
require.NoError(t, err)
nodes := startNodesWithFunds(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit)
defer nodes.closer()
lite := nodes.lite
clitest.RunMultisigTest(t, cli.Commands, lite)
}
func sendFunds(ctx context.Context, fromNode test.TestNode, fromAddr address.Address, toAddr address.Address, amt types.BigInt) error {
msg := &types.Message{
From: fromAddr,
To: toAddr,
Value: amt,
}
func TestDealFlow(t *testing.T) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
clitest.QuietMiningLogs()
sm, err := fromNode.MpoolPushMessage(ctx, msg, nil)
if err != nil {
return err
}
blocktime := 5 * time.Millisecond
ctx := context.Background()
nodes := startNodesWithFunds(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit)
defer nodes.closer()
res, err := fromNode.StateWaitMsg(ctx, sm.Cid(), 1)
if err != nil {
return err
}
if res.Receipt.ExitCode != 0 {
return xerrors.Errorf("send funds failed with exit code %d", res.Receipt.ExitCode)
}
return nil
test.MakeDeal(t, ctx, 6, nodes.lite, nodes.miner, false, false)
}
func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration, lookbackCap time.Duration) (test.TestNode, test.TestNode, jsonrpc.ClientCloser) {
func TestCLIDealFlow(t *testing.T) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
clitest.QuietMiningLogs()
blocktime := 5 * time.Millisecond
ctx := context.Background()
nodes := startNodesWithFunds(ctx, t, blocktime, maxLookbackCap, maxStateWaitLookbackLimit)
defer nodes.closer()
clitest.RunClientTest(t, cli.Commands, nodes.lite)
}
type testNodes struct {
lite test.TestNode
full test.TestNode
miner test.TestStorageNode
closer jsonrpc.ClientCloser
}
func startNodesWithFunds(
ctx context.Context,
t *testing.T,
blocktime time.Duration,
lookbackCap time.Duration,
stateWaitLookbackLimit abi.ChainEpoch,
) *testNodes {
nodes := startNodes(ctx, t, blocktime, lookbackCap, stateWaitLookbackLimit)
// The full node starts with a wallet
fullWalletAddr, err := nodes.full.WalletDefaultAddress(ctx)
require.NoError(t, err)
// Create a wallet on the lite node
liteWalletAddr, err := nodes.lite.WalletNew(ctx, types.KTSecp256k1)
require.NoError(t, err)
// Send some funds from the full node to the lite node
err = sendFunds(ctx, nodes.full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18))
require.NoError(t, err)
return nodes
}
func startNodes(
ctx context.Context,
t *testing.T,
blocktime time.Duration,
lookbackCap time.Duration,
stateWaitLookbackLimit abi.ChainEpoch,
) *testNodes {
var closer jsonrpc.ClientCloser
// Create one miner and two full nodes.
@@ -207,7 +240,8 @@ func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration, look
fullNode := nodes[0]
// Create a gateway server in front of the full node
_, addr, err := builder.CreateRPCServer(newGatewayAPI(fullNode, lookbackCap))
gapiImpl := newGatewayAPI(fullNode, lookbackCap, stateWaitLookbackLimit)
_, addr, err := builder.CreateRPCServer(gapiImpl)
require.NoError(t, err)
// Create a gateway client API that connects to the gateway server
@@ -234,9 +268,39 @@ func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration, look
err = miner.NetConnect(ctx, fullAddr)
require.NoError(t, err)
// Connect the miner and the lite node (so that the lite node can send
// data to the miner)
liteAddr, err := lite.NetAddrsListen(ctx)
require.NoError(t, err)
err = miner.NetConnect(ctx, liteAddr)
require.NoError(t, err)
// Start mining blocks
bm := test.NewBlockMiner(ctx, t, miner, blocktime)
bm.MineBlocks()
return full, lite, closer
return &testNodes{lite: lite, full: full, miner: miner, closer: closer}
}
func sendFunds(ctx context.Context, fromNode test.TestNode, fromAddr address.Address, toAddr address.Address, amt types.BigInt) error {
msg := &types.Message{
From: fromAddr,
To: toAddr,
Value: amt,
}
sm, err := fromNode.MpoolPushMessage(ctx, msg, nil)
if err != nil {
return err
}
res, err := fromNode.StateWaitMsg(ctx, sm.Cid(), 1)
if err != nil {
return err
}
if res.Receipt.ExitCode != 0 {
return xerrors.Errorf("send funds failed with exit code %d", res.Receipt.ExitCode)
}
return nil
}
+14 -1
View File
@@ -7,10 +7,15 @@ import (
"os"
"github.com/filecoin-project/go-jsonrpc"
"go.opencensus.io/tag"
"github.com/filecoin-project/lotus/build"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/lib/lotuslog"
"github.com/filecoin-project/lotus/metrics"
logging "github.com/ipfs/go-log"
"go.opencensus.io/stats/view"
"github.com/gorilla/mux"
"github.com/urfave/cli/v2"
@@ -64,6 +69,13 @@ var runCmd = &cli.Command{
ctx, cancel := context.WithCancel(ctx)
defer cancel()
// Register all metric views
if err := view.Register(
metrics.DefaultViews...,
); err != nil {
log.Fatalf("Cannot register the view: %v", err)
}
api, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
@@ -76,7 +88,7 @@ var runCmd = &cli.Command{
log.Info("Setting up API endpoint at " + address)
rpcServer := jsonrpc.NewServer()
rpcServer.Register("Filecoin", NewGatewayAPI(api))
rpcServer.Register("Filecoin", metrics.MetricedGatewayAPI(NewGatewayAPI(api)))
mux.Handle("/rpc/v0", rpcServer)
mux.PathPrefix("/").Handler(http.DefaultServeMux)
@@ -89,6 +101,7 @@ var runCmd = &cli.Command{
srv := &http.Server{
Handler: mux,
BaseContext: func(listener net.Listener) context.Context {
ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-gateway"))
return ctx
},
}
+12 -1
View File
@@ -18,6 +18,8 @@ import (
logging "github.com/ipfs/go-log/v2"
manet "github.com/multiformats/go-multiaddr/net"
"github.com/urfave/cli/v2"
"go.opencensus.io/stats/view"
"go.opencensus.io/tag"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-jsonrpc"
@@ -34,6 +36,7 @@ import (
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
"github.com/filecoin-project/lotus/lib/lotuslog"
"github.com/filecoin-project/lotus/lib/rpcenc"
"github.com/filecoin-project/lotus/metrics"
"github.com/filecoin-project/lotus/node/repo"
)
@@ -190,6 +193,13 @@ var runCmd = &cli.Command{
ctx, cancel := context.WithCancel(ctx)
defer cancel()
// Register all metric views
if err := view.Register(
metrics.DefaultViews...,
); err != nil {
log.Fatalf("Cannot register the view: %v", err)
}
v, err := nodeApi.Version(ctx)
if err != nil {
return err
@@ -363,7 +373,7 @@ var runCmd = &cli.Command{
readerHandler, readerServerOpt := rpcenc.ReaderParamDecoder()
rpcServer := jsonrpc.NewServer(readerServerOpt)
rpcServer.Register("Filecoin", apistruct.PermissionedWorkerAPI(workerApi))
rpcServer.Register("Filecoin", apistruct.PermissionedWorkerAPI(metrics.MetricedWorkerAPI(workerApi)))
mux.Handle("/rpc/v0", rpcServer)
mux.Handle("/rpc/streams/v0/push/{uuid}", readerHandler)
@@ -378,6 +388,7 @@ var runCmd = &cli.Command{
srv := &http.Server{
Handler: ah,
BaseContext: func(listener net.Listener) context.Context {
ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-worker"))
return ctx
},
}
+14 -7
View File
@@ -7,9 +7,9 @@ import (
"strings"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/big"
"github.com/urfave/cli/v2"
ledgerfil "github.com/whyrusleeping/ledger-filecoin-go"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
@@ -76,15 +76,22 @@ var ledgerListAddressesCmd = &cli.Command{
}
if cctx.Bool("print-balances") && api != nil { // api check makes linter happier
b, err := api.WalletBalance(ctx, addr)
a, err := api.StateGetActor(ctx, addr, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("getting balance: %w", err)
}
if !b.IsZero() {
end = i + 21 // BIP32 spec, stop after 20 empty addresses
if strings.Contains(err.Error(), "actor not found") {
a = nil
} else {
return err
}
}
fmt.Printf("%s %s %s\n", addr, printHDPath(p), types.FIL(b))
balance := big.Zero()
if a != nil {
balance = a.Balance
end = i + 20 + 1
}
fmt.Printf("%s %s %s\n", addr, printHDPath(p), types.FIL(balance))
} else {
fmt.Printf("%s %s\n", addr, printHDPath(p))
}
+1
View File
@@ -45,6 +45,7 @@ func main() {
datastoreCmd,
ledgerCmd,
sectorsCmd,
msgCmd,
}
app := &cli.App{
+280
View File
@@ -0,0 +1,280 @@
package main
import (
"bytes"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/fatih/color"
"github.com/ipfs/go-cid"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig"
)
var msgCmd = &cli.Command{
Name: "msg",
Usage: "Translate message between various formats",
ArgsUsage: "Message in any form",
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 1 {
return xerrors.Errorf("expected 1 argument")
}
msg, err := messageFromString(cctx, cctx.Args().First())
if err != nil {
return err
}
switch msg := msg.(type) {
case *types.SignedMessage:
return printSignedMessage(cctx, msg)
case *types.Message:
return printMessage(cctx, msg)
default:
return xerrors.Errorf("this error message can't be printed")
}
},
}
func printSignedMessage(cctx *cli.Context, smsg *types.SignedMessage) error {
color.Green("Signed:")
color.Blue("CID: %s\n", smsg.Cid())
b, err := smsg.Serialize()
if err != nil {
return err
}
color.Magenta("HEX: %x\n", b)
color.Blue("B64: %s\n", base64.StdEncoding.EncodeToString(b))
jm, err := json.MarshalIndent(smsg, "", " ")
if err != nil {
return xerrors.Errorf("marshaling as json: %w", err)
}
color.Magenta("JSON: %s\n", string(jm))
fmt.Println()
fmt.Println("---")
color.Green("Signed Message Details:")
fmt.Printf("Signature(hex): %x\n", smsg.Signature.Data)
fmt.Printf("Signature(b64): %s\n", base64.StdEncoding.EncodeToString(smsg.Signature.Data))
sigtype, err := smsg.Signature.Type.Name()
if err != nil {
sigtype = err.Error()
}
fmt.Printf("Signature type: %d (%s)\n", smsg.Signature.Type, sigtype)
fmt.Println("-------")
return printMessage(cctx, &smsg.Message)
}
func printMessage(cctx *cli.Context, msg *types.Message) error {
if msg.Version != 0x6d736967 {
color.Green("Unsigned:")
color.Yellow("CID: %s\n", msg.Cid())
b, err := msg.Serialize()
if err != nil {
return err
}
color.Cyan("HEX: %x\n", b)
color.Yellow("B64: %s\n", base64.StdEncoding.EncodeToString(b))
jm, err := json.MarshalIndent(msg, "", " ")
if err != nil {
return xerrors.Errorf("marshaling as json: %w", err)
}
color.Cyan("JSON: %s\n", string(jm))
fmt.Println()
} else {
color.Green("Msig Propose:")
pp := &multisig.ProposeParams{
To: msg.To,
Value: msg.Value,
Method: msg.Method,
Params: msg.Params,
}
var b bytes.Buffer
if err := pp.MarshalCBOR(&b); err != nil {
return err
}
color.Cyan("HEX: %x\n", b.Bytes())
color.Yellow("B64: %s\n", base64.StdEncoding.EncodeToString(b.Bytes()))
jm, err := json.MarshalIndent(pp, "", " ")
if err != nil {
return xerrors.Errorf("marshaling as json: %w", err)
}
color.Cyan("JSON: %s\n", string(jm))
fmt.Println()
}
fmt.Println("---")
color.Green("Message Details:")
fmt.Println("Value:", types.FIL(msg.Value))
fmt.Println("Max Fees:", types.FIL(msg.RequiredFunds()))
fmt.Println("Max Total Cost:", types.FIL(big.Add(msg.RequiredFunds(), msg.Value)))
api, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := lcli.ReqContext(cctx)
toact, err := api.StateGetActor(ctx, msg.To, types.EmptyTSK)
if err != nil {
return nil
}
fmt.Println("Method:", stmgr.MethodsMap[toact.Code][msg.Method].Name)
p, err := lcli.JsonParams(toact.Code, msg.Method, msg.Params)
if err != nil {
return err
}
fmt.Println("Params:", p)
return nil
}
func messageFromString(cctx *cli.Context, smsg string) (types.ChainMsg, error) {
// a CID is least likely to just decode
if c, err := cid.Parse(smsg); err == nil {
return messageFromCID(cctx, c)
}
// try baseX serializations next
{
// hex first, some hay strings may be decodable as b64
if b, err := hex.DecodeString(smsg); err == nil {
return messageFromBytes(cctx, b)
}
// b64 next
if b, err := base64.StdEncoding.DecodeString(smsg); err == nil {
return messageFromBytes(cctx, b)
}
// b64u??
if b, err := base64.URLEncoding.DecodeString(smsg); err == nil {
return messageFromBytes(cctx, b)
}
}
// maybe it's json?
if _, err := messageFromJson(cctx, []byte(smsg)); err == nil {
return nil, err
}
// declare defeat
return nil, xerrors.Errorf("couldn't decode the message")
}
func messageFromJson(cctx *cli.Context, msgb []byte) (types.ChainMsg, error) {
// Unsigned
{
var msg types.Message
if err := json.Unmarshal(msgb, &msg); err == nil {
if msg.To != address.Undef {
return &msg, nil
}
}
}
// Signed
{
var msg types.SignedMessage
if err := json.Unmarshal(msgb, &msg); err == nil {
if msg.Message.To != address.Undef {
return &msg, nil
}
}
}
return nil, xerrors.New("probably not a json-serialized message")
}
func messageFromBytes(cctx *cli.Context, msgb []byte) (types.ChainMsg, error) {
// Signed
{
var msg types.SignedMessage
if err := msg.UnmarshalCBOR(bytes.NewReader(msgb)); err == nil {
return &msg, nil
}
}
// Unsigned
{
var msg types.Message
if err := msg.UnmarshalCBOR(bytes.NewReader(msgb)); err == nil {
return &msg, nil
}
}
// Multisig propose?
{
var pp multisig.ProposeParams
if err := pp.UnmarshalCBOR(bytes.NewReader(msgb)); err == nil {
i, err := address.NewIDAddress(0)
if err != nil {
return nil, err
}
return &types.Message{
// Hack(-ish)
Version: 0x6d736967,
From: i,
To: pp.To,
Value: pp.Value,
Method: pp.Method,
Params: pp.Params,
GasFeeCap: big.Zero(),
GasPremium: big.Zero(),
}, nil
}
}
// Encoded json???
{
if msg, err := messageFromJson(cctx, msgb); err == nil {
return msg, nil
}
}
return nil, xerrors.New("probably not a cbor-serialized message")
}
func messageFromCID(cctx *cli.Context, c cid.Cid) (types.ChainMsg, error) {
api, closer, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return nil, err
}
defer closer()
ctx := lcli.ReqContext(cctx)
msgb, err := api.ChainReadObj(ctx, c)
if err != nil {
return nil, err
}
return messageFromBytes(cctx, msgb)
}
+28 -7
View File
@@ -603,8 +603,6 @@ func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address.
}
func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID, gasPrice types.BigInt, cctx *cli.Context) (address.Address, error) {
log.Info("Creating StorageMarket.CreateStorageMiner message")
var err error
var owner address.Address
if cctx.String("owner") != "" {
@@ -627,9 +625,32 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID,
} else if cctx.Bool("create-worker-key") { // TODO: Do we need to force this if owner is Secpk?
worker, err = api.WalletNew(ctx, types.KTBLS)
}
// TODO: Transfer some initial funds to worker
if err != nil {
return address.Undef, err
return address.Address{}, err
}
// make sure the worker account exists on chain
_, err = api.StateLookupID(ctx, worker, types.EmptyTSK)
if err != nil {
signed, err := api.MpoolPushMessage(ctx, &types.Message{
From: owner,
To: worker,
Value: types.NewInt(0),
}, nil)
if err != nil {
return address.Undef, xerrors.Errorf("push worker init: %w", err)
}
log.Infof("Initializing worker account %s, message: %s", worker, signed.Cid())
log.Infof("Waiting for confirmation")
mw, err := api.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence)
if err != nil {
return address.Undef, xerrors.Errorf("waiting for worker init: %w", err)
}
if mw.Receipt.ExitCode != 0 {
return address.Undef, xerrors.Errorf("initializing worker account failed: exit code %d", mw.Receipt.ExitCode)
}
}
spt, err := ffiwrapper.SealProofTypeFromSectorSize(abi.SectorSize(ssize))
@@ -670,15 +691,15 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID,
signed, err := api.MpoolPushMessage(ctx, createStorageMinerMsg, nil)
if err != nil {
return address.Undef, err
return address.Undef, xerrors.Errorf("pushing createMiner message: %w", err)
}
log.Infof("Pushed StorageMarket.CreateStorageMiner, %s to Mpool", signed.Cid())
log.Infof("Pushed CreateMiner message: %s", signed.Cid())
log.Infof("Waiting for confirmation")
mw, err := api.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence)
if err != nil {
return address.Undef, err
return address.Undef, xerrors.Errorf("waiting for createMiner message: %w", err)
}
if mw.Receipt.ExitCode != 0 {
+19 -2
View File
@@ -2,6 +2,7 @@ package main
import (
"context"
"net"
"net/http"
_ "net/http/pprof"
"os"
@@ -12,6 +13,8 @@ import (
"github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"github.com/urfave/cli/v2"
"go.opencensus.io/stats/view"
"go.opencensus.io/tag"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-jsonrpc"
@@ -22,6 +25,7 @@ import (
"github.com/filecoin-project/lotus/build"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/lib/ulimit"
"github.com/filecoin-project/lotus/metrics"
"github.com/filecoin-project/lotus/node"
"github.com/filecoin-project/lotus/node/impl"
"github.com/filecoin-project/lotus/node/modules/dtypes"
@@ -66,6 +70,13 @@ var runCmd = &cli.Command{
defer ncloser()
ctx := lcli.DaemonContext(cctx)
// Register all metric views
if err := view.Register(
metrics.DefaultViews...,
); err != nil {
log.Fatalf("Cannot register the view: %v", err)
}
v, err := nodeApi.Version(ctx)
if err != nil {
return err
@@ -147,7 +158,7 @@ var runCmd = &cli.Command{
mux := mux.NewRouter()
rpcServer := jsonrpc.NewServer()
rpcServer.Register("Filecoin", apistruct.PermissionedStorMinerAPI(minerapi))
rpcServer.Register("Filecoin", apistruct.PermissionedStorMinerAPI(metrics.MetricedStorMinerAPI(minerapi)))
mux.Handle("/rpc/v0", rpcServer)
mux.PathPrefix("/remote").HandlerFunc(minerapi.(*impl.StorageMinerAPI).ServeRemote)
@@ -158,7 +169,13 @@ var runCmd = &cli.Command{
Next: mux.ServeHTTP,
}
srv := &http.Server{Handler: ah}
srv := &http.Server{
Handler: ah,
BaseContext: func(listener net.Listener) context.Context {
ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-miner"))
return ctx
},
}
sigChan := make(chan os.Signal, 2)
go func() {
+12 -1
View File
@@ -9,6 +9,8 @@ import (
"github.com/gorilla/mux"
logging "github.com/ipfs/go-log/v2"
"github.com/urfave/cli/v2"
"go.opencensus.io/stats/view"
"go.opencensus.io/tag"
"github.com/filecoin-project/go-jsonrpc"
@@ -18,6 +20,7 @@ import (
ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/lib/lotuslog"
"github.com/filecoin-project/lotus/metrics"
"github.com/filecoin-project/lotus/node/repo"
)
@@ -75,6 +78,13 @@ var runCmd = &cli.Command{
ctx, cancel := context.WithCancel(ctx)
defer cancel()
// Register all metric views
if err := view.Register(
metrics.DefaultViews...,
); err != nil {
log.Fatalf("Cannot register the view: %v", err)
}
repoPath := cctx.String(FlagWalletRepo)
r, err := repo.NewFS(repoPath)
if err != nil {
@@ -125,7 +135,7 @@ var runCmd = &cli.Command{
log.Info("Setting up API endpoint at " + address)
rpcServer := jsonrpc.NewServer()
rpcServer.Register("Filecoin", &LoggedWallet{under: w})
rpcServer.Register("Filecoin", &LoggedWallet{under: metrics.MetricedWalletAPI(w)})
mux.Handle("/rpc/v0", rpcServer)
mux.PathPrefix("/").Handler(http.DefaultServeMux) // pprof
@@ -138,6 +148,7 @@ var runCmd = &cli.Command{
srv := &http.Server{
Handler: mux,
BaseContext: func(listener net.Listener) context.Context {
ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-wallet"))
return ctx
},
}
+11 -2
View File
@@ -3,6 +3,7 @@ package main
import (
"context"
"encoding/json"
"net"
"net/http"
_ "net/http/pprof"
"os"
@@ -13,6 +14,7 @@ import (
logging "github.com/ipfs/go-log/v2"
"github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"go.opencensus.io/tag"
"golang.org/x/xerrors"
"contrib.go.opencensus.io/exporter/prometheus"
@@ -22,6 +24,7 @@ import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apistruct"
"github.com/filecoin-project/lotus/metrics"
"github.com/filecoin-project/lotus/node"
"github.com/filecoin-project/lotus/node/impl"
)
@@ -30,7 +33,7 @@ var log = logging.Logger("main")
func serveRPC(a api.FullNode, stop node.StopFunc, addr multiaddr.Multiaddr, shutdownCh <-chan struct{}) error {
rpcServer := jsonrpc.NewServer()
rpcServer.Register("Filecoin", apistruct.PermissionedFullAPI(a))
rpcServer.Register("Filecoin", apistruct.PermissionedFullAPI(metrics.MetricedFullAPI(a)))
ah := &auth.Handler{
Verify: a.AuthVerify,
@@ -60,7 +63,13 @@ func serveRPC(a api.FullNode, stop node.StopFunc, addr multiaddr.Multiaddr, shut
return xerrors.Errorf("could not listen: %w", err)
}
srv := &http.Server{Handler: http.DefaultServeMux}
srv := &http.Server{
Handler: http.DefaultServeMux,
BaseContext: func(listener net.Listener) context.Context {
ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-daemon"))
return ctx
},
}
sigCh := make(chan os.Signal, 2)
shutdownDone := make(chan struct{})
+53 -55
View File
@@ -19,7 +19,6 @@ import (
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/conformance"
"github.com/filecoin-project/test-vectors/schema"
@@ -34,13 +33,14 @@ const (
)
type extractOpts struct {
id string
block string
class string
cid string
file string
retain string
precursor string
id string
block string
class string
cid string
file string
retain string
precursor string
ignoreSanityChecks bool
}
var extractFlags extractOpts
@@ -49,6 +49,8 @@ var extractCmd = &cli.Command{
Name: "extract",
Description: "generate a test vector by extracting it from a live chain",
Action: runExtract,
Before: initialize,
After: destroy,
Flags: []cli.Flag{
&repoFlag,
&cli.StringFlag{
@@ -88,53 +90,42 @@ var extractCmd = &cli.Command{
},
&cli.StringFlag{
Name: "precursor-select",
Usage: "precursors to apply; values: 'all', 'sender'; 'all' selects all preceding" +
"messages in the canonicalised tipset, 'sender' selects only preceding messages from the same" +
"sender. Usually, 'sender' is a good tradeoff and gives you sufficient accuracy. If the receipt sanity" +
"check fails due to gas reasons, switch to 'all', as previous messages in the tipset may have" +
Usage: "precursors to apply; values: 'all', 'sender'; 'all' selects all preceding " +
"messages in the canonicalised tipset, 'sender' selects only preceding messages from the same " +
"sender. Usually, 'sender' is a good tradeoff and gives you sufficient accuracy. If the receipt sanity " +
"check fails due to gas reasons, switch to 'all', as previous messages in the tipset may have " +
"affected state in a disruptive way",
Value: "sender",
Destination: &extractFlags.precursor,
},
&cli.BoolFlag{
Name: "ignore-sanity-checks",
Usage: "generate vector even if sanity checks fail",
Value: false,
Destination: &extractFlags.ignoreSanityChecks,
},
},
}
func runExtract(c *cli.Context) error {
// LOTUS_DISABLE_VM_BUF disables what's called "VM state tree buffering",
// which stashes write operations in a BufferedBlockstore
// (https://github.com/filecoin-project/lotus/blob/b7a4dbb07fd8332b4492313a617e3458f8003b2a/lib/bufbstore/buf_bstore.go#L21)
// such that they're not written until the VM is actually flushed.
//
// For some reason, the standard behaviour was not working for me (raulk),
// and disabling it (such that the state transformations are written immediately
// to the blockstore) worked.
_ = os.Setenv("LOTUS_DISABLE_VM_BUF", "iknowitsabadidea")
ctx := context.Background()
// Make the API client.
fapi, closer, err := lcli.GetFullNodeAPI(c)
if err != nil {
return err
}
defer closer()
return doExtract(ctx, fapi, extractFlags)
func runExtract(_ *cli.Context) error {
return doExtract(extractFlags)
}
func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
func doExtract(opts extractOpts) error {
ctx := context.Background()
mcid, err := cid.Decode(opts.cid)
if err != nil {
return err
}
msg, execTs, incTs, err := resolveFromChain(ctx, fapi, mcid, opts.block)
msg, execTs, incTs, err := resolveFromChain(ctx, FullAPI, mcid, opts.block)
if err != nil {
return fmt.Errorf("failed to resolve message and tipsets from chain: %w", err)
}
// get the circulating supply before the message was executed.
circSupplyDetail, err := fapi.StateVMCirculatingSupplyInternal(ctx, incTs.Key())
circSupplyDetail, err := FullAPI.StateVMCirculatingSupplyInternal(ctx, incTs.Key())
if err != nil {
return fmt.Errorf("failed while fetching circulating supply: %w", err)
}
@@ -147,7 +138,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
log.Printf("finding precursor messages using mode: %s", opts.precursor)
// Fetch messages in canonical order from inclusion tipset.
msgs, err := fapi.ChainGetParentMessages(ctx, execTs.Blocks()[0].Cid())
msgs, err := FullAPI.ChainGetParentMessages(ctx, execTs.Blocks()[0].Cid())
if err != nil {
return fmt.Errorf("failed to fetch messages in canonical order from inclusion tipset: %w", err)
}
@@ -174,8 +165,8 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
var (
// create a read-through store that uses ChainGetObject to fetch unknown CIDs.
pst = NewProxyingStores(ctx, fapi)
g = NewSurgeon(ctx, fapi, pst)
pst = NewProxyingStores(ctx, FullAPI)
g = NewSurgeon(ctx, FullAPI, pst)
)
driver := conformance.NewDriver(ctx, schema.Selector{}, conformance.DriverOpts{
@@ -200,7 +191,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
CircSupply: circSupplyDetail.FilCirculating,
BaseFee: basefee,
// recorded randomness will be discarded.
Rand: conformance.NewRecordingRand(new(conformance.LogReporter), fapi),
Rand: conformance.NewRecordingRand(new(conformance.LogReporter), FullAPI),
})
if err != nil {
return fmt.Errorf("failed to execute precursor message: %w", err)
@@ -215,7 +206,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
retention = opts.retain
// recordingRand will record randomness so we can embed it in the test vector.
recordingRand = conformance.NewRecordingRand(new(conformance.LogReporter), fapi)
recordingRand = conformance.NewRecordingRand(new(conformance.LogReporter), FullAPI)
)
log.Printf("using state retention strategy: %s", retention)
@@ -248,7 +239,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
case "accessed-actors":
log.Printf("calculating accessed actors")
// get actors accessed by message.
retain, err := g.GetAccessedActors(ctx, fapi, mcid)
retain, err := g.GetAccessedActors(ctx, FullAPI, mcid)
if err != nil {
return fmt.Errorf("failed to calculate accessed actors: %w", err)
}
@@ -286,7 +277,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
// TODO sometimes this returns a nil receipt and no error ¯\_(ツ)_/¯
// ex: https://filfox.info/en/message/bafy2bzacebpxw3yiaxzy2bako62akig46x3imji7fewszen6fryiz6nymu2b2
// This code is lenient and skips receipt comparison in case of a nil receipt.
rec, err := fapi.StateGetReceipt(ctx, mcid, execTs.Key())
rec, err := FullAPI.StateGetReceipt(ctx, mcid, execTs.Key())
if err != nil {
return fmt.Errorf("failed to find receipt on chain: %w", err)
}
@@ -300,13 +291,20 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
ReturnValue: rec.Return,
GasUsed: rec.GasUsed,
}
reporter := new(conformance.LogReporter)
conformance.AssertMsgResult(reporter, receipt, applyret, "as locally executed")
if reporter.Failed() {
log.Println(color.RedString("receipt sanity check failed; aborting"))
return fmt.Errorf("vector generation aborted")
if opts.ignoreSanityChecks {
log.Println(color.YellowString("receipt sanity check failed; proceeding anyway"))
} else {
log.Println(color.RedString("receipt sanity check failed; aborting"))
return fmt.Errorf("vector generation aborted")
}
} else {
log.Println(color.GreenString("receipt sanity check succeeded"))
}
log.Println(color.GreenString("receipt sanity check succeeded"))
} else {
receipt = &schema.Receipt{
ExitCode: int64(applyret.ExitCode),
@@ -336,17 +334,17 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
return err
}
version, err := fapi.Version(ctx)
version, err := FullAPI.Version(ctx)
if err != nil {
return err
}
ntwkName, err := fapi.StateNetworkName(ctx)
ntwkName, err := FullAPI.StateNetworkName(ctx)
if err != nil {
return err
}
nv, err := fapi.StateNetworkVersion(ctx, execTs.Key())
nv, err := FullAPI.StateNetworkVersion(ctx, execTs.Key())
if err != nil {
return err
}
@@ -399,8 +397,12 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
},
}
return writeVector(vector, opts.file)
}
func writeVector(vector schema.TestVector, file string) (err error) {
output := io.WriteCloser(os.Stdout)
if file := opts.file; file != "" {
if file := file; file != "" {
dir := filepath.Dir(file)
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("unable to create directory %s: %w", dir, err)
@@ -415,11 +417,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
enc := json.NewEncoder(output)
enc.SetIndent("", " ")
if err := enc.Encode(&vector); err != nil {
return err
}
return nil
return enc.Encode(&vector)
}
// resolveFromChain queries the chain for the provided message, using the block CID to
+5 -14
View File
@@ -1,7 +1,6 @@
package main
import (
"context"
"encoding/csv"
"fmt"
"io"
@@ -20,7 +19,6 @@ import (
"github.com/urfave/cli/v2"
"github.com/filecoin-project/lotus/chain/stmgr"
lcli "github.com/filecoin-project/lotus/cli"
)
var extractManyFlags struct {
@@ -45,6 +43,8 @@ var extractManyCmd = &cli.Command{
after these compulsory seven.
`,
Action: runExtractMany,
Before: initialize,
After: destroy,
Flags: []cli.Flag{
&repoFlag,
&cli.StringFlag{
@@ -77,15 +77,6 @@ func runExtractMany(c *cli.Context) error {
// to the blockstore) worked.
_ = os.Setenv("LOTUS_DISABLE_VM_BUF", "iknowitsabadidea")
ctx := context.Background()
// Make the API client.
fapi, closer, err := lcli.GetFullNodeAPI(c)
if err != nil {
return err
}
defer closer()
var (
in = extractManyFlags.in
outdir = extractManyFlags.outdir
@@ -198,8 +189,8 @@ func runExtractMany(c *cli.Context) error {
precursor: PrecursorSelectSender,
}
if err := doExtract(ctx, fapi, opts); err != nil {
log.Println(color.RedString("failed to extract vector for message %s: %s; queuing for 'canonical' precursor selection", mcid, err))
if err := doExtract(opts); err != nil {
log.Println(color.RedString("failed to extract vector for message %s: %s; queuing for 'all' precursor selection", mcid, err))
retry = append(retry, opts)
continue
}
@@ -215,7 +206,7 @@ func runExtractMany(c *cli.Context) error {
log.Printf("retrying %s: %s", r.cid, r.id)
r.precursor = PrecursorSelectAll
if err := doExtract(ctx, fapi, r); err != nil {
if err := doExtract(r); err != nil {
merr = multierror.Append(merr, fmt.Errorf("failed to extract vector for message %s: %w", r.cid, err))
continue
}
+45 -1
View File
@@ -1,13 +1,26 @@
package main
import (
"fmt"
"log"
"os"
"sort"
"github.com/filecoin-project/go-jsonrpc"
"github.com/urfave/cli/v2"
"github.com/filecoin-project/lotus/api"
lcli "github.com/filecoin-project/lotus/cli"
)
// FullAPI is a JSON-RPC client targeting a full node. It's initialized in a
// cli.BeforeFunc.
var FullAPI api.FullNode
// Closer is the closer for the JSON-RPC client, which must be called on
// cli.AfterFunc.
var Closer jsonrpc.ClientCloser
// DefaultLotusRepoPath is where the fallback path where to look for a Lotus
// client repo. It is expanded with mitchellh/go-homedir, so it'll work with all
// OSes despite the Unix twiddle notation.
@@ -23,7 +36,7 @@ var repoFlag = cli.StringFlag{
func main() {
app := &cli.App{
Name: "tvx",
Description: `tvx is a tool for extracting and executing test vectors. It has three subcommands.
Description: `tvx is a tool for extracting and executing test vectors. It has four subcommands.
tvx extract extracts a test vector from a live network. It requires access to
a Filecoin client that exposes the standard JSON-RPC API endpoint. Only
@@ -35,6 +48,10 @@ func main() {
tvx extract-many performs a batch extraction of many messages, supplied in a
CSV file. Refer to the help of that subcommand for more info.
tvx simulate takes a raw message and simulates it on top of the supplied
epoch, reporting the result on stderr and writing a test vector on stdout
or into the specified file.
SETTING THE JSON-RPC API ENDPOINT
You can set the JSON-RPC API endpoint through one of the following methods.
@@ -57,6 +74,7 @@ func main() {
extractCmd,
execCmd,
extractManyCmd,
simulateCmd,
},
}
@@ -69,3 +87,29 @@ func main() {
log.Fatal(err)
}
}
func initialize(c *cli.Context) error {
// LOTUS_DISABLE_VM_BUF disables what's called "VM state tree buffering",
// which stashes write operations in a BufferedBlockstore
// (https://github.com/filecoin-project/lotus/blob/b7a4dbb07fd8332b4492313a617e3458f8003b2a/lib/bufbstore/buf_bstore.go#L21)
// such that they're not written until the VM is actually flushed.
//
// For some reason, the standard behaviour was not working for me (raulk),
// and disabling it (such that the state transformations are written immediately
// to the blockstore) worked.
_ = os.Setenv("LOTUS_DISABLE_VM_BUF", "iknowitsabadidea")
// Make the API client.
var err error
if FullAPI, Closer, err = lcli.GetFullNodeAPI(c); err != nil {
err = fmt.Errorf("failed to locate Lotus node; ")
}
return err
}
func destroy(_ *cli.Context) error {
if Closer != nil {
Closer()
}
return nil
}
+235
View File
@@ -0,0 +1,235 @@
package main
import (
"bytes"
"compress/gzip"
"context"
"encoding/base64"
"encoding/json"
"fmt"
"log"
"os/exec"
"github.com/fatih/color"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/test-vectors/schema"
"github.com/urfave/cli/v2"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/conformance"
)
var simulateFlags struct {
msg string
epoch int64
out string
statediff bool
}
var simulateCmd = &cli.Command{
Name: "simulate",
Description: "simulate a raw message on top of the supplied epoch (or HEAD), " +
"reporting the result on stderr and writing a test vector on stdout " +
"or into the specified file",
Action: runSimulateCmd,
Before: initialize,
After: destroy,
Flags: []cli.Flag{
&repoFlag,
&cli.StringFlag{
Name: "msg",
Usage: "base64 cbor-encoded message",
Destination: &simulateFlags.msg,
Required: true,
},
&cli.Int64Flag{
Name: "at-epoch",
Usage: "epoch at which to run this message (or HEAD if not provided)",
Destination: &simulateFlags.epoch,
},
&cli.StringFlag{
Name: "out",
Usage: "file to write the test vector to; if nil, the vector will be written to stdout",
TakesFile: true,
Destination: &simulateFlags.out,
},
&cli.BoolFlag{
Name: "statediff",
Usage: "display a statediff of the precondition and postcondition states",
Destination: &simulateFlags.statediff,
},
},
}
func runSimulateCmd(_ *cli.Context) error {
ctx := context.Background()
r := new(conformance.LogReporter)
msgb, err := base64.StdEncoding.DecodeString(simulateFlags.msg)
if err != nil {
return fmt.Errorf("failed to base64-decode message: %w", err)
}
msg, err := types.DecodeMessage(msgb)
if err != nil {
return fmt.Errorf("failed to deserialize message: %w", err)
}
log.Printf("message to simulate has CID: %s", msg.Cid())
msgjson, err := json.Marshal(msg)
if err != nil {
return fmt.Errorf("failed to serialize message to json for printing: %w", err)
}
log.Printf("message to simulate: %s", string(msgjson))
// Resolve the tipset, root, epoch.
var ts *types.TipSet
if epochIn := simulateFlags.epoch; epochIn == 0 {
ts, err = FullAPI.ChainHead(ctx)
} else {
ts, err = FullAPI.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(epochIn), types.EmptyTSK)
}
if err != nil {
return fmt.Errorf("failed to get tipset: %w", err)
}
var (
preroot = ts.ParentState()
epoch = ts.Height()
baseFee = ts.Blocks()[0].ParentBaseFee
circSupply api.CirculatingSupply
)
// Get circulating supply.
circSupply, err = FullAPI.StateVMCirculatingSupplyInternal(ctx, ts.Key())
if err != nil {
return fmt.Errorf("failed to get circulating supply for tipset %s: %w", ts.Key(), err)
}
// Create the driver.
stores := NewProxyingStores(ctx, FullAPI)
driver := conformance.NewDriver(ctx, schema.Selector{}, conformance.DriverOpts{
DisableVMFlush: true,
})
rand := conformance.NewRecordingRand(r, FullAPI)
tbs, ok := stores.Blockstore.(TracingBlockstore)
if !ok {
return fmt.Errorf("no tracing blockstore available")
}
tbs.StartTracing()
applyret, postroot, err := driver.ExecuteMessage(stores.Blockstore, conformance.ExecuteMessageParams{
Preroot: preroot,
Epoch: epoch,
Message: msg,
CircSupply: circSupply.FilCirculating,
BaseFee: baseFee,
Rand: rand,
})
if err != nil {
return fmt.Errorf("failed to apply message: %w", err)
}
accessed := tbs.FinishTracing()
var (
out = new(bytes.Buffer)
gw = gzip.NewWriter(out)
g = NewSurgeon(ctx, FullAPI, stores)
)
if err := g.WriteCARIncluding(gw, accessed, preroot, postroot); err != nil {
return err
}
if err = gw.Flush(); err != nil {
return err
}
if err = gw.Close(); err != nil {
return err
}
version, err := FullAPI.Version(ctx)
if err != nil {
log.Printf("failed to get node version: %s; falling back to unknown", err)
version = api.Version{}
}
nv, err := FullAPI.StateNetworkVersion(ctx, ts.Key())
if err != nil {
return err
}
codename := GetProtocolCodename(epoch)
// Write out the test vector.
vector := schema.TestVector{
Class: schema.ClassMessage,
Meta: &schema.Metadata{
ID: fmt.Sprintf("simulated-%s", msg.Cid()),
Gen: []schema.GenerationData{
{Source: "github.com/filecoin-project/lotus", Version: version.String()}},
},
Selector: schema.Selector{
schema.SelectorMinProtocolVersion: codename,
},
Randomness: rand.Recorded(),
CAR: out.Bytes(),
Pre: &schema.Preconditions{
Variants: []schema.Variant{
{ID: codename, Epoch: int64(epoch), NetworkVersion: uint(nv)},
},
CircSupply: circSupply.FilCirculating.Int,
BaseFee: baseFee.Int,
StateTree: &schema.StateTree{
RootCID: preroot,
},
},
ApplyMessages: []schema.Message{{Bytes: msgb}},
Post: &schema.Postconditions{
StateTree: &schema.StateTree{
RootCID: postroot,
},
Receipts: []*schema.Receipt{
{
ExitCode: int64(applyret.ExitCode),
ReturnValue: applyret.Return,
GasUsed: applyret.GasUsed,
},
},
},
}
if err := writeVector(vector, simulateFlags.out); err != nil {
return fmt.Errorf("failed to write vector: %w", err)
}
log.Printf(color.GreenString("wrote vector at: %s"), simulateFlags.out)
if !simulateFlags.statediff {
return nil
}
if simulateFlags.out == "" {
log.Print("omitting statediff in non-file mode")
return nil
}
// check if statediff is installed; if not, skip.
if err := exec.Command("statediff", "--help").Run(); err != nil {
log.Printf("could not perform statediff on generated vector; command not found (%s)", err)
log.Printf("install statediff with:")
log.Printf("$ GOMODULE111=off go get github.com/filecoin-project/statediff/cmd/statediff")
return err
}
stdiff, err := exec.Command("statediff", "vector", "--file", simulateFlags.out).CombinedOutput()
if err != nil {
return fmt.Errorf("failed to statediff: %w", err)
}
log.Print(string(stdiff))
return nil
}
+1 -1
View File
@@ -248,7 +248,7 @@ func BaseFeeOrDefault(basefee *gobig.Int) abi.TokenAmount {
// DefaultCirculatingSupply.
func CircSupplyOrDefault(circSupply *gobig.Int) abi.TokenAmount {
if circSupply == nil {
return DefaultBaseFee
return DefaultCirculatingSupply
}
return big.NewFromGo(circSupply)
}
+4 -4
View File
@@ -14,14 +14,14 @@ import (
// FaultTracker TODO: Track things more actively
type FaultTracker interface {
CheckProvable(ctx context.Context, spt abi.RegisteredSealProof, sectors []abi.SectorID) ([]abi.SectorID, error)
CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []abi.SectorID) ([]abi.SectorID, error)
}
// CheckProvable returns unprovable sectors
func (m *Manager) CheckProvable(ctx context.Context, spt abi.RegisteredSealProof, sectors []abi.SectorID) ([]abi.SectorID, error) {
func (m *Manager) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []abi.SectorID) ([]abi.SectorID, error) {
var bad []abi.SectorID
ssize, err := spt.SectorSize()
ssize, err := pp.SectorSize()
if err != nil {
return nil, err
}
@@ -43,7 +43,7 @@ func (m *Manager) CheckProvable(ctx context.Context, spt abi.RegisteredSealProof
return nil
}
lp, _, err := m.localStore.AcquireSector(ctx, sector, spt, stores.FTSealed|stores.FTCache, stores.FTNone, stores.PathStorage, stores.AcquireMove)
lp, _, err := m.localStore.AcquireSector(ctx, sector, ssize, stores.FTSealed|stores.FTCache, stores.FTNone, stores.PathStorage, stores.AcquireMove)
if err != nil {
log.Warnw("CheckProvable Sector FAULT: acquire sector in checkProvable", "sector", sector, "error", err)
bad = append(bad, sector)
+11 -3
View File
@@ -65,12 +65,16 @@ type localWorkerPathProvider struct {
func (l *localWorkerPathProvider) AcquireSector(ctx context.Context, sector abi.SectorID, existing stores.SectorFileType, allocate stores.SectorFileType, sealing stores.PathType) (stores.SectorPaths, func(), error) {
paths, storageIDs, err := l.w.storage.AcquireSector(ctx, sector, l.w.scfg.SealProofType, existing, allocate, sealing, l.op)
ssize, err := l.w.scfg.SealProofType.SectorSize()
if err != nil {
return stores.SectorPaths{}, nil, err
}
paths, storageIDs, err := l.w.storage.AcquireSector(ctx, sector, ssize, existing, allocate, sealing, l.op)
if err != nil {
return stores.SectorPaths{}, nil, err
}
releaseStorage, err := l.w.localStore.Reserve(ctx, sector, l.w.scfg.SealProofType, allocate, storageIDs, stores.FSOverheadSeal)
releaseStorage, err := l.w.localStore.Reserve(ctx, sector, ssize, allocate, storageIDs, stores.FSOverheadSeal)
if err != nil {
return stores.SectorPaths{}, nil, xerrors.Errorf("reserving storage space: %w", err)
}
@@ -212,7 +216,11 @@ func (l *LocalWorker) Remove(ctx context.Context, sector abi.SectorID) error {
}
func (l *LocalWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) error {
if err := l.storage.MoveStorage(ctx, sector, l.scfg.SealProofType, types); err != nil {
ssize, err := l.scfg.SealProofType.SectorSize()
if err != nil {
return err
}
if err := l.storage.MoveStorage(ctx, sector, ssize, types); err != nil {
return xerrors.Errorf("moving sealed data to storage: %w", err)
}
+1 -1
View File
@@ -95,7 +95,7 @@ func New(ctx context.Context, ls stores.LocalStorage, si stores.SectorIndex, cfg
return nil, err
}
prover, err := ffiwrapper.New(&readonlyProvider{stor: lstor, index: si}, cfg)
prover, err := ffiwrapper.New(&readonlyProvider{stor: lstor, index: si, spt: cfg.SealProofType}, cfg)
if err != nil {
return nil, xerrors.Errorf("creating prover instance: %w", err)
}
+1 -1
View File
@@ -92,7 +92,7 @@ func newTestMgr(ctx context.Context, t *testing.T) (*Manager, *stores.Local, *st
lstor, err := stores.NewLocal(ctx, st, si, nil)
require.NoError(t, err)
prover, err := ffiwrapper.New(&readonlyProvider{stor: lstor}, cfg)
prover, err := ffiwrapper.New(&readonlyProvider{stor: lstor, spt: cfg.SealProofType}, cfg)
require.NoError(t, err)
stor := stores.NewRemote(lstor, si, nil, 6000)
+1 -1
View File
@@ -392,7 +392,7 @@ func (mgr *SectorMgr) Remove(ctx context.Context, sector abi.SectorID) error {
return nil
}
func (mgr *SectorMgr) CheckProvable(ctx context.Context, spt abi.RegisteredSealProof, ids []abi.SectorID) ([]abi.SectorID, error) {
func (mgr *SectorMgr) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, ids []abi.SectorID) ([]abi.SectorID, error) {
var bad []abi.SectorID
for _, sid := range ids {
+6 -1
View File
@@ -21,6 +21,11 @@ func (l *readonlyProvider) AcquireSector(ctx context.Context, id abi.SectorID, e
return stores.SectorPaths{}, nil, xerrors.New("read-only storage")
}
ssize, err := l.spt.SectorSize()
if err != nil {
return stores.SectorPaths{}, nil, xerrors.Errorf("failed to determine sector size: %w", err)
}
ctx, cancel := context.WithCancel(ctx)
// use TryLock to avoid blocking
@@ -34,7 +39,7 @@ func (l *readonlyProvider) AcquireSector(ctx context.Context, id abi.SectorID, e
return stores.SectorPaths{}, nil, xerrors.Errorf("failed to acquire sector lock")
}
p, _, err := l.stor.AcquireSector(ctx, id, l.spt, existing, allocate, sealing, stores.AcquireMove)
p, _, err := l.stor.AcquireSector(ctx, id, ssize, existing, allocate, sealing, stores.AcquireMove)
return p, cancel, err
}
+6 -1
View File
@@ -44,7 +44,12 @@ func (s *allocSelector) Ok(ctx context.Context, task sealtasks.TaskType, spt abi
have[path.ID] = struct{}{}
}
best, err := s.index.StorageBestAlloc(ctx, s.alloc, spt, s.ptype)
ssize, err := spt.SectorSize()
if err != nil {
return false, xerrors.Errorf("getting sector size: %w", err)
}
best, err := s.index.StorageBestAlloc(ctx, s.alloc, ssize, s.ptype)
if err != nil {
return false, xerrors.Errorf("finding best alloc storage: %w", err)
}
+6 -1
View File
@@ -46,7 +46,12 @@ func (s *existingSelector) Ok(ctx context.Context, task sealtasks.TaskType, spt
have[path.ID] = struct{}{}
}
best, err := s.index.StorageFindSector(ctx, s.sector, s.alloc, spt, s.allowFetch)
ssize, err := spt.SectorSize()
if err != nil {
return false, xerrors.Errorf("getting sector size: %w", err)
}
best, err := s.index.StorageFindSector(ctx, s.sector, s.alloc, ssize, s.allowFetch)
if err != nil {
return false, xerrors.Errorf("finding best storage: %w", err)
}
+1 -6
View File
@@ -53,12 +53,7 @@ func (t SectorFileType) Has(singleType SectorFileType) bool {
return t&singleType == singleType
}
func (t SectorFileType) SealSpaceUse(spt abi.RegisteredSealProof) (uint64, error) {
ssize, err := spt.SectorSize()
if err != nil {
return 0, xerrors.Errorf("getting sector size: %w", err)
}
func (t SectorFileType) SealSpaceUse(ssize abi.SectorSize) (uint64, error) {
var need uint64
for _, pathType := range PathTypes {
if !t.Has(pathType) {
+6 -6
View File
@@ -55,9 +55,9 @@ type SectorIndex interface { // part of storage-miner api
StorageDeclareSector(ctx context.Context, storageID ID, s abi.SectorID, ft SectorFileType, primary bool) error
StorageDropSector(ctx context.Context, storageID ID, s abi.SectorID, ft SectorFileType) error
StorageFindSector(ctx context.Context, sector abi.SectorID, ft SectorFileType, spt abi.RegisteredSealProof, allowFetch bool) ([]SectorStorageInfo, error)
StorageFindSector(ctx context.Context, sector abi.SectorID, ft SectorFileType, ssize abi.SectorSize, allowFetch bool) ([]SectorStorageInfo, error)
StorageBestAlloc(ctx context.Context, allocate SectorFileType, spt abi.RegisteredSealProof, pathType PathType) ([]StorageInfo, error)
StorageBestAlloc(ctx context.Context, allocate SectorFileType, ssize abi.SectorSize, pathType PathType) ([]StorageInfo, error)
// atomically acquire locks on all sector file types. close ctx to unlock
StorageLock(ctx context.Context, sector abi.SectorID, read SectorFileType, write SectorFileType) error
@@ -246,7 +246,7 @@ func (i *Index) StorageDropSector(ctx context.Context, storageID ID, s abi.Secto
return nil
}
func (i *Index) StorageFindSector(ctx context.Context, s abi.SectorID, ft SectorFileType, spt abi.RegisteredSealProof, allowFetch bool) ([]SectorStorageInfo, error) {
func (i *Index) StorageFindSector(ctx context.Context, s abi.SectorID, ft SectorFileType, ssize abi.SectorSize, allowFetch bool) ([]SectorStorageInfo, error) {
i.lk.RLock()
defer i.lk.RUnlock()
@@ -297,7 +297,7 @@ func (i *Index) StorageFindSector(ctx context.Context, s abi.SectorID, ft Sector
}
if allowFetch {
spaceReq, err := ft.SealSpaceUse(spt)
spaceReq, err := ft.SealSpaceUse(ssize)
if err != nil {
return nil, xerrors.Errorf("estimating required space: %w", err)
}
@@ -365,13 +365,13 @@ func (i *Index) StorageInfo(ctx context.Context, id ID) (StorageInfo, error) {
return *si.info, nil
}
func (i *Index) StorageBestAlloc(ctx context.Context, allocate SectorFileType, spt abi.RegisteredSealProof, pathType PathType) ([]StorageInfo, error) {
func (i *Index) StorageBestAlloc(ctx context.Context, allocate SectorFileType, ssize abi.SectorSize, pathType PathType) ([]StorageInfo, error) {
i.lk.RLock()
defer i.lk.RUnlock()
var candidates []storageEntry
spaceReq, err := allocate.SealSpaceUse(spt)
spaceReq, err := allocate.SealSpaceUse(ssize)
if err != nil {
return nil, xerrors.Errorf("estimating required space: %w", err)
}
+2 -2
View File
@@ -22,7 +22,7 @@ const (
)
type Store interface {
AcquireSector(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, existing SectorFileType, allocate SectorFileType, sealing PathType, op AcquireMode) (paths SectorPaths, stores SectorPaths, err error)
AcquireSector(ctx context.Context, s abi.SectorID, ssize abi.SectorSize, existing SectorFileType, allocate SectorFileType, sealing PathType, op AcquireMode) (paths SectorPaths, stores SectorPaths, err error)
Remove(ctx context.Context, s abi.SectorID, types SectorFileType, force bool) error
// like remove, but doesn't remove the primary sector copy, nor the last
@@ -30,7 +30,7 @@ type Store interface {
RemoveCopies(ctx context.Context, s abi.SectorID, types SectorFileType) error
// move sectors into storage
MoveStorage(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, types SectorFileType) error
MoveStorage(ctx context.Context, s abi.SectorID, ssize abi.SectorSize, types SectorFileType) error
FsStat(ctx context.Context, id ID) (fsutil.FsStat, error)
}
+7 -12
View File
@@ -269,12 +269,7 @@ func (st *Local) reportHealth(ctx context.Context) {
}
}
func (st *Local) Reserve(ctx context.Context, sid abi.SectorID, spt abi.RegisteredSealProof, ft SectorFileType, storageIDs SectorPaths, overheadTab map[SectorFileType]int) (func(), error) {
ssize, err := spt.SectorSize()
if err != nil {
return nil, xerrors.Errorf("getting sector size: %w", err)
}
func (st *Local) Reserve(ctx context.Context, sid abi.SectorID, ssize abi.SectorSize, ft SectorFileType, storageIDs SectorPaths, overheadTab map[SectorFileType]int) (func(), error) {
st.localLk.Lock()
done := func() {}
@@ -324,7 +319,7 @@ func (st *Local) Reserve(ctx context.Context, sid abi.SectorID, spt abi.Register
return done, nil
}
func (st *Local) AcquireSector(ctx context.Context, sid abi.SectorID, spt abi.RegisteredSealProof, existing SectorFileType, allocate SectorFileType, pathType PathType, op AcquireMode) (SectorPaths, SectorPaths, error) {
func (st *Local) AcquireSector(ctx context.Context, sid abi.SectorID, ssize abi.SectorSize, existing SectorFileType, allocate SectorFileType, pathType PathType, op AcquireMode) (SectorPaths, SectorPaths, error) {
if existing|allocate != existing^allocate {
return SectorPaths{}, SectorPaths{}, xerrors.New("can't both find and allocate a sector")
}
@@ -340,7 +335,7 @@ func (st *Local) AcquireSector(ctx context.Context, sid abi.SectorID, spt abi.Re
continue
}
si, err := st.index.StorageFindSector(ctx, sid, fileType, spt, false)
si, err := st.index.StorageFindSector(ctx, sid, fileType, ssize, false)
if err != nil {
log.Warnf("finding existing sector %d(t:%d) failed: %+v", sid, fileType, err)
continue
@@ -370,7 +365,7 @@ func (st *Local) AcquireSector(ctx context.Context, sid abi.SectorID, spt abi.Re
continue
}
sis, err := st.index.StorageBestAlloc(ctx, fileType, spt, pathType)
sis, err := st.index.StorageBestAlloc(ctx, fileType, ssize, pathType)
if err != nil {
return SectorPaths{}, SectorPaths{}, xerrors.Errorf("finding best storage for allocating : %w", err)
}
@@ -525,13 +520,13 @@ func (st *Local) removeSector(ctx context.Context, sid abi.SectorID, typ SectorF
return nil
}
func (st *Local) MoveStorage(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, types SectorFileType) error {
dest, destIds, err := st.AcquireSector(ctx, s, spt, FTNone, types, PathStorage, AcquireMove)
func (st *Local) MoveStorage(ctx context.Context, s abi.SectorID, ssize abi.SectorSize, types SectorFileType) error {
dest, destIds, err := st.AcquireSector(ctx, s, ssize, FTNone, types, PathStorage, AcquireMove)
if err != nil {
return xerrors.Errorf("acquire dest storage: %w", err)
}
src, srcIds, err := st.AcquireSector(ctx, s, spt, types, FTNone, PathStorage, AcquireMove)
src, srcIds, err := st.AcquireSector(ctx, s, ssize, types, FTNone, PathStorage, AcquireMove)
if err != nil {
return xerrors.Errorf("acquire src storage: %w", err)
}
+7 -7
View File
@@ -58,7 +58,7 @@ func NewRemote(local *Local, index SectorIndex, auth http.Header, fetchLimit int
}
}
func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, existing SectorFileType, allocate SectorFileType, pathType PathType, op AcquireMode) (SectorPaths, SectorPaths, error) {
func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, ssize abi.SectorSize, existing SectorFileType, allocate SectorFileType, pathType PathType, op AcquireMode) (SectorPaths, SectorPaths, error) {
if existing|allocate != existing^allocate {
return SectorPaths{}, SectorPaths{}, xerrors.New("can't both find and allocate a sector")
}
@@ -90,7 +90,7 @@ func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, spt abi.Regi
r.fetchLk.Unlock()
}()
paths, stores, err := r.local.AcquireSector(ctx, s, spt, existing, allocate, pathType, op)
paths, stores, err := r.local.AcquireSector(ctx, s, ssize, existing, allocate, pathType, op)
if err != nil {
return SectorPaths{}, SectorPaths{}, xerrors.Errorf("local acquire error: %w", err)
}
@@ -106,7 +106,7 @@ func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, spt abi.Regi
}
}
apaths, ids, err := r.local.AcquireSector(ctx, s, spt, FTNone, toFetch, pathType, op)
apaths, ids, err := r.local.AcquireSector(ctx, s, ssize, FTNone, toFetch, pathType, op)
if err != nil {
return SectorPaths{}, SectorPaths{}, xerrors.Errorf("allocate local sector for fetching: %w", err)
}
@@ -116,7 +116,7 @@ func (r *Remote) AcquireSector(ctx context.Context, s abi.SectorID, spt abi.Regi
odt = FsOverheadFinalized
}
releaseStorage, err := r.local.Reserve(ctx, s, spt, toFetch, ids, odt)
releaseStorage, err := r.local.Reserve(ctx, s, ssize, toFetch, ids, odt)
if err != nil {
return SectorPaths{}, SectorPaths{}, xerrors.Errorf("reserving storage space: %w", err)
}
@@ -281,14 +281,14 @@ func (r *Remote) fetch(ctx context.Context, url, outname string) error {
}
}
func (r *Remote) MoveStorage(ctx context.Context, s abi.SectorID, spt abi.RegisteredSealProof, types SectorFileType) error {
func (r *Remote) MoveStorage(ctx context.Context, s abi.SectorID, ssize abi.SectorSize, types SectorFileType) error {
// Make sure we have the data local
_, _, err := r.AcquireSector(ctx, s, spt, types, FTNone, PathStorage, AcquireMove)
_, _, err := r.AcquireSector(ctx, s, ssize, types, FTNone, PathStorage, AcquireMove)
if err != nil {
return xerrors.Errorf("acquire src storage (remote): %w", err)
}
return r.local.MoveStorage(ctx, s, spt, types)
return r.local.MoveStorage(ctx, s, ssize, types)
}
func (r *Remote) Remove(ctx context.Context, sid abi.SectorID, typ SectorFileType, force bool) error {
+3 -3
View File
@@ -17,8 +17,8 @@ require (
github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e
github.com/dgraph-io/badger/v2 v2.2007.2
github.com/docker/go-units v0.4.0
github.com/drand/drand v1.1.2-0.20200905144319-79c957281b32
github.com/drand/kyber v1.1.2
github.com/drand/drand v1.2.1
github.com/drand/kyber v1.1.4
github.com/dustin/go-humanize v1.0.0
github.com/elastic/go-sysinfo v1.3.0
github.com/fatih/color v1.9.0
@@ -134,7 +134,7 @@ require (
go.uber.org/multierr v1.5.0
go.uber.org/zap v1.15.0
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980
golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c
golang.org/x/time v0.0.0-20191024005414-555d28b269f0
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
gopkg.in/cheggaaa/pb.v1 v1.0.28
+17 -6
View File
@@ -91,6 +91,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/briandowns/spinner v1.11.1 h1:OixPqDEcX3juo5AjQZAnFPbeUA0jvkp2qzB5gOZJ/L0=
github.com/briandowns/spinner v1.11.1/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ=
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
@@ -196,14 +197,15 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/drand/bls12-381 v0.3.2 h1:RImU8Wckmx8XQx1tp1q04OV73J9Tj6mmpQLYDP7V1XE=
github.com/drand/bls12-381 v0.3.2/go.mod h1:dtcLgPtYT38L3NO6mPDYH0nbpc5tjPassDqiniuAt4Y=
github.com/drand/drand v1.1.2-0.20200905144319-79c957281b32 h1:sU+51aQRaDxg0KnjQg19KuYRIxDBEUHffBAICSnBys8=
github.com/drand/drand v1.1.2-0.20200905144319-79c957281b32/go.mod h1:0sQEVg+ngs1jaDPVIiEgY0lbENWJPaUlWxGHEaSmKVM=
github.com/drand/drand v1.2.1 h1:KB7z+69YbnQ5z22AH/LMi0ObDR8DzYmrkS6vZXTR9jI=
github.com/drand/drand v1.2.1/go.mod h1:j0P7RGmVaY7E/OuO2yQOcQj7OgeZCuhgu2gdv0JAm+g=
github.com/drand/kyber v1.0.1-0.20200110225416-8de27ed8c0e2/go.mod h1:UpXoA0Upd1N9l4TvRPHr1qAUBBERj6JQ/mnKI3BPEmw=
github.com/drand/kyber v1.0.2/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw=
github.com/drand/kyber v1.1.2 h1:faemqlaFyLrbBSjZGRzzu5SG/do+uTYpHlnrJIHbAhQ=
github.com/drand/kyber v1.1.2/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw=
github.com/drand/kyber-bls12381 v0.1.0 h1:/P4C65VnyEwxzR5ZYYVMNzY1If+aYBrdUU5ukwh7LQw=
github.com/drand/kyber-bls12381 v0.1.0/go.mod h1:N1emiHpm+jj7kMlxEbu3MUyOiooTgNySln564cgD9mk=
github.com/drand/kyber v1.1.4 h1:YvKM03QWGvLrdTnYmxxP5iURAX+Gdb6qRDUOgg8i60Q=
github.com/drand/kyber v1.1.4/go.mod h1:9+IgTq7kadePhZg7eRwSD7+bA+bmvqRK+8DtmoV5a3U=
github.com/drand/kyber-bls12381 v0.2.0/go.mod h1:zQip/bHdeEB6HFZSU3v+d3cQE0GaBVQw9aR2E7AdoeI=
github.com/drand/kyber-bls12381 v0.2.1 h1:/d5/YAdaCmHpYjF1NZevOEcKGaq6LBbyvkCTIdGqDjs=
github.com/drand/kyber-bls12381 v0.2.1/go.mod h1:JwWn4nHO9Mp4F5qCie5sVIPQZ0X6cw8XAeMRvc/GXBE=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@@ -716,6 +718,9 @@ github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dv
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kilic/bls12-381 v0.0.0-20200607163746-32e1441c8a9f h1:qET3Wx0v8tMtoTOQnsJXVvqvCopSf48qobR6tcJuDHo=
github.com/kilic/bls12-381 v0.0.0-20200607163746-32e1441c8a9f/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s=
github.com/kilic/bls12-381 v0.0.0-20200731194930-64c428e1bff5/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s=
github.com/kilic/bls12-381 v0.0.0-20200820230200-6b2c19996391 h1:51kHw7l/dUDdOdW06AlUGT5jnpj6nqQSILebcsikSjA=
github.com/kilic/bls12-381 v0.0.0-20200820230200-6b2c19996391/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@@ -1548,6 +1553,9 @@ golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1702,6 +1710,9 @@ golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c h1:38q6VNPWR010vN82/SB121GujZNIfAUb4YttE2rhGuc=
golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+10 -4
View File
@@ -8,6 +8,7 @@ import (
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
"github.com/raulk/clock"
"go.uber.org/multierr"
"github.com/filecoin-project/lotus/build"
@@ -24,9 +25,10 @@ import (
type TimedCacheBS struct {
mu sync.RWMutex
active, inactive blockstore.MemStore
interval time.Duration
closeCh chan struct{}
clock clock.Clock
interval time.Duration
closeCh chan struct{}
doneRotatingCh chan struct{}
}
func NewTimedCacheBS(cacheTime time.Duration) *TimedCacheBS {
@@ -34,6 +36,7 @@ func NewTimedCacheBS(cacheTime time.Duration) *TimedCacheBS {
active: blockstore.NewTemporary(),
inactive: blockstore.NewTemporary(),
interval: cacheTime,
clock: build.Clock,
}
}
@@ -45,12 +48,15 @@ func (t *TimedCacheBS) Start(ctx context.Context) error {
}
t.closeCh = make(chan struct{})
go func() {
ticker := build.Clock.Ticker(t.interval)
ticker := t.clock.Ticker(t.interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
t.rotate()
if t.doneRotatingCh != nil {
t.doneRotatingCh <- struct{}{}
}
case <-t.closeCh:
return
}
+14 -7
View File
@@ -1,21 +1,27 @@
package timedbs_test
package timedbs
import (
"context"
"testing"
"time"
"github.com/raulk/clock"
"github.com/stretchr/testify/require"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/lib/timedbs"
)
func TestTimedBSSimple(t *testing.T) {
tc := timedbs.NewTimedCacheBS(10 * time.Millisecond)
tc := NewTimedCacheBS(10 * time.Millisecond)
mClock := clock.NewMock()
mClock.Set(time.Now())
tc.clock = mClock
tc.doneRotatingCh = make(chan struct{})
_ = tc.Start(context.Background())
mClock.Add(1) // IDK why it is needed but it makes it work
defer func() {
_ = tc.Stop(context.Background())
}()
@@ -36,7 +42,8 @@ func TestTimedBSSimple(t *testing.T) {
require.NoError(t, err)
require.True(t, has)
time.Sleep(15 * time.Millisecond)
mClock.Add(10 * time.Millisecond)
<-tc.doneRotatingCh
// We should still have everything.
has, err = tc.Has(b1.Cid())
@@ -60,8 +67,8 @@ func TestTimedBSSimple(t *testing.T) {
require.NoError(t, err)
require.ElementsMatch(t, ks, []cid.Cid{b1.Cid(), b2.Cid(), b3.Cid()})
time.Sleep(10 * time.Millisecond)
mClock.Add(10 * time.Millisecond)
<-tc.doneRotatingCh
// should still have b2, and b3, but not b1
has, err = tc.Has(b1.Cid())
+9 -15
View File
@@ -27,8 +27,6 @@ import (
"github.com/filecoin-project/lotus/chain/events"
"github.com/filecoin-project/lotus/chain/events/state"
"github.com/filecoin-project/lotus/chain/market"
"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/lib/sigs"
"github.com/filecoin-project/lotus/markets/utils"
@@ -40,8 +38,6 @@ type ClientNodeAdapter struct {
full.ChainAPI
full.MpoolAPI
sm *stmgr.StateManager
cs *store.ChainStore
fm *market.FundMgr
ev *events.Events
}
@@ -51,14 +47,12 @@ type clientApi struct {
full.StateAPI
}
func NewClientNodeAdapter(state full.StateAPI, chain full.ChainAPI, mpool full.MpoolAPI, sm *stmgr.StateManager, cs *store.ChainStore, fm *market.FundMgr) storagemarket.StorageClientNode {
func NewClientNodeAdapter(state full.StateAPI, chain full.ChainAPI, mpool full.MpoolAPI, fm *market.FundMgr) storagemarket.StorageClientNode {
return &ClientNodeAdapter{
StateAPI: state,
ChainAPI: chain,
MpoolAPI: mpool,
sm: sm,
cs: cs,
fm: fm,
ev: events.NewEvents(context.TODO(), &clientApi{chain, state}),
}
@@ -138,12 +132,12 @@ func (c *ClientNodeAdapter) GetBalance(ctx context.Context, addr address.Address
func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal storagemarket.ClientDeal) (abi.DealID, error) {
log.Infow("DEAL ACCEPTED!")
pubmsg, err := c.cs.GetMessage(*deal.PublishMessage)
pubmsg, err := c.ChainGetMessage(ctx, *deal.PublishMessage)
if err != nil {
return 0, xerrors.Errorf("getting deal publish message: %w", err)
}
mi, err := stmgr.StateMinerInfo(ctx, c.sm, c.cs.GetHeaviestTipSet(), deal.Proposal.Provider)
mi, err := c.StateMinerInfo(ctx, deal.Proposal.Provider, types.EmptyTSK)
if err != nil {
return 0, xerrors.Errorf("getting miner worker failed: %w", err)
}
@@ -189,16 +183,16 @@ func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal stor
}
// TODO: timeout
_, ret, _, err := c.sm.WaitForMessage(ctx, *deal.PublishMessage, build.MessageConfidence, stmgr.LookbackNoLimit)
ret, err := c.StateWaitMsg(ctx, *deal.PublishMessage, build.MessageConfidence)
if err != nil {
return 0, xerrors.Errorf("waiting for deal publish message: %w", err)
}
if ret.ExitCode != 0 {
return 0, xerrors.Errorf("deal publish failed: exit=%d", ret.ExitCode)
if ret.Receipt.ExitCode != 0 {
return 0, xerrors.Errorf("deal publish failed: exit=%d", ret.Receipt.ExitCode)
}
var res market2.PublishStorageDealsReturn
if err := res.UnmarshalCBOR(bytes.NewReader(ret.Return)); err != nil {
if err := res.UnmarshalCBOR(bytes.NewReader(ret.Receipt.Return)); err != nil {
return 0, err
}
@@ -218,7 +212,7 @@ func (c *ClientNodeAdapter) DealProviderCollateralBounds(ctx context.Context, si
func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider address.Address, dealId abi.DealID, cb storagemarket.DealSectorCommittedCallback) error {
checkFunc := func(ts *types.TipSet) (done bool, more bool, err error) {
sd, err := stmgr.GetStorageDeal(ctx, c.StateManager, dealId, ts)
sd, err := c.StateMarketStorageDeal(ctx, dealId, ts.Key())
if err != nil {
// TODO: This may be fine for some errors
@@ -245,7 +239,7 @@ func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider
return false, nil
}
sd, err := stmgr.GetStorageDeal(ctx, c.StateManager, dealId, ts)
sd, err := c.StateMarketStorageDeal(ctx, dealId, ts.Key())
if err != nil {
return false, xerrors.Errorf("failed to look up deal on chain: %w", err)
}
+19
View File
@@ -1,6 +1,7 @@
package metrics
import (
"context"
"time"
"go.opencensus.io/stats"
@@ -24,6 +25,8 @@ var (
MessageTo, _ = tag.NewKey("message_to")
MessageNonce, _ = tag.NewKey("message_nonce")
ReceivedFrom, _ = tag.NewKey("received_from")
Endpoint, _ = tag.NewKey("endpoint")
APIInterface, _ = tag.NewKey("api") // to distinguish between gateway api and full node api endpoint calls
)
// Measures
@@ -49,6 +52,7 @@ var (
PubsubRecvRPC = stats.Int64("pubsub/recv_rpc", "Counter for total received RPCs", stats.UnitDimensionless)
PubsubSendRPC = stats.Int64("pubsub/send_rpc", "Counter for total sent RPCs", stats.UnitDimensionless)
PubsubDropRPC = stats.Int64("pubsub/drop_rpc", "Counter for total dropped RPCs", stats.UnitDimensionless)
APIRequestDuration = stats.Float64("api/request_duration_ms", "Duration of API requests", stats.UnitMilliseconds)
)
var (
@@ -137,6 +141,11 @@ var (
Measure: PubsubDropRPC,
Aggregation: view.Count(),
}
APIRequestDurationView = &view.View{
Measure: APIRequestDuration,
Aggregation: defaultMillisecondsDistribution,
TagKeys: []tag.Key{APIInterface, Endpoint},
}
)
// DefaultViews is an array of OpenCensus views for metric gathering purposes
@@ -161,6 +170,7 @@ var DefaultViews = append([]*view.View{
PubsubRecvRPCView,
PubsubSendRPCView,
PubsubDropRPCView,
APIRequestDurationView,
},
rpcmetrics.DefaultViews...)
@@ -168,3 +178,12 @@ var DefaultViews = append([]*view.View{
func SinceInMilliseconds(startTime time.Time) float64 {
return float64(time.Since(startTime).Nanoseconds()) / 1e6
}
// Timer is a function stopwatch, calling it starts the timer,
// calling the returned function will record the duration.
func Timer(ctx context.Context, m *stats.Float64Measure) func() {
start := time.Now()
return func() {
stats.Record(ctx, m.M(SinceInMilliseconds(start)))
}
}
+65
View File
@@ -0,0 +1,65 @@
package metrics
import (
"context"
"reflect"
"go.opencensus.io/tag"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apistruct"
)
func MetricedStorMinerAPI(a api.StorageMiner) api.StorageMiner {
var out apistruct.StorageMinerStruct
proxy(a, &out.Internal)
proxy(a, &out.CommonStruct.Internal)
return &out
}
func MetricedFullAPI(a api.FullNode) api.FullNode {
var out apistruct.FullNodeStruct
proxy(a, &out.Internal)
proxy(a, &out.CommonStruct.Internal)
return &out
}
func MetricedWorkerAPI(a api.WorkerAPI) api.WorkerAPI {
var out apistruct.WorkerStruct
proxy(a, &out.Internal)
return &out
}
func MetricedWalletAPI(a api.WalletAPI) api.WalletAPI {
var out apistruct.WalletStruct
proxy(a, &out.Internal)
return &out
}
func MetricedGatewayAPI(a api.GatewayAPI) api.GatewayAPI {
var out apistruct.GatewayStruct
proxy(a, &out.Internal)
return &out
}
func proxy(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)
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)
// upsert function name into context
ctx, _ = tag.New(ctx, tag.Upsert(Endpoint, field.Name))
stop := Timer(ctx, APIRequestDuration)
defer stop()
// pass tagged ctx back into function call
args[0] = reflect.ValueOf(ctx)
return fn.Call(args)
}))
}
}
+4 -13
View File
@@ -280,7 +280,7 @@ minerLoop:
m.minedBlockHeights.Add(blkKey, true)
if err := m.api.SyncSubmitBlock(ctx, b); err != nil {
log.Errorf("failed to submit newly mined block: %s", err)
log.Errorf("failed to submit newly mined block: %+v", err)
}
} else {
base.NullRounds++
@@ -386,7 +386,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (*types.BlockMsg,
rbase = bvals[len(bvals)-1]
}
ticket, err := m.computeTicket(ctx, &rbase, base)
ticket, err := m.computeTicket(ctx, &rbase, base, mbi)
if err != nil {
return nil, xerrors.Errorf("scratching ticket failed: %w", err)
}
@@ -456,16 +456,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (*types.BlockMsg,
return b, nil
}
func (m *Miner) computeTicket(ctx context.Context, brand *types.BeaconEntry, base *MiningBase) (*types.Ticket, error) {
mi, err := m.api.StateMinerInfo(ctx, m.address, types.EmptyTSK)
if err != nil {
return nil, err
}
worker, err := m.api.StateAccountKey(ctx, mi.Worker, types.EmptyTSK)
if err != nil {
return nil, err
}
func (m *Miner) computeTicket(ctx context.Context, brand *types.BeaconEntry, base *MiningBase, mbi *api.MiningBaseInfo) (*types.Ticket, error) {
buf := new(bytes.Buffer)
if err := m.address.MarshalCBOR(buf); err != nil {
return nil, xerrors.Errorf("failed to marshal address to cbor: %w", err)
@@ -481,7 +472,7 @@ func (m *Miner) computeTicket(ctx context.Context, brand *types.BeaconEntry, bas
return nil, err
}
vrfOut, err := gen.ComputeVRF(ctx, m.api.WalletSign, worker, input)
vrfOut, err := gen.ComputeVRF(ctx, m.api.WalletSign, mbi.WorkerKey, input)
if err != nil {
return nil, err
}
-1
View File
@@ -250,7 +250,6 @@ func Online() Option {
Override(new(*store.ChainStore), modules.ChainStore),
Override(new(stmgr.UpgradeSchedule), stmgr.DefaultUpgradeSchedule()),
Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule),
Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))),
Override(new(*wallet.LocalWallet), wallet.NewWallet),
Override(new(wallet.Default), From(new(*wallet.LocalWallet))),
Override(new(api.WalletAPI), From(new(wallet.MultiWallet))),
+2 -2
View File
@@ -65,9 +65,9 @@ type API struct {
fx.In
full.ChainAPI
full.StateAPI
full.WalletAPI
paych.PaychAPI
full.StateAPI
SMDealClient storagemarket.StorageClient
RetDiscovery discovery.PeerResolver
@@ -117,7 +117,7 @@ func (a *API) ClientStartDeal(ctx context.Context, params *api.StartDealParams)
}
}
walletKey, err := a.StateAPI.StateManager.ResolveToKeyAddress(ctx, params.Wallet, nil)
walletKey, err := a.StateAccountKey(ctx, params.Wallet, types.EmptyTSK)
if err != nil {
return nil, xerrors.Errorf("failed resolving params.Wallet addr: %w", params.Wallet)
}
+10 -7
View File
@@ -40,8 +40,11 @@ import (
var log = logging.Logger("fullnode")
type ChainModuleAPI interface {
ChainNotify(context.Context) (<-chan []*api.HeadChange, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
ChainHasObj(context.Context, cid.Cid) (bool, error)
ChainHead(context.Context) (*types.TipSet, error)
ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error)
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
@@ -67,8 +70,8 @@ type ChainAPI struct {
Chain *store.ChainStore
}
func (a *ChainAPI) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) {
return a.Chain.SubHeadChanges(ctx), nil
func (m *ChainModule) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, error) {
return m.Chain.SubHeadChanges(ctx), nil
}
func (m *ChainModule) ChainHead(context.Context) (*types.TipSet, error) {
@@ -101,13 +104,13 @@ func (m *ChainModule) ChainGetTipSet(ctx context.Context, key types.TipSetKey) (
return m.Chain.LoadTipSet(key)
}
func (a *ChainAPI) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (*api.BlockMessages, error) {
b, err := a.Chain.GetBlock(msg)
func (m *ChainModule) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (*api.BlockMessages, error) {
b, err := m.Chain.GetBlock(msg)
if err != nil {
return nil, err
}
bmsgs, smsgs, err := a.Chain.MessagesForBlock(b)
bmsgs, smsgs, err := m.Chain.MessagesForBlock(b)
if err != nil {
return nil, err
}
@@ -532,8 +535,8 @@ func (a *ChainAPI) ChainGetNode(ctx context.Context, p string) (*api.IpldObject,
}, nil
}
func (a *ChainAPI) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
cm, err := a.Chain.GetCMessage(mc)
func (m *ChainModule) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
cm, err := m.Chain.GetCMessage(mc)
if err != nil {
return nil, err
}
+64 -45
View File
@@ -40,12 +40,22 @@ import (
)
type StateModuleAPI interface {
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error)
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error)
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error)
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error)
StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error)
StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error)
StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error)
StateNetworkVersion(ctx context.Context, key types.TipSetKey) (network.Version, error)
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error)
}
// StateModule provides a default implementation of StateModuleAPI.
@@ -112,13 +122,13 @@ func (a *StateAPI) StateMinerActiveSectors(ctx context.Context, maddr address.Ad
return stmgr.GetMinerSectorSet(ctx, a.StateManager, ts, maddr, &activeSectors)
}
func (a *StateAPI) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) {
act, err := a.StateManager.LoadActorTsk(ctx, actor, tsk)
func (m *StateModule) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) {
act, err := m.StateManager.LoadActorTsk(ctx, actor, tsk)
if err != nil {
return miner.MinerInfo{}, xerrors.Errorf("failed to load miner actor: %w", err)
}
mas, err := miner.Load(a.StateManager.ChainStore().Store(ctx), act)
mas, err := miner.Load(m.StateManager.ChainStore().Store(ctx), act)
if err != nil {
return miner.MinerInfo{}, xerrors.Errorf("failed to load miner actor state: %w", err)
}
@@ -215,18 +225,18 @@ func (a *StateAPI) StateMinerPartitions(ctx context.Context, m address.Address,
return out, err
}
func (a *StateAPI) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) {
ts, err := a.StateManager.ChainStore().GetTipSetFromKey(tsk)
func (m *StateModule) StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
act, err := a.StateManager.LoadActor(ctx, addr, ts)
act, err := m.StateManager.LoadActor(ctx, addr, ts)
if err != nil {
return nil, xerrors.Errorf("failed to load miner actor: %w", err)
}
mas, err := miner.Load(a.StateManager.ChainStore().Store(ctx), act)
mas, err := miner.Load(m.StateManager.ChainStore().Store(ctx), act)
if err != nil {
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
}
@@ -310,19 +320,19 @@ func (a *StateAPI) StateMinerRecoveries(ctx context.Context, addr address.Addres
return miner.AllPartSectors(mas, miner.Partition.RecoveringSectors)
}
func (a *StateAPI) StateMinerPower(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*api.MinerPower, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
func (m *StateModule) StateMinerPower(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*api.MinerPower, error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
m, net, hmp, err := stmgr.GetPower(ctx, a.StateManager, ts, addr)
mp, net, hmp, err := stmgr.GetPower(ctx, m.StateManager, ts, addr)
if err != nil {
return nil, err
}
return &api.MinerPower{
MinerPower: m,
MinerPower: mp,
TotalPower: net,
HasMinPower: hmp,
}, nil
@@ -563,20 +573,20 @@ func (a *StateAPI) StateSearchMsg(ctx context.Context, msg cid.Cid) (*api.MsgLoo
return nil, nil
}
func (a *StateAPI) StateGetReceipt(ctx context.Context, msg cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
func (m *StateModule) StateGetReceipt(ctx context.Context, msg cid.Cid, tsk types.TipSetKey) (*types.MessageReceipt, error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return a.StateManager.GetReceipt(ctx, msg, ts)
return m.StateManager.GetReceipt(ctx, msg, ts)
}
func (a *StateAPI) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
func (m *StateModule) StateListMiners(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.ListMinerActors(ctx, a.StateManager, ts)
return stmgr.ListMinerActors(ctx, m.StateManager, ts)
}
func (a *StateAPI) StateListActors(ctx context.Context, tsk types.TipSetKey) ([]address.Address, error) {
@@ -587,12 +597,12 @@ func (a *StateAPI) StateListActors(ctx context.Context, tsk types.TipSetKey) ([]
return a.StateManager.ListAllActors(ctx, ts)
}
func (a *StateAPI) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
func (m *StateModule) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return api.MarketBalance{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return a.StateManager.MarketBalance(ctx, addr, ts)
return m.StateManager.MarketBalance(ctx, addr, ts)
}
func (a *StateAPI) StateMarketParticipants(ctx context.Context, tsk types.TipSetKey) (map[string]api.MarketBalance, error) {
@@ -676,12 +686,12 @@ func (a *StateAPI) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (m
return out, nil
}
func (a *StateAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
func (m *StateModule) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return stmgr.GetStorageDeal(ctx, a.StateManager, dealId, ts)
return stmgr.GetStorageDeal(ctx, m.StateManager, dealId, ts)
}
func (a *StateAPI) StateChangedActors(ctx context.Context, old cid.Cid, new cid.Cid) (map[string]types.Actor, error) {
@@ -1158,19 +1168,19 @@ func (a *StateAPI) StateVerifierStatus(ctx context.Context, addr address.Address
// StateVerifiedClientStatus returns the data cap for the given address.
// Returns zero if there is no entry in the data cap table for the
// address.
func (a *StateAPI) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
act, err := a.StateGetActor(ctx, verifreg.Address, tsk)
func (m *StateModule) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
act, err := m.StateGetActor(ctx, verifreg.Address, tsk)
if err != nil {
return nil, err
}
aid, err := a.StateLookupID(ctx, addr, tsk)
aid, err := m.StateLookupID(ctx, addr, tsk)
if err != nil {
log.Warnf("lookup failure %v", err)
return nil, err
}
vrs, err := verifreg.Load(a.StateManager.ChainStore().Store(ctx), act)
vrs, err := verifreg.Load(m.StateManager.ChainStore().Store(ctx), act)
if err != nil {
return nil, xerrors.Errorf("failed to load verified registry state: %w", err)
}
@@ -1205,33 +1215,33 @@ var dealProviderCollateralDen = types.NewInt(100)
// StateDealProviderCollateralBounds returns the min and max collateral a storage provider
// can issue. It takes the deal size and verified status as parameters.
func (a *StateAPI) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
func (m *StateModule) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return api.DealCollateralBounds{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
pact, err := a.StateGetActor(ctx, power.Address, tsk)
pact, err := m.StateGetActor(ctx, power.Address, tsk)
if err != nil {
return api.DealCollateralBounds{}, xerrors.Errorf("failed to load power actor: %w", err)
}
ract, err := a.StateGetActor(ctx, reward.Address, tsk)
ract, err := m.StateGetActor(ctx, reward.Address, tsk)
if err != nil {
return api.DealCollateralBounds{}, xerrors.Errorf("failed to load reward actor: %w", err)
}
pst, err := power.Load(a.StateManager.ChainStore().Store(ctx), pact)
pst, err := power.Load(m.StateManager.ChainStore().Store(ctx), pact)
if err != nil {
return api.DealCollateralBounds{}, xerrors.Errorf("failed to load power actor state: %w", err)
}
rst, err := reward.Load(a.StateManager.ChainStore().Store(ctx), ract)
rst, err := reward.Load(m.StateManager.ChainStore().Store(ctx), ract)
if err != nil {
return api.DealCollateralBounds{}, xerrors.Errorf("failed to load reward actor state: %w", err)
}
circ, err := a.StateVMCirculatingSupplyInternal(ctx, ts.Key())
circ, err := stateVMCirculatingSupplyInternal(ctx, ts.Key(), m.Chain, m.StateManager)
if err != nil {
return api.DealCollateralBounds{}, xerrors.Errorf("getting total circulating supply: %w", err)
}
@@ -1252,7 +1262,7 @@ func (a *StateAPI) StateDealProviderCollateralBounds(ctx context.Context, size a
powClaim.QualityAdjPower,
rewPow,
circ.FilCirculating,
a.StateManager.GetNtwkVersion(ctx, ts.Height()))
m.StateManager.GetNtwkVersion(ctx, ts.Height()))
return api.DealCollateralBounds{
Min: types.BigDiv(types.BigMul(min, dealProviderCollateralNum), dealProviderCollateralDen),
Max: max,
@@ -1273,23 +1283,32 @@ func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetK
}
func (a *StateAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
return stateVMCirculatingSupplyInternal(ctx, tsk, a.Chain, a.StateManager)
}
func stateVMCirculatingSupplyInternal(
ctx context.Context,
tsk types.TipSetKey,
cstore *store.ChainStore,
smgr *stmgr.StateManager,
) (api.CirculatingSupply, error) {
ts, err := cstore.GetTipSetFromKey(tsk)
if err != nil {
return api.CirculatingSupply{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
sTree, err := a.stateForTs(ctx, ts)
sTree, err := stateForTs(ctx, ts, cstore, smgr)
if err != nil {
return api.CirculatingSupply{}, err
}
return a.StateManager.GetVMCirculatingSupplyDetailed(ctx, ts.Height(), sTree)
return smgr.GetVMCirculatingSupplyDetailed(ctx, ts.Height(), sTree)
}
func (a *StateAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
func (m *StateModule) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return network.VersionMax, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return a.StateManager.GetNtwkVersion(ctx, ts.Height()), nil
return m.StateManager.GetNtwkVersion(ctx, ts.Height()), nil
}
-5
View File
@@ -13,17 +13,12 @@ import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/types"
full "github.com/filecoin-project/lotus/node/impl/full"
"github.com/filecoin-project/lotus/paychmgr"
)
type PaychAPI struct {
fx.In
full.MpoolAPI
full.WalletAPI
full.ChainAPI
PaychMgr *paychmgr.Manager
}
+28 -3
View File
@@ -3,19 +3,40 @@ package modules
import (
"context"
"github.com/filecoin-project/lotus/api"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apibstore"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
cbor "github.com/ipfs/go-ipld-cbor"
)
type RPCStateManager struct {
gapi api.GatewayAPI
gapi api.GatewayAPI
cstore *cbor.BasicIpldStore
}
func NewRPCStateManager(api api.GatewayAPI) *RPCStateManager {
return &RPCStateManager{gapi: api}
cstore := cbor.NewCborStore(apibstore.NewAPIBlockstore(api))
return &RPCStateManager{gapi: api, cstore: cstore}
}
func (s *RPCStateManager) GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error) {
act, err := s.gapi.StateGetActor(ctx, addr, ts.Key())
if err != nil {
return nil, nil, err
}
actState, err := paych.Load(adt.WrapStore(ctx, s.cstore), act)
if err != nil {
return nil, nil, err
}
return act, actState, nil
}
func (s *RPCStateManager) LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error) {
@@ -30,4 +51,8 @@ func (s *RPCStateManager) ResolveToKeyAddress(ctx context.Context, addr address.
return s.gapi.StateAccountKey(ctx, addr, ts.Key())
}
func (s *RPCStateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) {
return nil, xerrors.Errorf("RPCStateManager does not implement StateManager.Call")
}
var _ stmgr.StateManagerAPI = (*RPCStateManager)(nil)
+3 -8
View File
@@ -16,7 +16,6 @@ import (
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
@@ -61,14 +60,10 @@ type managerAPI interface {
// managerAPIImpl is used to create a composite that implements managerAPI
type managerAPIImpl struct {
*stmgr.StateManager
stmgr.StateManagerAPI
paychAPI
}
func (m *managerAPIImpl) AdtStore(ctx context.Context) adt.Store {
return m.ChainStore().Store(ctx)
}
type Manager struct {
// The Manager context is used to terminate wait operations on shutdown
ctx context.Context
@@ -82,11 +77,11 @@ type Manager struct {
channels map[string]*channelAccessor
}
func NewManager(mctx helpers.MetricsCtx, lc fx.Lifecycle, sm *stmgr.StateManager, pchstore *Store, api PaychAPI) *Manager {
func NewManager(mctx helpers.MetricsCtx, lc fx.Lifecycle, sm stmgr.StateManagerAPI, pchstore *Store, api PaychAPI) *Manager {
ctx := helpers.LifecycleCtx(mctx, lc)
ctx, shutdown := context.WithCancel(ctx)
impl := &managerAPIImpl{StateManager: sm, paychAPI: &api}
impl := &managerAPIImpl{StateManagerAPI: sm, paychAPI: &api}
return &Manager{
ctx: ctx,
shutdown: shutdown,
+10 -6
View File
@@ -12,6 +12,7 @@ import (
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/go-state-types/network"
"github.com/ipfs/go-cid"
"go.opencensus.io/trace"
@@ -151,7 +152,15 @@ func (s *WindowPoStScheduler) runSubmitPoST(
defer span.End()
// Get randomness from tickets
// use the challenge epoch if we've upgraded to network version 4
// (actors version 2). We want to go back as far as possible to be safe.
commEpoch := deadline.Open
if ver, err := s.api.StateNetworkVersion(ctx, types.EmptyTSK); err != nil {
log.Errorw("failed to get network version to determine PoSt epoch randomness lookback", "error", err)
} else if ver >= network.Version4 {
commEpoch = deadline.Challenge
}
commRand, err := s.api.ChainGetRandomnessFromTickets(ctx, ts.Key(), crypto.DomainSeparationTag_PoStChainCommit, commEpoch, nil)
if err != nil {
err = xerrors.Errorf("failed to get chain randomness from tickets for windowPost (ts=%d; deadline=%d): %w", ts.Height(), commEpoch, err)
@@ -180,11 +189,6 @@ func (s *WindowPoStScheduler) runSubmitPoST(
}
func (s *WindowPoStScheduler) checkSectors(ctx context.Context, check bitfield.BitField) (bitfield.BitField, error) {
spt, err := s.proofType.RegisteredSealProof()
if err != nil {
return bitfield.BitField{}, xerrors.Errorf("getting seal proof type: %w", err)
}
mid, err := address.IDFromAddress(s.actor)
if err != nil {
return bitfield.BitField{}, err
@@ -206,7 +210,7 @@ func (s *WindowPoStScheduler) checkSectors(ctx context.Context, check bitfield.B
return bitfield.BitField{}, xerrors.Errorf("iterating over bitfield: %w", err)
}
bad, err := s.faultTracker.CheckProvable(ctx, spt, tocheck)
bad, err := s.faultTracker.CheckProvable(ctx, s.proofType, tocheck)
if err != nil {
return bitfield.BitField{}, xerrors.Errorf("checking provable sectors: %w", err)
}
+3 -2
View File
@@ -23,6 +23,7 @@ import (
tutils "github.com/filecoin-project/specs-actors/v2/support/testing"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/journal"
@@ -47,7 +48,7 @@ func (m *mockStorageMinerAPI) StateMinerInfo(ctx context.Context, a address.Addr
}
func (m *mockStorageMinerAPI) StateNetworkVersion(ctx context.Context, key types.TipSetKey) (network.Version, error) {
panic("implement me")
return build.NewestNetworkVersion, nil
}
func (m *mockStorageMinerAPI) ChainGetRandomnessFromTickets(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) {
@@ -114,7 +115,7 @@ func (m *mockProver) GenerateWindowPoSt(ctx context.Context, aid abi.ActorID, si
type mockFaultTracker struct {
}
func (m mockFaultTracker) CheckProvable(ctx context.Context, spt abi.RegisteredSealProof, sectors []abi.SectorID) ([]abi.SectorID, error) {
func (m mockFaultTracker) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []abi.SectorID) ([]abi.SectorID, error) {
// Returns "bad" sectors so just return nil meaning all sectors are good
return nil, nil
}