Compare commits

..
Author SHA1 Message Date
Travis Person d1b95b02dd Merge pull request #4325 from filecoin-project/asr/calbinet
Introduce tape upgrade to calibration net
2020-10-11 23:47:39 -07:00
Aayush Rajasekaran b273bfc5c3 Set tape upgrade to 15000 2020-10-12 02:33:10 -04:00
Aayush Rajasekaran af14f30e3a Merge branch 'master' into ntwk-calibration 2020-10-12 02:14:51 -04:00
Aayush Rajasekaran a9d8bc7c45 Merge pull request #4322 from filecoin-project/steb/tape-upgrade
implement tape upgrade
2020-10-12 02:14:13 -04:00
Aayush Rajasekaran de1038ecc3 Merge branch 'master' into ntwk-calibration 2020-10-12 02:11:41 -04:00
Steven Allen 92177b5738 implement tape upgrade
Upgrade to specs-actors v2.1 and network version 5. This fixes the bug where
prove commits were not accepted.
2020-10-12 02:00:27 -04:00
Łukasz Magiera 8fd9b5f235 Merge pull request #4315 from filecoin-project/feat/stats-ops
lotus-stats: optmize getting miner power
2020-10-12 06:01:52 +02:00
Jakub Sztandera a95e343dee Merge pull request #4321 from filecoin-project/feat/love
Chain is love
2020-10-12 05:44:34 +02:00
Steven Allen c296e1bbca use actor abstraction in metrics command 2020-10-11 20:31:20 -07:00
Jakub Sztandera ae366972a9 Chain is love
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-12 05:11:04 +02:00
Travis Person 23470bc38f lotus-stats: optmize getting miner power 2020-10-11 20:27:36 +00:00
Whyrusleeping 40b2e2d0c1 Merge pull request #4312 from filecoin-project/feat/msig-inspect-decode
decode parameters for multisig transactions in inspect
2020-10-11 11:51:32 -05:00
Łukasz Magiera 00620aac57 Merge pull request #4296 from filecoin-project/feat/sync-unmarkbad-all
sync unmark-bad --all
2020-10-10 22:35:56 +02:00
Łukasz Magiera 32d95fc97a docsgen, gofmt 2020-10-10 20:46:06 +02:00
Łukasz Magiera a491fc97b9 Merge pull request #4301 from filecoin-project/steb/fix-two-races
Fix two races
2020-10-10 20:37:13 +02:00
Łukasz Magiera 151577f04e Merge pull request #4287 from filecoin-project/feat/flush_validation_cache_on_chain_import
Dump the block validation cache whenever we perform an import
2020-10-10 20:33:17 +02:00
Steven Allen c463582528 fix a race and optimize hello messages
LifecycleCtx can _only_ be called during startup as it appends an fx hook.
Worse, this was causing us to append an fx hook on every single hello message,
leaking memory (and probably causing other shutdown issues...).
2020-10-10 08:33:06 -07:00
Steven Allen 7245ac2b69 fix a race in the sync manager
1. SyncerState contains a mutex and should never be copied. Honestly, this case
was probably fine but it's just as easy to create a separate snapshot type and
easier to reason about.

2. We need to initialize the syncStates array once at start, before accessing
it. By each syncer state inside each worker, we were racing with calls to
`State()`. Again, this was probably benign, but I don't trust optimizing
compilers.
2020-10-10 08:31:04 -07:00
Łukasz Magiera 58f13a7d5a Merge pull request #4299 from filecoin-project/fix/wallet-export-panic
Fix panic in wallet export when key is not found
2020-10-10 16:25:40 +02:00
Peter Rabbitson e7d3b2503e Merge tag 'v0.9.1' 2020-10-10 15:54:51 +02:00
Łukasz Magiera ee8b8b8174 Merge pull request #4298 from filecoin-project/fix/cli-stderr-errors
cli: Don't output errors to stdout
2020-10-10 15:52:43 +02:00
Łukasz Magiera 4fa6afad13 Fix panic in wallet export when key is not found 2020-10-10 15:44:22 +02:00
Łukasz Magiera a80e98dc05 cli: Don't output errors to stdout 2020-10-10 15:38:14 +02:00
Peter Rabbitson 23f5a99117 Add comment clarifying current codepath 2020-10-10 15:36:32 +02:00
Łukasz Magiera 651522cbaa Merge pull request #4274 from filecoin-project/feat/msig-remove-api
add an api for removing multisig signers
2020-10-10 12:56:07 +02:00
Łukasz Magiera 388c9afce0 docsgen 2020-10-10 12:28:59 +02:00
Łukasz Magiera 9a26896c69 Merge pull request #4282 from filecoin-project/steb/fix-tipset-cache-race
fix a race in tipset cache usage
2020-10-10 12:27:15 +02:00
Łukasz Magiera 2db8b7efa7 Merge pull request #4291 from filecoin-project/steb/node-test-races
make pledge test pass with the race detector
2020-10-10 11:54:25 +02:00
Łukasz Magiera 18e58467f8 sync unmark-bad --all 2020-10-10 10:26:42 +02:00
Łukasz Magiera 1401efb115 Merge pull request #4294 from filecoin-project/feat/v0.9.1
Bump the version to 0.9.1
2020-10-10 09:15:04 +02:00
Łukasz Magiera f417d39a08 Bump the version to 0.9.1 2020-10-10 09:13:52 +02:00
Łukasz Magiera 11e35cf911 Merge pull request #4293 from filecoin-project/steb/actors-fixes
upgrade specs-actors
2020-10-10 08:53:20 +02:00
Steven Allen 10d464a1eb upgrade to specs-actors v2.0.3 2020-10-09 21:52:01 -07:00
Steven Allen d84f5dabab remove upgrade invariant checks
These checks may be _too_ strict and could cause the upgrade to fail unnecessarily.
2020-10-09 21:51:58 -07:00
Steven Allen f3abd1ae82 make pledge test pass with the race detector 2020-10-09 20:32:09 -07:00
Peter Rabbitson 85abca4b16 Delint 2020-10-10 04:00:12 +02:00
Peter Rabbitson 6610a247cf Dump the block validation cache whenever we perform an import
This solves a problem with folks resurrecting long-out-of-sync nodes via
snapshot imports.

The interface switch to Batching is necessary: startup is too long otherwise
( 8 minutes just to clear everything on a relatively old node )
2020-10-10 03:41:04 +02:00
Łukasz Magiera a6d9b302fa Merge pull request #3583 from filecoin-project/feat/signing-backends
Remote wallet backends
2020-10-10 02:58:02 +02:00
Steven Allen f32b3bf99b fix a race in tipset cache usage
This tipset cache is shared between multiple services and is called from
multiple places.
2020-10-09 17:32:45 -07:00
Łukasz Magiera 114a1aaffd Merge pull request #4281 from filecoin-project/steb/seal-race
fix race in unseal
2020-10-10 02:23:02 +02:00
Łukasz Magiera 83ba7ec8cc Merge pull request #4280 from filecoin-project/fix/market-deal-race
fix a race when retrieving pieces
2020-10-10 02:15:47 +02:00
Steven Allen 83dfc460d4 fix race in unseal
1. Remove an invalid error check.
2. Make sure to shadow the outer error type from within the goroutine instead or
reading the outer type.

This may have been causing test issues (caught in TestMinerAllInfo with the race
detector).
2020-10-09 15:39:41 -07:00
Steven Allen 283fd054e8 fix a race when retrieving pieces
We'd read the deal ID without synchronizing. This could (and probably did given
the history of flaky deal tests) cause us to miss events.

This patch also makes sure to always unsubscribe from events, even on error.
2020-10-09 15:35:44 -07:00
Łukasz Magiera 09bff14d85 Merge pull request #4269 from filecoin-project/steb/simplify-sync
simplify message syncing logic
2020-10-10 00:00:26 +02:00
Łukasz Magiera 3cb1abba4f Merge pull request #4276 from filecoin-project/steb/fix-bad-error
return the correct err from iterFullTipset
2020-10-09 23:26:54 +02:00
Łukasz Magiera d4c92942e7 Merge pull request #4275 from filecoin-project/steb/unshare-journal
unshare the journal
2020-10-09 23:16:27 +02:00
Aayush Rajasekaran f773ab4b28 Correct docs 2020-10-09 17:14:21 -04:00
Steven Allen c0182f8301 return the correct err from iterFullTipset 2020-10-09 13:59:56 -07:00
Łukasz Magiera c06f394b81 Merge pull request #4273 from filecoin-project/fix/fundsmgr-incorrect-cached-value
Revert cached "available" amount if the AddFunds message send fails
2020-10-09 22:52:40 +02:00
Steven Allen 748d2e82a7 unshare the journal
Motivation:

* Run lotus with the race detector enabled (primary motivation).
* Allow multiple lotus nodes in a process (not a high priority).

Previously, the journal was shared between all lotus instances, but it was
initialized for every new node. This caused safety problems in tests (at a
minimum).

This patch explicitly passes the journal to all services that need it.
2020-10-09 13:23:07 -07:00
Steven Allen a5c78371fd Merge pull request #4270 from filecoin-project/steb/test-fix-paychstatus-race
fix a race in the payment channel status test
2020-10-09 13:22:16 -07:00
Ingar Shu d80e7eda93 Revert cached "available" amount if the AddFunds message send fails 2020-10-09 13:18:43 -07:00
Steven Allen 9f9d5cb2a5 fix a race in the payment channel status test
We should not be clobbering the cmd variable.
2020-10-09 11:50:16 -07:00
Łukasz Magiera fdaa9c14ad Merge remote-tracking branch 'origin/master' into feat/signing-backends 2020-10-09 20:36:51 +02:00
Łukasz Magiera 9d8932d395 Merge pull request #4268 from iand/fix/rewardv2-cumsumrealized
fix: spec actors 2 reward shim uses correct field for CumsumRealized
2020-10-09 20:32:14 +02:00
Steven Allen 105aa40007 simplify message syncing logic
1. Allow duplicate blocks from bitswap. This shouldn't happen, but there's no
reason to bail (just log loudly).
2. Simplify logic to very explicitly check to make sure we're fetching every
block.
2020-10-09 11:06:49 -07:00
Łukasz Magiera 110f033c83 Merge pull request #4095 from filecoin-project/feat/daemon-lite
lotus-lite: replace wallet / msig calls with thin client to gateway
2020-10-09 19:22:43 +02:00
Ian Davis f87d325b6f fix: spec actors 2 reward shim uses correct field for CumsumRealized 2020-10-09 17:48:20 +01:00
Łukasz Magiera ab8286fa38 Fix docsgen, lotus-soup build 2020-10-09 18:43:22 +02:00
whyrusleeping 4cca3f19a3 add an api for removing multisig signers 2020-10-09 09:40:25 -07:00
Łukasz Magiera feb4b3c8b4 Merge remote-tracking branch 'origin/master' into feat/signing-backends 2020-10-09 15:51:25 +02:00
Dirk McCormick 7f7c9e978f feat: hide lite mode flag 2020-10-09 11:56:25 +02:00
Dirk McCormick 200a95f824 refactor: unify test builder full node options 2020-10-09 11:56:25 +02:00
Dirk McCormick d69e4c7cf2 refactor: lite-mode - simplify organization of dep injection 2020-10-09 11:54:42 +02:00
Dirk McCormick b2834baa4b feat: add msig available balance and vested to lite mode 2020-10-09 11:51:20 +02:00
Dirk McCormick e9e27cbbb0 feat: put gateway in middle of end-to-end test for lite mode 2020-10-09 11:48:35 +02:00
Dirk McCormick ef73b964fb feat: add end-to-end test for lite mode 2020-10-09 11:48:35 +02:00
Dirk McCormick 7b1bec91ed feat: add tests for gateway ChainGetTipsetByHeight 2020-10-09 11:45:16 +02:00
Dirk McCormick b32d25c562 feat: add RPC for GasEstimateMessageGas 2020-10-09 11:45:16 +02:00
Dirk McCormick 767611247c feat: add RPC for StateWaitMsg 2020-10-09 11:45:16 +02:00
Dirk McCormick be09a8a00a feat: lite-mode - check that gateway API implements required chain, mpool, state methods 2020-10-09 11:43:03 +02:00
Dirk McCormick 2719adc1b1 feat: lite-mode - thin client for chan & state 2020-10-09 11:43:03 +02:00
Dirk McCormick f1b1d8cec6 fix: MpoolAPI DI 2020-10-09 11:43:03 +02:00
Dirk McCormick 8fa4c0a970 feat: gateway - MpoolPush 2020-10-09 11:43:03 +02:00
Dirk McCormick 00a14de094 feat: gateway - StateLookupID 2020-10-09 11:43:03 +02:00
Dirk McCormick eec13ff8dc refactor: daemon - simplify gateway cleanup 2020-10-09 11:43:03 +02:00
Dirk McCormick 1ffdd7d5b3 fix: gateway - remove tracing (JsonRPC automatically traces all calls) 2020-10-09 11:43:03 +02:00
Dirk McCormick e19cd9ed01 feat: lotus-lite - replace wallet StateManager with thin client to gateway 2020-10-09 11:43:03 +02:00
Łukasz Magiera bacac245c7 Merge pull request #4256 from filecoin-project/steb/call-stop
cleanup tests on finish
2020-10-09 10:20:33 +02:00
Łukasz Magiera e1792ffe4d Merge pull request #4260 from filecoin-project/asr/wallet-abstract
Fix deletion of addresses from wallet
2020-10-09 09:55:25 +02:00
Aayush Rajasekaran 9c35762966 Fix deletion of addresses from wallet 2020-10-09 03:26:51 -04:00
Łukasz Magiera 356137439f apistruct: Drop unused WalletSignMessage 2020-10-09 03:12:33 +02:00
Łukasz Magiera 6cc7559b04 Fix APIInfo import cycle in tests 2020-10-09 02:58:12 +02:00
Łukasz Magiera 3cd53ad9d9 Use APIInfo parser for RemoteBacked wallet config 2020-10-09 02:21:37 +02:00
Łukasz Magiera 6c54d2445d Appease the linter 2020-10-09 01:53:12 +02:00
Łukasz Magiera 6a10af626c Nicer message logging in lotus-wallet 2020-10-09 01:50:46 +02:00
Łukasz Magiera 597d065e05 Update go-jsonrpc with http(s) client support 2020-10-09 01:39:06 +02:00
Łukasz Magiera 791aa5c6c8 Add lotus-wallet to Makefile 2020-10-09 01:37:17 +02:00
Steven Allen 82b15d2637 cleanup tests on finish 2020-10-08 16:36:02 -07:00
Łukasz Magiera 7d2f06cfbd Fix WalletSign in tests 2020-10-09 01:34:48 +02:00
Łukasz Magiera 6e8efb9d2c gofmt 2020-10-09 01:27:49 +02:00
Łukasz Magiera f3dc730b05 wallet: Add metadata to WalletAPI.WalletSign 2020-10-09 01:27:38 +02:00
Łukasz Magiera 114776f2c5 wallet: Drop WalletSignMessage from WalletAPI 2020-10-09 01:04:59 +02:00
Łukasz Magiera 4835109470 wallet: Post-merge fixes 2020-10-09 00:51:04 +02:00
Łukasz Magiera 8783c7434e Merge remote-tracking branch 'origin/master' into feat/signing-backends 2020-10-09 00:50:41 +02:00
Łukasz Magiera 2d3b61675b Merge pull request #3444 from IPFSMain-Official/fix-GetBestMiningCandidate-bug
fix GetBestMiningCandidate bug
2020-10-08 23:55:19 +02:00
刘林欣 a23ab123d7 fix GetBestMiningCandidate bug
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
2020-10-08 23:39:33 +02:00
Travis Person d0e432ab16 Calibration genesis 2020-10-07 04:05:40 +00:00
Travis Person f5132c3b61 New calibration network info 2020-10-07 02:52:42 +00:00
whyrusleeping ef3987e2ab decode parameters for multisig transactions in inspect 2020-10-02 14:51:32 -07:00
Łukasz Magiera 780f6dba34 Remote wallet backends 2020-09-05 21:39:09 +02:00
Łukasz Magiera f90cfda2e6 wallet: Add interface layer 2020-09-04 22:18:03 +02:00
116 changed files with 2926 additions and 1064 deletions
+1
View File
@@ -12,6 +12,7 @@
/lotus-bench
/lotus-gateway
/lotus-pcr
/lotus-wallet
/bench.json
/lotuspond/front/node_modules
/lotuspond/front/build
+20
View File
@@ -1,5 +1,25 @@
# Lotus changelog
# 0.9.1 / 2020-10-10
This release fixes an issue which may cause the actors v2 migration to compute the state incorrectly when more than one migration is running in parallel.
## Changes
- Make concurrent actor migrations safe (https://github.com/filecoin-project/lotus/pull/4293)
- Remote wallet backends (https://github.com/filecoin-project/lotus/pull/3583)
- Track funds in FundMgr correctly in case of AddFunds failing (https://github.com/filecoin-project/lotus/pull/4273)
- Partial lite-node mode (https://github.com/filecoin-project/lotus/pull/4095)
- Fix potential infinite loop in GetBestMiningCandidate (https://github.com/filecoin-project/lotus/pull/3444)
- sync wait: Handle processed message offset (https://github.com/filecoin-project/lotus/pull/4253)
- Add some new endpoints for querying Msig info (https://github.com/filecoin-project/lotus/pull/4250)
- Update markets v0.7.1 (https://github.com/filecoin-project/lotus/pull/4254)
- Optimize SearchForMessage and GetReceipt (https://github.com/filecoin-project/lotus/pull/4246)
- Use FIL instead of attoFIL in CLI more consistently (https://github.com/filecoin-project/lotus/pull/4249)
- fix: clash between daemon --api flag and cli tests (https://github.com/filecoin-project/lotus/pull/4241)
- add more info to chain sync lookback failure (https://github.com/filecoin-project/lotus/pull/4245)
- Add message counts to inspect chain output (https://github.com/filecoin-project/lotus/pull/4230)
# 0.9.0 / 2020-10-07
This consensus-breaking release of Lotus upgrades the actors version to v2.0.0. This requires migrating actor state from v0 to v2. The changes that break consensus are:
+6
View File
@@ -186,6 +186,12 @@ lotus-health:
.PHONY: lotus-health
BINS+=lotus-health
lotus-wallet:
rm -f lotus-wallet
go build -o lotus-wallet ./cmd/lotus-wallet
.PHONY: lotus-wallet
BINS+=lotus-wallet
testground:
go build -tags testground -o /dev/null ./cmd/lotus
.PHONY: testground
+27 -5
View File
@@ -172,6 +172,9 @@ type FullNode interface {
// SyncUnmarkBad unmarks a blocks as bad, making it possible to be validated and synced again.
SyncUnmarkBad(ctx context.Context, bcid cid.Cid) error
// SyncUnmarkAllBad purges bad block cache, making it possible to sync to chains previously marked as bad
SyncUnmarkAllBad(ctx context.Context) error
// SyncCheckBad checks if a block was marked as bad, and if it was, returns
// the reason.
SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error)
@@ -367,6 +370,10 @@ type FullNode interface {
// StateWaitMsg looks back in the chain for a message. If not found, it blocks until the
// message arrives on chain, and gets to the indicated confidence depth.
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error)
// StateWaitMsgLimited looks back up to limit epochs in the chain for a message.
// If not found, it blocks until the message arrives on chain, and gets to the
// indicated confidence depth.
StateWaitMsgLimited(ctx context.Context, cid cid.Cid, confidence uint64, limit abi.ChainEpoch) (*MsgLookup, error)
// StateListMiners returns the addresses of every miner that has claimed power in the Power Actor
StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error)
// StateListActors returns the addresses of every actor in the state
@@ -418,8 +425,7 @@ type FullNode interface {
// MsigGetAvailableBalance returns the portion of a multisig's balance that can be withdrawn or spent
MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
// MsigGetLockedBalance returns the locked balance of an msig at a vien epoch.
// The return may be greater than the multisig actor's actual balance.
// MsigGetVestingSchedule returns the vesting details of a given multisig.
MsigGetVestingSchedule(context.Context, address.Address, types.TipSetKey) (MsigVesting, error)
// MsigGetVested returns the amount of FIL that vested in a multisig in a certain period.
// It takes the following params: <multisig address>, <start epoch>, <end epoch>
@@ -432,12 +438,21 @@ type FullNode interface {
// It takes the following params: <multisig address>, <recipient address>, <value to transfer>,
// <sender address of the propose msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigPropose(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
// MsigApprove approves a previously-proposed multisig message
// MsigApprove approves a previously-proposed multisig message by transaction ID
// It takes the following params: <multisig address>, <proposed transaction ID> <signer address>
MsigApprove(context.Context, address.Address, uint64, address.Address) (cid.Cid, error)
// MsigApproveTxnHash approves a previously-proposed multisig message, specified
// using both transaction ID and a hash of the parameters used in the
// proposal. This method of approval can be used to ensure you only approve
// exactly the transaction you think you are.
// It takes the following params: <multisig address>, <proposed message ID>, <proposer address>, <recipient address>, <value to transfer>,
// <sender address of the approve msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigApprove(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
MsigApproveTxnHash(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
// MsigCancel cancels a previously-proposed multisig message
// It takes the following params: <multisig address>, <proposed message ID>, <recipient address>, <value to transfer>,
// It takes the following params: <multisig address>, <proposed transaction ID>, <recipient address>, <value to transfer>,
// <sender address of the cancel msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigCancel(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
// MsigAddPropose proposes adding a signer in the multisig
@@ -465,6 +480,13 @@ type FullNode interface {
// <old signer>, <new signer>
MsigSwapCancel(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error)
// MsigRemoveSigner proposes the removal of a signer from the multisig.
// It accepts the multisig to make the change on, the proposer address to
// send the message from, the address to be removed, and a boolean
// indicating whether or not the signing threshold should be lowered by one
// along with the address removal.
MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error)
MarketEnsureAvailable(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error)
// MarketFreeBalance
+24
View File
@@ -0,0 +1,24 @@
package api
import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
)
type GatewayAPI interface {
ChainHead(ctx context.Context) (*types.TipSet, error)
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, 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)
StateGetActor(ctx context.Context, actor address.Address, ts 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) (*MsgLookup, error)
}
+47
View File
@@ -0,0 +1,47 @@
package api
import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/chain/types"
)
type MsgType string
const (
MTUnknown = "unknown"
// Signing message CID. MsgMeta.Extra contains raw cbor message bytes
MTChainMsg = "message"
// Signing a blockheader. signing raw cbor block bytes (MsgMeta.Extra is empty)
MTBlock = "block"
// Signing a deal proposal. signing raw cbor proposal bytes (MsgMeta.Extra is empty)
MTDealProposal = "dealproposal"
// TODO: Deals, Vouchers, VRF
)
type MsgMeta struct {
Type MsgType
// Additional data related to what is signed. Should be verifiable with the
// signed bytes (e.g. CID(Extra).Bytes() == toSign)
Extra []byte
}
type WalletAPI interface {
WalletNew(context.Context, crypto.SigType) (address.Address, error)
WalletHas(context.Context, address.Address) (bool, error)
WalletList(context.Context) ([]address.Address, error)
WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta MsgMeta) (*crypto.Signature, error)
WalletExport(context.Context, address.Address) (*types.KeyInfo, error)
WalletImport(context.Context, *types.KeyInfo) (address.Address, error)
WalletDelete(context.Context, address.Address) error
}
+6
View File
@@ -36,3 +36,9 @@ func PermissionedWorkerAPI(a api.WorkerAPI) api.WorkerAPI {
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
return &out
}
func PermissionedWalletAPI(a api.WalletAPI) api.WalletAPI {
var out WalletStruct
auth.PermissionedProxy(AllPermissions, DefaultPerms, a, &out.Internal)
return &out
}
+126 -3
View File
@@ -111,6 +111,7 @@ type FullNodeStruct struct {
SyncCheckpoint func(ctx context.Context, key types.TipSetKey) error `perm:"admin"`
SyncMarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"`
SyncUnmarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"`
SyncUnmarkAllBad func(ctx context.Context) error `perm:"admin"`
SyncCheckBad func(ctx context.Context, bcid cid.Cid) (string, error) `perm:"read"`
SyncValidateTipset func(ctx context.Context, tsk types.TipSetKey) (bool, error) `perm:"read"`
@@ -190,6 +191,7 @@ type FullNodeStruct struct {
StateReadState func(context.Context, address.Address, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
StateMsgGasCost func(context.Context, cid.Cid, types.TipSetKey) (*api.MsgGasCost, error) `perm:"read"`
StateWaitMsg func(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) `perm:"read"`
StateWaitMsgLimited func(context.Context, cid.Cid, uint64, abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"`
StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"`
StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
@@ -216,7 +218,8 @@ type FullNodeStruct struct {
MsigGetVested func(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) `perm:"read"`
MsigCreate func(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
MsigPropose func(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
MsigApprove func(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
MsigApprove func(context.Context, address.Address, uint64, address.Address) (cid.Cid, error) `perm:"sign"`
MsigApproveTxnHash func(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
MsigCancel func(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
MsigAddPropose func(context.Context, address.Address, address.Address, address.Address, bool) (cid.Cid, error) `perm:"sign"`
MsigAddApprove func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, bool) (cid.Cid, error) `perm:"sign"`
@@ -224,6 +227,7 @@ type FullNodeStruct struct {
MsigSwapPropose func(context.Context, address.Address, address.Address, address.Address, address.Address) (cid.Cid, error) `perm:"sign"`
MsigSwapApprove func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, address.Address) (cid.Cid, error) `perm:"sign"`
MsigSwapCancel func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error) `perm:"sign"`
MsigRemoveSigner func(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error) `perm:"sign"`
MarketEnsureAvailable func(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
@@ -361,6 +365,35 @@ type WorkerStruct struct {
}
}
type GatewayStruct struct {
Internal struct {
// TODO: does the gateway need perms?
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)
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)
}
}
type WalletStruct struct {
Internal struct {
WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"`
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
WalletList func(context.Context) ([]address.Address, error) `perm:"write"`
WalletSign func(context.Context, address.Address, []byte, api.MsgMeta) (*crypto.Signature, error) `perm:"sign"`
WalletExport func(context.Context, address.Address) (*types.KeyInfo, error) `perm:"admin"`
WalletImport func(context.Context, *types.KeyInfo) (address.Address, error) `perm:"admin"`
WalletDelete func(context.Context, address.Address) error `perm:"write"`
}
}
// CommonStruct
func (c *CommonStruct) AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) {
@@ -750,6 +783,10 @@ func (c *FullNodeStruct) SyncUnmarkBad(ctx context.Context, bcid cid.Cid) error
return c.Internal.SyncUnmarkBad(ctx, bcid)
}
func (c *FullNodeStruct) SyncUnmarkAllBad(ctx context.Context) error {
return c.Internal.SyncUnmarkAllBad(ctx)
}
func (c *FullNodeStruct) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) {
return c.Internal.SyncCheckBad(ctx, bcid)
}
@@ -854,6 +891,10 @@ func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid, confide
return c.Internal.StateWaitMsg(ctx, msgc, confidence)
}
func (c *FullNodeStruct) StateWaitMsgLimited(ctx context.Context, msgc cid.Cid, confidence uint64, limit abi.ChainEpoch) (*api.MsgLookup, error) {
return c.Internal.StateWaitMsgLimited(ctx, msgc, confidence, limit)
}
func (c *FullNodeStruct) StateSearchMsg(ctx context.Context, msgc cid.Cid) (*api.MsgLookup, error) {
return c.Internal.StateSearchMsg(ctx, msgc)
}
@@ -950,8 +991,12 @@ func (c *FullNodeStruct) MsigPropose(ctx context.Context, msig address.Address,
return c.Internal.MsigPropose(ctx, msig, to, amt, src, method, params)
}
func (c *FullNodeStruct) MsigApprove(ctx context.Context, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
return c.Internal.MsigApprove(ctx, msig, txID, proposer, to, amt, src, method, params)
func (c *FullNodeStruct) MsigApprove(ctx context.Context, msig address.Address, txID uint64, signer address.Address) (cid.Cid, error) {
return c.Internal.MsigApprove(ctx, msig, txID, signer)
}
func (c *FullNodeStruct) MsigApproveTxnHash(ctx context.Context, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
return c.Internal.MsigApproveTxnHash(ctx, msig, txID, proposer, to, amt, src, method, params)
}
func (c *FullNodeStruct) MsigCancel(ctx context.Context, msig address.Address, txID uint64, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
@@ -982,6 +1027,10 @@ func (c *FullNodeStruct) MsigSwapCancel(ctx context.Context, msig address.Addres
return c.Internal.MsigSwapCancel(ctx, msig, src, txID, oldAdd, newAdd)
}
func (c *FullNodeStruct) MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error) {
return c.Internal.MsigRemoveSigner(ctx, msig, proposer, toRemove, decrease)
}
func (c *FullNodeStruct) MarketEnsureAvailable(ctx context.Context, addr, wallet address.Address, amt types.BigInt) (cid.Cid, error) {
return c.Internal.MarketEnsureAvailable(ctx, addr, wallet, amt)
}
@@ -1372,7 +1421,81 @@ func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
return w.Internal.Closing(ctx)
}
func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
return g.Internal.ChainHead(ctx)
}
func (g GatewayStruct) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
return g.Internal.ChainGetTipSet(ctx, tsk)
}
func (g GatewayStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
}
func (g GatewayStruct) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
return g.Internal.GasEstimateMessageGas(ctx, msg, spec, tsk)
}
func (g GatewayStruct) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
return g.Internal.MpoolPush(ctx, sm)
}
func (g GatewayStruct) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
return g.Internal.MsigGetAvailableBalance(ctx, addr, tsk)
}
func (g GatewayStruct) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
return g.Internal.MsigGetVested(ctx, addr, start, end)
}
func (g GatewayStruct) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
return g.Internal.StateAccountKey(ctx, addr, 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) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
return g.Internal.StateLookupID(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)
}
func (c *WalletStruct) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
return c.Internal.WalletNew(ctx, typ)
}
func (c *WalletStruct) WalletHas(ctx context.Context, addr address.Address) (bool, error) {
return c.Internal.WalletHas(ctx, addr)
}
func (c *WalletStruct) WalletList(ctx context.Context) ([]address.Address, error) {
return c.Internal.WalletList(ctx)
}
func (c *WalletStruct) WalletSign(ctx context.Context, k address.Address, msg []byte, meta api.MsgMeta) (*crypto.Signature, error) {
return c.Internal.WalletSign(ctx, k, msg, meta)
}
func (c *WalletStruct) WalletExport(ctx context.Context, a address.Address) (*types.KeyInfo, error) {
return c.Internal.WalletExport(ctx, a)
}
func (c *WalletStruct) WalletImport(ctx context.Context, ki *types.KeyInfo) (address.Address, error) {
return c.Internal.WalletImport(ctx, ki)
}
func (c *WalletStruct) WalletDelete(ctx context.Context, addr address.Address) error {
return c.Internal.WalletDelete(ctx, addr)
}
var _ api.Common = &CommonStruct{}
var _ api.FullNode = &FullNodeStruct{}
var _ api.StorageMiner = &StorageMinerStruct{}
var _ api.WorkerAPI = &WorkerStruct{}
var _ api.GatewayAPI = &GatewayStruct{}
var _ api.WalletAPI = &WalletStruct{}
+26
View File
@@ -82,3 +82,29 @@ func NewWorkerRPC(ctx context.Context, addr string, requestHeader http.Header) (
return &res, closer, err
}
// NewGatewayRPC creates a new http jsonrpc client for a gateway node.
func NewGatewayRPC(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (api.GatewayAPI, jsonrpc.ClientCloser, error) {
var res apistruct.GatewayStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
&res.Internal,
},
requestHeader,
opts...,
)
return &res, closer, err
}
func NewWalletRPC(ctx context.Context, addr string, requestHeader http.Header) (api.WalletAPI, jsonrpc.ClientCloser, error) {
var res apistruct.WalletStruct
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
[]interface{}{
&res.Internal,
},
requestHeader,
)
return &res, closer, err
}
+1 -8
View File
@@ -12,10 +12,7 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node"
"github.com/filecoin-project/lotus/node/impl"
)
@@ -37,11 +34,7 @@ func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeHeight abi.ChainEpoch) {
ctx := context.Background()
n, sn := b(t, 1, OneMiner, node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
Network: build.ActorUpgradeNetworkVersion,
Height: upgradeHeight,
Migration: stmgr.UpgradeActorsV2,
}}))
n, sn := b(t, []FullNodeOpts{FullNodeWithUpgradeAt(upgradeHeight)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
+4 -4
View File
@@ -48,7 +48,7 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, OneMiner)
n, sn := b(t, OneFull, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@@ -85,7 +85,7 @@ func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, OneMiner)
n, sn := b(t, OneFull, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@@ -149,7 +149,7 @@ func TestFastRetrievalDealFlow(t *testing.T, b APIBuilder, blocktime time.Durati
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, OneMiner)
n, sn := b(t, OneFull, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@@ -204,7 +204,7 @@ func TestSenondDealRetrieval(t *testing.T, b APIBuilder, blocktime time.Duration
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 1, OneMiner)
n, sn := b(t, OneFull, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
+3 -3
View File
@@ -25,7 +25,7 @@ var log = logging.Logger("apitest")
func (ts *testSuite) testMining(t *testing.T) {
ctx := context.Background()
apis, sn := ts.makeNodes(t, 1, OneMiner)
apis, sn := ts.makeNodes(t, OneFull, OneMiner)
api := apis[0]
newHeads, err := api.ChainNotify(ctx)
@@ -54,7 +54,7 @@ func (ts *testSuite) testMiningReal(t *testing.T) {
}()
ctx := context.Background()
apis, sn := ts.makeNodes(t, 1, OneMiner)
apis, sn := ts.makeNodes(t, OneFull, OneMiner)
api := apis[0]
newHeads, err := api.ChainNotify(ctx)
@@ -93,7 +93,7 @@ func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExpo
// test making a deal with a fresh miner, and see if it starts to mine
ctx := context.Background()
n, sn := b(t, 1, []StorageMiner{
n, sn := b(t, OneFull, []StorageMiner{
{Full: 0, Preseal: PresealGenesis},
{Full: 0, Preseal: 0}, // TODO: Add support for miners on non-first full node
})
+1 -1
View File
@@ -33,7 +33,7 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
ctx := context.Background()
n, sn := b(t, 2, OneMiner)
n, sn := b(t, TwoFull, OneMiner)
paymentCreator := n[0]
paymentReceiver := n[1]
+43 -4
View File
@@ -4,11 +4,14 @@ import (
"context"
"testing"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/miner"
@@ -35,17 +38,27 @@ var PresealGenesis = -1
const GenesisPreseals = 2
// Options for setting up a mock storage miner
type StorageMiner struct {
Full int
Preseal int
}
type OptionGenerator func([]TestNode) node.Option
// Options for setting up a mock full node
type FullNodeOpts struct {
Lite bool // run node in "lite" mode
Opts OptionGenerator // generate dependency injection options
}
// APIBuilder is a function which is invoked in test suite to provide
// test nodes and networks
//
// fullOpts array defines options for each full node
// storage array defines storage nodes, numbers in the array specify full node
// index the storage node 'belongs' to
type APIBuilder func(t *testing.T, nFull int, storage []StorageMiner, opts ...node.Option) ([]TestNode, []TestStorageNode)
type APIBuilder func(t *testing.T, full []FullNodeOpts, storage []StorageMiner) ([]TestNode, []TestStorageNode)
type testSuite struct {
makeNodes APIBuilder
}
@@ -63,13 +76,39 @@ func TestApis(t *testing.T, b APIBuilder) {
t.Run("testMiningReal", ts.testMiningReal)
}
func DefaultFullOpts(nFull int) []FullNodeOpts {
full := make([]FullNodeOpts, nFull)
for i := range full {
full[i] = FullNodeOpts{
Opts: func(nodes []TestNode) node.Option {
return node.Options()
},
}
}
return full
}
var OneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}}
var OneFull = DefaultFullOpts(1)
var TwoFull = DefaultFullOpts(2)
var FullNodeWithUpgradeAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
return FullNodeOpts{
Opts: func(nodes []TestNode) node.Option {
return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
Network: build.ActorUpgradeNetworkVersion,
Height: upgradeHeight,
Migration: stmgr.UpgradeActorsV2,
}})
},
}
}
func (ts *testSuite) testVersion(t *testing.T) {
build.RunningNodeType = build.NodeFull
ctx := context.Background()
apis, _ := ts.makeNodes(t, 1, OneMiner)
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
api := apis[0]
v, err := api.Version(ctx)
@@ -81,7 +120,7 @@ func (ts *testSuite) testVersion(t *testing.T) {
func (ts *testSuite) testID(t *testing.T) {
ctx := context.Background()
apis, _ := ts.makeNodes(t, 1, OneMiner)
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
api := apis[0]
id, err := api.ID(ctx)
@@ -93,7 +132,7 @@ func (ts *testSuite) testID(t *testing.T) {
func (ts *testSuite) testConnectTwo(t *testing.T) {
ctx := context.Background()
apis, _ := ts.makeNodes(t, 2, OneMiner)
apis, _ := ts.makeNodes(t, TwoFull, OneMiner)
p, err := apis[0].NetPeers(ctx)
if err != nil {
+9 -12
View File
@@ -3,6 +3,7 @@ package test
import (
"context"
"fmt"
"sync/atomic"
"os"
"strings"
@@ -15,11 +16,9 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/extern/sector-storage/mock"
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
"github.com/filecoin-project/lotus/node"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
bminer "github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/lotus/node/impl"
@@ -33,8 +32,10 @@ func init() {
}
func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
ctx := context.Background()
n, sn := b(t, 1, OneMiner)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
n, sn := b(t, OneFull, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@@ -48,11 +49,11 @@ func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSect
}
build.Clock.Sleep(time.Second)
mine := true
mine := int64(1)
done := make(chan struct{})
go func() {
defer close(done)
for mine {
for atomic.LoadInt64(&mine) != 0 {
build.Clock.Sleep(blocktime)
if err := sn[0].MineOne(ctx, bminer.MineReq{Done: func(bool, abi.ChainEpoch, error) {
@@ -64,7 +65,7 @@ func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSect
pledgeSectors(t, ctx, miner, nSectors, 0, nil)
mine = false
atomic.StoreInt64(&mine, 0)
<-done
}
@@ -133,11 +134,7 @@ func testWindowPostUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration,
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
n, sn := b(t, 1, OneMiner, node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
Network: build.ActorUpgradeNetworkVersion,
Height: upgradeHeight,
Migration: stmgr.UpgradeActorsV2,
}}))
n, sn := b(t, []FullNodeOpts{FullNodeWithUpgradeAt(upgradeHeight)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
+4 -12
View File
@@ -1,12 +1,4 @@
/dns4/bootstrap-0.testnet.fildev.network/tcp/1347/p2p/12D3KooWJTUBUjtzWJGWU1XSiY21CwmHaCNLNYn2E7jqHEHyZaP7
/dns4/bootstrap-1.testnet.fildev.network/tcp/1347/p2p/12D3KooW9yeKXha4hdrJKq74zEo99T8DhriQdWNoojWnnQbsgB3v
/dns4/bootstrap-2.testnet.fildev.network/tcp/1347/p2p/12D3KooWCrx8yVG9U9Kf7w8KLN3Edkj5ZKDhgCaeMqQbcQUoB6CT
/dns4/bootstrap-4.testnet.fildev.network/tcp/1347/p2p/12D3KooWPkL9LrKRQgHtq7kn9ecNhGU9QaziG8R5tX8v9v7t3h34
/dns4/bootstrap-3.testnet.fildev.network/tcp/1347/p2p/12D3KooWKYSsbpgZ3HAjax5M1BXCwXLa6gVkUARciz7uN3FNtr7T
/dns4/bootstrap-5.testnet.fildev.network/tcp/1347/p2p/12D3KooWQYzqnLASJAabyMpPb1GcWZvNSe7JDcRuhdRqonFoiK9W
/dns4/lotus-bootstrap.forceup.cn/tcp/41778/p2p/12D3KooWFQsv3nRMUevZNWWsY1Wu6NUzUbawnWU5NcRhgKuJA37C
/dns4/bootstrap-0.starpool.in/tcp/12757/p2p/12D3KooWGHpBMeZbestVEWkfdnC9u7p6uFHXL1n7m1ZBqsEmiUzz
/dns4/bootstrap-1.starpool.in/tcp/12757/p2p/12D3KooWQZrGH1PxSNZPum99M1zNvjNFM33d1AAu5DcvdHptuU7u
/dns4/node.glif.io/tcp/1235/p2p/12D3KooWBF8cpp65hp2u9LK5mh19x67ftAam84z9LsfaquTDSBpt
/dns4/bootstrap-0.ipfsmain.cn/tcp/34721/p2p/12D3KooWQnwEGNqcM2nAcPtRR9rAX8Hrg4k9kJLCHoTR5chJfz6d
/dns4/bootstrap-1.ipfsmain.cn/tcp/34723/p2p/12D3KooWMKxMkD5DMpSWsW7dBddKxKT7L2GgbNuckz9otxvkvByP
/dns4/bootstrap-0.calibration.fildev.network/tcp/1347/p2p/12D3KooWGru4fBMc12t4rcwp9UxRAK1o8JBLdAJNL1fdYpQuu6mg
/dns4/bootstrap-1.calibration.fildev.network/tcp/1347/p2p/12D3KooWCaXUxN1cSjfS3SYM93Tv1itnUExXkohRzct1bAtjSEJ2
/dns4/bootstrap-2.calibration.fildev.network/tcp/1347/p2p/12D3KooWSdjKZoigrDK7Qkpbmk5Pk1X7c6M2YB8gjN4qEXW79cp7
/dns4/bootstrap-3.calibration.fildev.network/tcp/1347/p2p/12D3KooWR21sXfgX7MEQZEwdtPL1RwRAormMiYL1zo2h7Gmg4Tit
Binary file not shown.
+2 -1
View File
@@ -17,9 +17,10 @@ const BreezeGasTampingDuration = 0
const UpgradeSmokeHeight = -1
const UpgradeIgnitionHeight = -2
const UpgradeRefuelHeight = -3
const UpgradeTapeHeight = -4
var UpgradeActorsV2Height = abi.ChainEpoch(10)
var UpgradeLiftoffHeight = abi.ChainEpoch(-4)
var UpgradeLiftoffHeight = abi.ChainEpoch(-5)
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
+1 -1
View File
@@ -25,7 +25,7 @@ const UnixfsLinksPerLevel = 1024
// Consensus / Network
const AllowableClockDriftSecs = uint64(1)
const NewestNetworkVersion = network.Version4
const NewestNetworkVersion = network.Version5
const ActorUpgradeNetworkVersion = network.Version4
// Epochs
+3 -2
View File
@@ -83,14 +83,15 @@ var (
UpgradeSmokeHeight abi.ChainEpoch = -1
UpgradeIgnitionHeight abi.ChainEpoch = -2
UpgradeRefuelHeight abi.ChainEpoch = -3
UpgradeTapeHeight abi.ChainEpoch = -4
UpgradeActorsV2Height abi.ChainEpoch = 10
UpgradeLiftoffHeight abi.ChainEpoch = -4
UpgradeLiftoffHeight abi.ChainEpoch = -5
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
}
NewestNetworkVersion = network.Version4
NewestNetworkVersion = network.Version5
ActorUpgradeNetworkVersion = network.Version4
Devnet = true
+12 -19
View File
@@ -5,9 +5,6 @@
package build
import (
"math"
"os"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/policy"
@@ -16,19 +13,20 @@ import (
)
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandIncentinet,
UpgradeSmokeHeight: DrandMainnet,
0: DrandMainnet,
}
const UpgradeBreezeHeight = 41280
const UpgradeBreezeHeight = -1
const BreezeGasTampingDuration = 120
const UpgradeSmokeHeight = 51000
const UpgradeSmokeHeight = -2
const UpgradeIgnitionHeight = 94000
const UpgradeRefuelHeight = 130800
const UpgradeIgnitionHeight = -3
const UpgradeRefuelHeight = -4
var UpgradeActorsV2Height = abi.ChainEpoch(138720)
const UpgradeActorsV2Height = 500
const UpgradeTapeHeight = 15000
// This signals our tentative epoch for mainnet launch. Can make it later, but not earlier.
// Miners, clients, developers, custodians all need time to prepare.
@@ -36,21 +34,16 @@ var UpgradeActorsV2Height = abi.ChainEpoch(138720)
const UpgradeLiftoffHeight = 148888
func init() {
policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40))
policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 30))
policy.SetSupportedProofTypes(
abi.RegisteredSealProof_StackedDrg512MiBV1,
abi.RegisteredSealProof_StackedDrg32GiBV1,
abi.RegisteredSealProof_StackedDrg64GiBV1,
)
if os.Getenv("LOTUS_USE_TEST_ADDRESSES") != "1" {
SetAddressNetwork(address.Mainnet)
}
SetAddressNetwork(address.Testnet)
if os.Getenv("LOTUS_DISABLE_V2_ACTOR_MIGRATION") == "1" {
UpgradeActorsV2Height = math.MaxInt64
}
Devnet = false
Devnet = true
}
const BlockDelaySecs = uint64(builtin0.EpochDurationSeconds)
+1 -1
View File
@@ -29,7 +29,7 @@ func buildType() string {
}
// BuildVersion is the local build version, set by build system
const BuildVersion = "0.9.0"
const BuildVersion = "0.9.1"
func UserVersion() string {
return BuildVersion + buildType() + CurrentCommit
+1
View File
@@ -51,6 +51,7 @@ type State interface {
MinerPower(address.Address) (Claim, bool, error)
MinerNominalPowerMeetsConsensusMinimum(address.Address) (bool, error)
ListAllMiners() ([]address.Address, error)
ForEachClaim(func(miner address.Address, claim Claim) error) error
}
type Claim struct {
+19
View File
@@ -96,3 +96,22 @@ func (s *state0) ListAllMiners() ([]address.Address, error) {
return miners, nil
}
func (s *state0) ForEachClaim(cb func(miner address.Address, claim Claim) error) error {
claims, err := adt0.AsMap(s.store, s.Claims)
if err != nil {
return err
}
var claim power0.Claim
return claims.ForEach(&claim, func(k string) error {
a, err := address.NewFromBytes([]byte(k))
if err != nil {
return err
}
return cb(a, Claim{
RawBytePower: claim.RawBytePower,
QualityAdjPower: claim.QualityAdjPower,
})
})
}
+19
View File
@@ -96,3 +96,22 @@ func (s *state2) ListAllMiners() ([]address.Address, error) {
return miners, nil
}
func (s *state2) ForEachClaim(cb func(miner address.Address, claim Claim) error) error {
claims, err := adt2.AsMap(s.store, s.Claims)
if err != nil {
return err
}
var claim power2.Claim
return claims.ForEach(&claim, func(k string) error {
a, err := address.NewFromBytes([]byte(k))
if err != nil {
return err
}
return cb(a, Claim{
RawBytePower: claim.RawBytePower,
QualityAdjPower: claim.QualityAdjPower,
})
})
}
+1 -1
View File
@@ -57,7 +57,7 @@ func (s *state0) CumsumBaseline() (abi.StoragePower, error) {
}
func (s *state0) CumsumRealized() (abi.StoragePower, error) {
return s.State.CumsumBaseline, nil
return s.State.CumsumRealized, nil
}
func (s *state0) InitialPledgeForPower(sectorWeight abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) {
+1 -1
View File
@@ -60,7 +60,7 @@ func (s *state2) CumsumBaseline() (abi.StoragePower, error) {
}
func (s *state2) CumsumRealized() (abi.StoragePower, error) {
return s.State.CumsumBaseline, nil
return s.State.CumsumRealized, nil
}
func (s *state2) InitialPledgeForPower(qaPower abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) {
+1 -1
View File
@@ -18,7 +18,7 @@ func VersionForNetwork(version network.Version) Version {
switch version {
case network.Version0, network.Version1, network.Version2, network.Version3:
return Version0
case network.Version4:
case network.Version4, network.Version5:
return Version2
default:
panic(fmt.Sprintf("unsupported network version %d", version))
+4
View File
@@ -60,6 +60,10 @@ func (bts *BadBlockCache) Remove(c cid.Cid) {
bts.badBlocks.Remove(c)
}
func (bts *BadBlockCache) Purge() {
bts.badBlocks.Purge()
}
func (bts *BadBlockCache) Has(c cid.Cid) (BadBlockReason, bool) {
rval, ok := bts.badBlocks.Get(c)
if !ok {
+24 -2
View File
@@ -2,6 +2,7 @@ package events
import (
"context"
"sync"
"github.com/filecoin-project/go-state-types/abi"
"golang.org/x/xerrors"
@@ -17,6 +18,8 @@ type tsCacheAPI interface {
// tipSetCache implements a simple ring-buffer cache to keep track of recent
// tipsets
type tipSetCache struct {
mu sync.RWMutex
cache []*types.TipSet
start int
len int
@@ -35,6 +38,9 @@ func newTSCache(cap abi.ChainEpoch, storage tsCacheAPI) *tipSetCache {
}
func (tsc *tipSetCache) add(ts *types.TipSet) error {
tsc.mu.Lock()
defer tsc.mu.Unlock()
if tsc.len > 0 {
if tsc.cache[tsc.start].Height() >= ts.Height() {
return xerrors.Errorf("tipSetCache.add: expected new tipset height to be at least %d, was %d", tsc.cache[tsc.start].Height()+1, ts.Height())
@@ -65,6 +71,13 @@ func (tsc *tipSetCache) add(ts *types.TipSet) error {
}
func (tsc *tipSetCache) revert(ts *types.TipSet) error {
tsc.mu.Lock()
defer tsc.mu.Unlock()
return tsc.revertUnlocked(ts)
}
func (tsc *tipSetCache) revertUnlocked(ts *types.TipSet) error {
if tsc.len == 0 {
return nil // this can happen, and it's fine
}
@@ -77,7 +90,7 @@ func (tsc *tipSetCache) revert(ts *types.TipSet) error {
tsc.start = normalModulo(tsc.start-1, len(tsc.cache))
tsc.len--
_ = tsc.revert(nil) // revert null block gap
_ = tsc.revertUnlocked(nil) // revert null block gap
return nil
}
@@ -95,7 +108,10 @@ func (tsc *tipSetCache) getNonNull(height abi.ChainEpoch) (*types.TipSet, error)
}
func (tsc *tipSetCache) get(height abi.ChainEpoch) (*types.TipSet, error) {
tsc.mu.RLock()
if tsc.len == 0 {
tsc.mu.RUnlock()
log.Warnf("tipSetCache.get: cache is empty, requesting from storage (h=%d)", height)
return tsc.storage.ChainGetTipSetByHeight(context.TODO(), height, types.EmptyTSK)
}
@@ -103,6 +119,7 @@ func (tsc *tipSetCache) get(height abi.ChainEpoch) (*types.TipSet, error) {
headH := tsc.cache[tsc.start].Height()
if height > headH {
tsc.mu.RUnlock()
return nil, xerrors.Errorf("tipSetCache.get: requested tipset not in cache (req: %d, cache head: %d)", height, headH)
}
@@ -116,15 +133,20 @@ func (tsc *tipSetCache) get(height abi.ChainEpoch) (*types.TipSet, error) {
}
if height < tail.Height() {
tsc.mu.RUnlock()
log.Warnf("tipSetCache.get: requested tipset not in cache, requesting from storage (h=%d; tail=%d)", height, tail.Height())
return tsc.storage.ChainGetTipSetByHeight(context.TODO(), height, tail.Key())
}
return tsc.cache[normalModulo(tsc.start-int(headH-height), clen)], nil
ts := tsc.cache[normalModulo(tsc.start-int(headH-height), clen)]
tsc.mu.RUnlock()
return ts, nil
}
func (tsc *tipSetCache) best() (*types.TipSet, error) {
tsc.mu.RLock()
best := tsc.cache[tsc.start]
tsc.mu.RUnlock()
if best == nil {
return tsc.storage.ChainHead(context.TODO())
}
+24 -12
View File
@@ -39,6 +39,7 @@ import (
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
"github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/journal"
"github.com/filecoin-project/lotus/lib/blockstore"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/node/repo"
@@ -71,7 +72,7 @@ type ChainGen struct {
GetMessages func(*ChainGen) ([]*types.SignedMessage, error)
w *wallet.Wallet
w *wallet.LocalWallet
eppProvs map[address.Address]WinningPoStProver
Miners []address.Address
@@ -122,6 +123,7 @@ var DefaultRemainderAccountActor = genesis.Actor{
}
func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
j := journal.NilJournal()
// TODO: we really shouldn't modify a global variable here.
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
@@ -153,14 +155,14 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err)
}
banker, err := w.GenerateKey(crypto.SigTypeSecp256k1)
banker, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
return nil, xerrors.Errorf("failed to generate banker key: %w", err)
}
receievers := make([]address.Address, msgsPerBlock)
for r := range receievers {
receievers[r], err = w.GenerateKey(crypto.SigTypeBLS)
receievers[r], err = w.WalletNew(context.Background(), crypto.SigTypeBLS)
if err != nil {
return nil, xerrors.Errorf("failed to generate receiver key: %w", err)
}
@@ -190,11 +192,11 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
return nil, err
}
mk1, err := w.Import(k1)
mk1, err := w.WalletImport(context.Background(), k1)
if err != nil {
return nil, err
}
mk2, err := w.Import(k2)
mk2, err := w.WalletImport(context.Background(), k2)
if err != nil {
return nil, err
}
@@ -229,12 +231,12 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
Timestamp: uint64(build.Clock.Now().Add(-500 * time.Duration(build.BlockDelaySecs) * time.Second).Unix()),
}
genb, err := genesis2.MakeGenesisBlock(context.TODO(), bs, sys, tpl)
genb, err := genesis2.MakeGenesisBlock(context.TODO(), j, bs, sys, tpl)
if err != nil {
return nil, xerrors.Errorf("make genesis block failed: %w", err)
}
cs := store.NewChainStore(bs, ds, sys)
cs := store.NewChainStore(bs, ds, sys, j)
genfb := &types.FullBlock{Header: genb.Genesis}
gents := store.NewFullTipSet([]*types.FullBlock{genfb})
@@ -374,7 +376,13 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
return nil, nil, nil, xerrors.Errorf("get miner worker: %w", err)
}
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, ticketRand)
sf := func(ctx context.Context, a address.Address, i []byte) (*crypto.Signature, error) {
return cg.w.WalletSign(ctx, a, i, api.MsgMeta{
Type: api.MTUnknown,
})
}
vrfout, err := ComputeVRF(ctx, sf, worker, ticketRand)
if err != nil {
return nil, nil, nil, xerrors.Errorf("compute VRF: %w", err)
}
@@ -506,7 +514,7 @@ func (cg *ChainGen) Banker() address.Address {
return cg.banker
}
func (cg *ChainGen) Wallet() *wallet.Wallet {
func (cg *ChainGen) Wallet() *wallet.LocalWallet {
return cg.w
}
@@ -528,7 +536,9 @@ func getRandomMessages(cg *ChainGen) ([]*types.SignedMessage, error) {
GasPremium: types.NewInt(0),
}
sig, err := cg.w.Sign(context.TODO(), cg.banker, msg.Cid().Bytes())
sig, err := cg.w.WalletSign(context.TODO(), cg.banker, msg.Cid().Bytes(), api.MsgMeta{
Type: api.MTUnknown, // testing
})
if err != nil {
return nil, err
}
@@ -559,7 +569,7 @@ type MiningCheckAPI interface {
}
type mca struct {
w *wallet.Wallet
w *wallet.LocalWallet
sm *stmgr.StateManager
pv ffiwrapper.Verifier
bcn beacon.Schedule
@@ -588,7 +598,9 @@ func (mca mca) MinerGetBaseInfo(ctx context.Context, maddr address.Address, epoc
}
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*crypto.Signature, error) {
return mca.w.Sign(ctx, a, v)
return mca.w.WalletSign(ctx, a, v, api.MsgMeta{
Type: api.MTUnknown,
})
}
type WinningPoStProver interface {
+6 -2
View File
@@ -7,6 +7,7 @@ import (
"fmt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/journal"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
@@ -466,7 +467,10 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
return st, nil
}
func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys vm.SyscallBuilder, template genesis.Template) (*GenesisBootstrap, error) {
func MakeGenesisBlock(ctx context.Context, j journal.Journal, bs bstore.Blockstore, sys vm.SyscallBuilder, template genesis.Template) (*GenesisBootstrap, error) {
if j == nil {
j = journal.NilJournal()
}
st, keyIDs, err := MakeInitialStateTree(ctx, bs, template)
if err != nil {
return nil, xerrors.Errorf("make initial state tree failed: %w", err)
@@ -478,7 +482,7 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys vm.SyscallB
}
// temp chainstore
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys)
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys, j)
// Verify PreSealed Data
stateroot, err = VerifyPreSealedData(ctx, cs, stateroot, template, keyIDs)
+4 -3
View File
@@ -15,11 +15,10 @@ import (
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/lib/sigs/bls"
)
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, bt *api.BlockTemplate) (*types.FullBlock, error) {
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w api.WalletAPI, bt *api.BlockTemplate) (*types.FullBlock, error) {
pts, err := sm.ChainStore().LoadTipSet(bt.Parents)
if err != nil {
@@ -131,7 +130,9 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
return nil, xerrors.Errorf("failed to get signing bytes for block: %w", err)
}
sig, err := w.Sign(ctx, waddr, nosigbytes)
sig, err := w.WalletSign(ctx, waddr, nosigbytes, api.MsgMeta{
Type: api.MTBlock,
})
if err != nil {
return nil, xerrors.Errorf("failed to sign new block: %w", err)
}
+4 -2
View File
@@ -120,9 +120,10 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
return cid.Undef, err
}
fm.lk.Lock()
defer fm.lk.Unlock()
bal, err := fm.api.StateMarketBalance(ctx, addr, types.EmptyTSK)
if err != nil {
fm.lk.Unlock()
return cid.Undef, err
}
@@ -138,7 +139,6 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
toAdd = types.NewInt(0)
}
fm.available[idAddr] = big.Add(avail, toAdd)
fm.lk.Unlock()
log.Infof("Funds operation w/ Expected Balance: %s, In State: %s, Requested: %s, Adding: %s", avail.String(), stateAvail.String(), amt.String(), toAdd.String())
@@ -148,6 +148,7 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
params, err := actors.SerializeParams(&addr)
if err != nil {
fm.available[idAddr] = avail
return cid.Undef, err
}
@@ -159,6 +160,7 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
Params: params,
}, nil)
if err != nil {
fm.available[idAddr] = avail
return cid.Undef, err
}
+24 -14
View File
@@ -57,9 +57,10 @@ func addFundsMsg(toAdd abi.TokenAmount, addr address.Address, wallet address.Add
}
type expectedResult struct {
addAmt abi.TokenAmount
shouldAdd bool
err error
addAmt abi.TokenAmount
shouldAdd bool
err error
cachedAvailable abi.TokenAmount
}
func TestAddFunds(t *testing.T) {
@@ -88,8 +89,9 @@ func TestAddFunds(t *testing.T) {
addAmounts: []abi.TokenAmount{abi.NewTokenAmount(100)},
expectedResults: []expectedResult{
{
shouldAdd: false,
err: nil,
shouldAdd: false,
err: nil,
cachedAvailable: abi.NewTokenAmount(100),
},
},
},
@@ -102,18 +104,21 @@ func TestAddFunds(t *testing.T) {
err: nil,
},
{
addAmt: abi.NewTokenAmount(100),
shouldAdd: true,
err: nil,
addAmt: abi.NewTokenAmount(100),
shouldAdd: true,
err: nil,
cachedAvailable: abi.NewTokenAmount(200),
},
{
addAmt: abi.NewTokenAmount(50),
shouldAdd: true,
err: nil,
addAmt: abi.NewTokenAmount(50),
shouldAdd: true,
err: nil,
cachedAvailable: abi.NewTokenAmount(250),
},
{
shouldAdd: false,
err: nil,
shouldAdd: false,
err: nil,
cachedAvailable: abi.NewTokenAmount(250),
},
},
},
@@ -132,7 +137,8 @@ func TestAddFunds(t *testing.T) {
addAmounts: []abi.TokenAmount{abi.NewTokenAmount(100)},
expectedResults: []expectedResult{
{
err: errors.New("something went wrong"),
err: errors.New("something went wrong"),
cachedAvailable: abi.NewTokenAmount(0),
},
},
},
@@ -183,6 +189,10 @@ func TestAddFunds(t *testing.T) {
} else {
require.EqualError(t, err, expected.err.Error())
}
if !expected.cachedAvailable.Nil() {
require.Equal(t, expected.cachedAvailable, fundMgr.available[addr])
}
}
})
}
+12 -6
View File
@@ -159,6 +159,7 @@ type MessagePool struct {
sigValCache *lru.TwoQueueCache
evtTypes [3]journal.EventType
journal journal.Journal
}
type msgSet struct {
@@ -316,7 +317,7 @@ func (ms *msgSet) getRequiredFunds(nonce uint64) types.BigInt {
return types.BigInt{Int: requiredFunds}
}
func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*MessagePool, error) {
func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName, j journal.Journal) (*MessagePool, error) {
cache, _ := lru.New2Q(build.BlsSignatureCacheSize)
verifcache, _ := lru.New2Q(build.VerifSigCacheSize)
@@ -325,6 +326,10 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*Messa
return nil, xerrors.Errorf("error loading mpool config: %w", err)
}
if j == nil {
j = journal.NilJournal()
}
mp := &MessagePool{
ds: ds,
addSema: make(chan struct{}, 1),
@@ -344,10 +349,11 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName) (*Messa
netName: netName,
cfg: cfg,
evtTypes: [...]journal.EventType{
evtTypeMpoolAdd: journal.J.RegisterEventType("mpool", "add"),
evtTypeMpoolRemove: journal.J.RegisterEventType("mpool", "remove"),
evtTypeMpoolRepub: journal.J.RegisterEventType("mpool", "repub"),
evtTypeMpoolAdd: j.RegisterEventType("mpool", "add"),
evtTypeMpoolRemove: j.RegisterEventType("mpool", "remove"),
evtTypeMpoolRepub: j.RegisterEventType("mpool", "repub"),
},
journal: j,
}
// enable initial prunes
@@ -744,7 +750,7 @@ func (mp *MessagePool) addLocked(m *types.SignedMessage, strict, untrusted bool)
Message: m,
}, localUpdates)
journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolAdd], func() interface{} {
mp.journal.RecordEvent(mp.evtTypes[evtTypeMpoolAdd], func() interface{} {
return MessagePoolEvt{
Action: "add",
Messages: []MessagePoolEvtMessage{{Message: m.Message, CID: m.Cid()}},
@@ -865,7 +871,7 @@ func (mp *MessagePool) remove(from address.Address, nonce uint64, applied bool)
Message: m,
}, localUpdates)
journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolRemove], func() interface{} {
mp.journal.RecordEvent(mp.evtTypes[evtTypeMpoolRemove], func() interface{} {
return MessagePoolEvt{
Action: "remove",
Messages: []MessagePoolEvtMessage{{Message: m.Message, CID: m.Cid()}}}
+21 -21
View File
@@ -225,14 +225,14 @@ func TestMessagePool(t *testing.T) {
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
a := tma.nextBlock()
sender, err := w.GenerateKey(crypto.SigTypeBLS)
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
if err != nil {
t.Fatal(err)
}
@@ -266,14 +266,14 @@ func TestMessagePoolMessagesInEachBlock(t *testing.T) {
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
a := tma.nextBlock()
sender, err := w.GenerateKey(crypto.SigTypeBLS)
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
if err != nil {
t.Fatal(err)
}
@@ -315,7 +315,7 @@ func TestRevertMessages(t *testing.T) {
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -323,7 +323,7 @@ func TestRevertMessages(t *testing.T) {
a := tma.nextBlock()
b := tma.nextBlock()
sender, err := w.GenerateKey(crypto.SigTypeBLS)
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
if err != nil {
t.Fatal(err)
}
@@ -378,7 +378,7 @@ func TestPruningSimple(t *testing.T) {
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -386,7 +386,7 @@ func TestPruningSimple(t *testing.T) {
a := tma.nextBlock()
tma.applyBlock(t, a)
sender, err := w.GenerateKey(crypto.SigTypeBLS)
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
if err != nil {
t.Fatal(err)
}
@@ -422,7 +422,7 @@ func TestLoadLocal(t *testing.T) {
tma := newTestMpoolAPI()
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -433,7 +433,7 @@ func TestLoadLocal(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -443,7 +443,7 @@ func TestLoadLocal(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -465,7 +465,7 @@ func TestLoadLocal(t *testing.T) {
t.Fatal(err)
}
mp, err = New(tma, ds, "mptest")
mp, err = New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -494,7 +494,7 @@ func TestClearAll(t *testing.T) {
tma := newTestMpoolAPI()
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -505,7 +505,7 @@ func TestClearAll(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -515,7 +515,7 @@ func TestClearAll(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -548,7 +548,7 @@ func TestClearNonLocal(t *testing.T) {
tma := newTestMpoolAPI()
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -559,7 +559,7 @@ func TestClearNonLocal(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -569,7 +569,7 @@ func TestClearNonLocal(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -609,7 +609,7 @@ func TestUpdates(t *testing.T) {
tma := newTestMpoolAPI()
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -620,7 +620,7 @@ func TestUpdates(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -630,7 +630,7 @@ func TestUpdates(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
+1 -2
View File
@@ -11,7 +11,6 @@ import (
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/messagepool/gasguess"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/journal"
"github.com/ipfs/go-cid"
)
@@ -148,7 +147,7 @@ loop:
}
if len(msgs) > 0 {
journal.J.RecordEvent(mp.evtTypes[evtTypeMpoolRepub], func() interface{} {
mp.journal.RecordEvent(mp.evtTypes[evtTypeMpoolRepub], func() interface{} {
msgsEv := make([]MessagePoolEvtMessage, 0, len(msgs))
for _, m := range msgs {
msgsEv = append(msgsEv, MessagePoolEvtMessage{Message: m.Message, CID: m.Cid()})
+4 -3
View File
@@ -1,6 +1,7 @@
package messagepool
import (
"context"
"testing"
"time"
@@ -21,7 +22,7 @@ func TestRepubMessages(t *testing.T) {
tma := newTestMpoolAPI()
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "mptest")
mp, err := New(tma, ds, "mptest", nil)
if err != nil {
t.Fatal(err)
}
@@ -32,7 +33,7 @@ func TestRepubMessages(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -42,7 +43,7 @@ func TestRepubMessages(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
+33 -31
View File
@@ -13,6 +13,10 @@ import (
"sort"
"testing"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
logging "github.com/ipfs/go-log"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/build"
@@ -21,12 +25,10 @@ import (
"github.com/filecoin-project/lotus/chain/types/mock"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
"github.com/filecoin-project/lotus/api"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
logging "github.com/ipfs/go-log"
)
func init() {
@@ -34,7 +36,7 @@ func init() {
MaxActorPendingMessages = 1000000
}
func makeTestMessage(w *wallet.Wallet, from, to address.Address, nonce uint64, gasLimit int64, gasPrice uint64) *types.SignedMessage {
func makeTestMessage(w *wallet.LocalWallet, from, to address.Address, nonce uint64, gasLimit int64, gasPrice uint64) *types.SignedMessage {
msg := &types.Message{
From: from,
To: to,
@@ -45,7 +47,7 @@ func makeTestMessage(w *wallet.Wallet, from, to address.Address, nonce uint64, g
GasFeeCap: types.NewInt(100 + gasPrice),
GasPremium: types.NewInt(gasPrice),
}
sig, err := w.Sign(context.TODO(), from, msg.Cid().Bytes())
sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{})
if err != nil {
panic(err)
}
@@ -58,7 +60,7 @@ func makeTestMessage(w *wallet.Wallet, from, to address.Address, nonce uint64, g
func makeTestMpool() (*MessagePool, *testMpoolAPI) {
tma := newTestMpoolAPI()
ds := datastore.NewMapDatastore()
mp, err := New(tma, ds, "test")
mp, err := New(tma, ds, "test", nil)
if err != nil {
panic(err)
}
@@ -75,7 +77,7 @@ func TestMessageChains(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -85,7 +87,7 @@ func TestMessageChains(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -313,7 +315,7 @@ func TestMessageChainSkipping(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -323,7 +325,7 @@ func TestMessageChainSkipping(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -389,7 +391,7 @@ func TestBasicMessageSelection(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -399,7 +401,7 @@ func TestBasicMessageSelection(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -533,7 +535,7 @@ func TestMessageSelectionTrimming(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -543,7 +545,7 @@ func TestMessageSelectionTrimming(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -596,7 +598,7 @@ func TestPriorityMessageSelection(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -606,7 +608,7 @@ func TestPriorityMessageSelection(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -675,7 +677,7 @@ func TestPriorityMessageSelection2(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -685,7 +687,7 @@ func TestPriorityMessageSelection2(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -744,7 +746,7 @@ func TestPriorityMessageSelection3(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -754,7 +756,7 @@ func TestPriorityMessageSelection3(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -841,7 +843,7 @@ func TestOptimalMessageSelection1(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -851,7 +853,7 @@ func TestOptimalMessageSelection1(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -908,7 +910,7 @@ func TestOptimalMessageSelection2(t *testing.T) {
t.Fatal(err)
}
a1, err := w1.GenerateKey(crypto.SigTypeSecp256k1)
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -918,7 +920,7 @@ func TestOptimalMessageSelection2(t *testing.T) {
t.Fatal(err)
}
a2, err := w2.GenerateKey(crypto.SigTypeSecp256k1)
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -984,7 +986,7 @@ func TestOptimalMessageSelection3(t *testing.T) {
nActors := 10
// the actors
var actors []address.Address
var wallets []*wallet.Wallet
var wallets []*wallet.LocalWallet
for i := 0; i < nActors; i++ {
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
@@ -992,7 +994,7 @@ func TestOptimalMessageSelection3(t *testing.T) {
t.Fatal(err)
}
a, err := w.GenerateKey(crypto.SigTypeSecp256k1)
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -1064,7 +1066,7 @@ func testCompetitiveMessageSelection(t *testing.T, rng *rand.Rand, getPremium fu
nActors := 300
// the actors
var actors []address.Address
var wallets []*wallet.Wallet
var wallets []*wallet.LocalWallet
for i := 0; i < nActors; i++ {
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
@@ -1072,7 +1074,7 @@ func testCompetitiveMessageSelection(t *testing.T, rng *rand.Rand, getPremium fu
t.Fatal(err)
}
a, err := w.GenerateKey(crypto.SigTypeSecp256k1)
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -1330,7 +1332,7 @@ readLoop:
}
actorMap := make(map[address.Address]address.Address)
actorWallets := make(map[address.Address]*wallet.Wallet)
actorWallets := make(map[address.Address]api.WalletAPI)
for _, m := range msgs {
baseNonce := baseNonces[m.Message.From]
@@ -1342,7 +1344,7 @@ readLoop:
t.Fatal(err)
}
a, err := w.GenerateKey(crypto.SigTypeSecp256k1)
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
if err != nil {
t.Fatal(err)
}
@@ -1360,7 +1362,7 @@ readLoop:
m.Message.From = localActor
m.Message.Nonce -= baseNonce
sig, err := w.Sign(context.TODO(), localActor, m.Message.Cid().Bytes())
sig, err := w.WalletSign(context.TODO(), localActor, m.Message.Cid().Bytes(), api.MsgMeta{})
if err != nil {
t.Fatal(err)
}
+20 -14
View File
@@ -5,40 +5,37 @@ import (
"context"
"sync"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/namespace"
logging "github.com/ipfs/go-log/v2"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes"
)
const dsKeyActorNonce = "ActorNextNonce"
var log = logging.Logger("messagesigner")
type mpoolAPI interface {
type MpoolNonceAPI interface {
GetNonce(address.Address) (uint64, error)
}
// MessageSigner keeps track of nonces per address, and increments the nonce
// when signing a message
type MessageSigner struct {
wallet *wallet.Wallet
wallet api.WalletAPI
lk sync.Mutex
mpool mpoolAPI
mpool MpoolNonceAPI
ds datastore.Batching
}
func NewMessageSigner(wallet *wallet.Wallet, mpool *messagepool.MessagePool, ds dtypes.MetadataDS) *MessageSigner {
return newMessageSigner(wallet, mpool, ds)
}
func newMessageSigner(wallet *wallet.Wallet, mpool mpoolAPI, ds dtypes.MetadataDS) *MessageSigner {
func NewMessageSigner(wallet api.WalletAPI, mpool MpoolNonceAPI, ds dtypes.MetadataDS) *MessageSigner {
ds = namespace.Wrap(ds, datastore.NewKey("/message-signer/"))
return &MessageSigner{
wallet: wallet,
@@ -61,7 +58,16 @@ func (ms *MessageSigner) SignMessage(ctx context.Context, msg *types.Message, cb
// Sign the message with the nonce
msg.Nonce = nonce
sig, err := ms.wallet.Sign(ctx, msg.From, msg.Cid().Bytes())
mb, err := msg.ToStorageBlock()
if err != nil {
return nil, xerrors.Errorf("serializing message: %w", err)
}
sig, err := ms.wallet.WalletSign(ctx, msg.From, mb.Cid().Bytes(), api.MsgMeta{
Type: api.MTChainMsg,
Extra: mb.RawData(),
})
if err != nil {
return nil, xerrors.Errorf("failed to sign message: %w", err)
}
+5 -5
View File
@@ -47,13 +47,13 @@ func TestMessageSignerSignMessage(t *testing.T) {
ctx := context.Background()
w, _ := wallet.NewWallet(wallet.NewMemKeyStore())
from1, err := w.GenerateKey(crypto.SigTypeSecp256k1)
from1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
require.NoError(t, err)
from2, err := w.GenerateKey(crypto.SigTypeSecp256k1)
from2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
require.NoError(t, err)
to1, err := w.GenerateKey(crypto.SigTypeSecp256k1)
to1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
require.NoError(t, err)
to2, err := w.GenerateKey(crypto.SigTypeSecp256k1)
to2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
require.NoError(t, err)
type msgSpec struct {
@@ -177,7 +177,7 @@ func TestMessageSignerSignMessage(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
mpool := newMockMpool()
ds := ds_sync.MutexWrap(datastore.NewMapDatastore())
ms := newMessageSigner(w, mpool, ds)
ms := NewMessageSigner(w, mpool, ds)
for _, m := range tt.msgs {
if len(m.mpoolNonce) == 1 {
+4 -15
View File
@@ -24,7 +24,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/migration/nv3"
m2 "github.com/filecoin-project/specs-actors/v2/actors/migration"
states2 "github.com/filecoin-project/specs-actors/v2/actors/states"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/adt"
@@ -80,9 +79,12 @@ func DefaultUpgradeSchedule() UpgradeSchedule {
Network: network.Version4,
Expensive: true,
Migration: UpgradeActorsV2,
}, {
Height: build.UpgradeTapeHeight,
Network: network.Version5,
}, {
Height: build.UpgradeLiftoffHeight,
Network: network.Version4,
Network: network.Version5,
Migration: UpgradeLiftoff,
}}
@@ -580,19 +582,6 @@ func UpgradeActorsV2(ctx context.Context, sm *StateManager, cb ExecCallback, roo
return cid.Undef, xerrors.Errorf("upgrading to actors v2: %w", err)
}
newStateTree, err := states2.LoadTree(store, newHamtRoot)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to load new state tree: %w", err)
}
// Check all state-tree invariants.
if msgs, err := states2.CheckStateInvariants(newStateTree, types.TotalFilecoinInt); err != nil {
return cid.Undef, xerrors.Errorf("failed to check new state tree: %w", err)
} else if !msgs.IsEmpty() {
// This error is going to be really nasty.
return cid.Undef, xerrors.Errorf("network upgrade failed: %v", msgs.Messages())
}
newRoot, err := store.Put(ctx, &types.StateRoot{
Version: types.StateTreeVersion1,
Actors: newHamtRoot,
+10 -9
View File
@@ -6,15 +6,21 @@ import (
"io"
"testing"
"github.com/ipfs/go-cid"
ipldcbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log"
"github.com/stretchr/testify/require"
cbg "github.com/whyrusleeping/cbor-gen"
"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/cbor"
"github.com/filecoin-project/specs-actors/actors/builtin"
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
lotusinit "github.com/filecoin-project/lotus/chain/actors/builtin/init"
@@ -25,11 +31,6 @@ import (
"github.com/filecoin-project/lotus/chain/vm"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
"github.com/ipfs/go-cid"
ipldcbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log"
cbg "github.com/whyrusleeping/cbor-gen"
)
func init() {
@@ -186,7 +187,7 @@ func TestForkHeightTriggers(t *testing.T) {
Params: enc,
GasLimit: types.TestGasLimit,
}
sig, err := cg.Wallet().Sign(ctx, cg.Banker(), m.Cid().Bytes())
sig, err := cg.Wallet().WalletSign(ctx, cg.Banker(), m.Cid().Bytes(), api.MsgMeta{})
if err != nil {
t.Fatal(err)
}
@@ -214,7 +215,7 @@ func TestForkHeightTriggers(t *testing.T) {
}
nonce++
sig, err := cg.Wallet().Sign(ctx, cg.Banker(), m.Cid().Bytes())
sig, err := cg.Wallet().WalletSign(ctx, cg.Banker(), m.Cid().Bytes(), api.MsgMeta{})
if err != nil {
return nil, err
}
+28 -8
View File
@@ -38,8 +38,16 @@ import (
"github.com/filecoin-project/lotus/chain/vm"
)
const LookbackNoLimit = abi.ChainEpoch(-1)
var log = logging.Logger("statemgr")
type StateManagerAPI interface {
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)
}
type versionSpec struct {
networkVersion network.Version
atOrBelow abi.ChainEpoch
@@ -508,7 +516,7 @@ func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.T
return nil, fmt.Errorf("failed to load message: %w", err)
}
_, r, _, err := sm.searchBackForMsg(ctx, ts, m)
_, r, _, err := sm.searchBackForMsg(ctx, ts, m, LookbackNoLimit)
if err != nil {
return nil, fmt.Errorf("failed to look back through chain for message: %w", err)
}
@@ -517,9 +525,9 @@ func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.T
}
// WaitForMessage blocks until a message appears on chain. It looks backwards in the chain to see if this has already
// happened. It guarantees that the message has been on chain for at least confidence epochs without being reverted
// before returning.
func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confidence uint64) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
// happened, with an optional limit to how many epochs it will search. It guarantees that the message has been on
// chain for at least confidence epochs without being reverted before returning.
func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confidence uint64, lookbackLimit abi.ChainEpoch) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
@@ -557,7 +565,7 @@ func (sm *StateManager) WaitForMessage(ctx context.Context, mcid cid.Cid, confid
var backFm cid.Cid
backSearchWait := make(chan struct{})
go func() {
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head[0].Val, msg)
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head[0].Val, msg, lookbackLimit)
if err != nil {
log.Warnf("failed to look back through chain for message: %w", err)
return
@@ -649,7 +657,7 @@ func (sm *StateManager) SearchForMessage(ctx context.Context, mcid cid.Cid) (*ty
return head, r, foundMsg, nil
}
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head, msg)
fts, r, foundMsg, err := sm.searchBackForMsg(ctx, head, msg, LookbackNoLimit)
if err != nil {
log.Warnf("failed to look back through chain for message %s", mcid)
@@ -663,7 +671,15 @@ func (sm *StateManager) SearchForMessage(ctx context.Context, mcid cid.Cid) (*ty
return fts, r, foundMsg, nil
}
func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet, m types.ChainMsg) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
// searchBackForMsg searches up to limit tipsets backwards from the given
// tipset for a message receipt.
// If limit is
// - 0 then no tipsets are searched
// - 5 then five tipset are searched
// - LookbackNoLimit then there is no limit
func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet, m types.ChainMsg, limit abi.ChainEpoch) (*types.TipSet, *types.MessageReceipt, cid.Cid, error) {
limitHeight := from.Height() - limit
noLimit := limit == LookbackNoLimit
cur := from
curActor, err := sm.LoadActor(ctx, m.VMMessage().From, cur)
@@ -679,7 +695,9 @@ func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet
mNonce := m.VMMessage().Nonce
for {
if cur.Height() == 0 {
// If we've reached the genesis block, or we've reached the limit of
// how far back to look
if cur.Height() == 0 || !noLimit && cur.Height() <= limitHeight {
// it ain't here!
return nil, nil, cid.Undef, nil
}
@@ -1393,3 +1411,5 @@ func (sm *StateManager) GetMarketState(ctx context.Context, ts *types.TipSet) (m
}
return actState, nil
}
var _ StateManagerAPI = (*StateManager)(nil)
+1 -1
View File
@@ -31,7 +31,7 @@ func TestIndexSeeks(t *testing.T) {
ctx := context.TODO()
nbs := blockstore.NewTemporarySync()
cs := store.NewChainStore(nbs, syncds.MutexWrap(datastore.NewMapDatastore()), nil)
cs := store.NewChainStore(nbs, syncds.MutexWrap(datastore.NewMapDatastore()), nil, nil)
_, err = cs.Import(bytes.NewReader(gencar))
if err != nil {
+59 -4
View File
@@ -8,6 +8,7 @@ import (
"io"
"os"
"strconv"
"strings"
"sync"
"golang.org/x/sync/errgroup"
@@ -38,7 +39,9 @@ import (
lru "github.com/hashicorp/golang-lru"
block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
dstore "github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/query"
cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2"
car "github.com/ipld/go-car"
@@ -102,7 +105,7 @@ type HeadChangeEvt struct {
// 2. a block => messages references cache.
type ChainStore struct {
bs bstore.Blockstore
ds dstore.Datastore
ds dstore.Batching
heaviestLk sync.Mutex
heaviest *types.TipSet
@@ -124,11 +127,15 @@ type ChainStore struct {
vmcalls vm.SyscallBuilder
evtTypes [1]journal.EventType
journal journal.Journal
}
func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallBuilder) *ChainStore {
func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallBuilder, j journal.Journal) *ChainStore {
c, _ := lru.NewARC(DefaultMsgMetaCacheSize)
tsc, _ := lru.NewARC(DefaultTipSetCacheSize)
if j == nil {
j = journal.NilJournal()
}
cs := &ChainStore{
bs: bs,
ds: ds,
@@ -137,10 +144,11 @@ func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls vm.SyscallB
mmCache: c,
tsCache: tsc,
vmcalls: vmcalls,
journal: j,
}
cs.evtTypes = [1]journal.EventType{
evtTypeHeadChange: journal.J.RegisterEventType("sync", "head_change"),
evtTypeHeadChange: j.RegisterEventType("sync", "head_change"),
}
ci := NewChainIndex(cs.LoadTipSet)
@@ -379,7 +387,7 @@ func (cs *ChainStore) reorgWorker(ctx context.Context, initialNotifees []ReorgNo
continue
}
journal.J.RecordEvent(cs.evtTypes[evtTypeHeadChange], func() interface{} {
cs.journal.RecordEvent(cs.evtTypes[evtTypeHeadChange], func() interface{} {
return HeadChangeEvt{
From: r.old.Key(),
FromHeight: r.old.Height(),
@@ -441,6 +449,53 @@ func (cs *ChainStore) takeHeaviestTipSet(ctx context.Context, ts *types.TipSet)
return nil
}
// FlushValidationCache removes all results of block validation from the
// chain metadata store. Usually the first step after a new chain import.
func (cs *ChainStore) FlushValidationCache() error {
log.Infof("clearing block validation cache...")
dsWalk, err := cs.ds.Query(query.Query{
// Potential TODO: the validation cache is not a namespace on its own
// but is rather constructed as prefixed-key `foo:bar` via .Instance(), which
// in turn does not work with the filter, which can match only on `foo/bar`
//
// If this is addressed (blockcache goes into its own sub-namespace) then
// strings.HasPrefix(...) below can be skipped
//
//Prefix: blockValidationCacheKeyPrefix.String()
KeysOnly: true,
})
if err != nil {
return xerrors.Errorf("failed to initialize key listing query: %w", err)
}
allKeys, err := dsWalk.Rest()
if err != nil {
return xerrors.Errorf("failed to run key listing query: %w", err)
}
batch, err := cs.ds.Batch()
if err != nil {
return xerrors.Errorf("failed to open a DS batch: %w", err)
}
delCnt := 0
for _, k := range allKeys {
if strings.HasPrefix(k.Key, blockValidationCacheKeyPrefix.String()) {
delCnt++
batch.Delete(datastore.RawKey(k.Key)) // nolint:errcheck
}
}
if err := batch.Commit(); err != nil {
return xerrors.Errorf("failed to commit the DS batch: %w", err)
}
log.Infof("%d block validation entries cleared.", delCnt)
return nil
}
// SetHead sets the chainstores current 'best' head node.
// This should only be called if something is broken and needs fixing
func (cs *ChainStore) SetHead(ts *types.TipSet) error {
+2 -2
View File
@@ -62,7 +62,7 @@ func BenchmarkGetRandomness(b *testing.B) {
bs := blockstore.NewBlockstore(bds)
cs := store.NewChainStore(bs, mds, nil)
cs := store.NewChainStore(bs, mds, nil, nil)
b.ResetTimer()
@@ -96,7 +96,7 @@ func TestChainExportImport(t *testing.T) {
}
nbs := blockstore.NewTemporary()
cs := store.NewChainStore(nbs, datastore.NewMapDatastore(), nil)
cs := store.NewChainStore(nbs, datastore.NewMapDatastore(), nil, nil)
root, err := cs.Import(buf)
if err != nil {
+22 -27
View File
@@ -120,12 +120,6 @@ func FetchMessagesByCids(
return err
}
// FIXME: We already sort in `fetchCids`, we are duplicating too much work,
// we don't need to pass the index.
if out[i] != nil {
return fmt.Errorf("received duplicate message")
}
out[i] = msg
return nil
})
@@ -149,10 +143,6 @@ func FetchSignedMessagesByCids(
return err
}
if out[i] != nil {
return fmt.Errorf("received duplicate message")
}
out[i] = smsg
return nil
})
@@ -184,24 +174,29 @@ func fetchCids(
return fmt.Errorf("duplicate CIDs in fetchCids input")
}
fetchedBlocks := bserv.GetBlocks(ctx, cids)
for i := 0; i < len(cids); i++ {
select {
case block, ok := <-fetchedBlocks:
if !ok {
return fmt.Errorf("failed to fetch all messages")
}
ix, ok := cidIndex[block.Cid()]
if !ok {
return fmt.Errorf("received message we didnt ask for")
}
if err := cb(ix, block); err != nil {
return err
}
for block := range bserv.GetBlocks(ctx, cids) {
ix, ok := cidIndex[block.Cid()]
if !ok {
// Ignore duplicate/unexpected blocks. This shouldn't
// happen, but we can be safe.
log.Errorw("received duplicate/unexpected block when syncing", "cid", block.Cid())
continue
}
// Record that we've received the block.
delete(cidIndex, block.Cid())
if err := cb(ix, block); err != nil {
return err
}
}
if len(cidIndex) > 0 {
err := ctx.Err()
if err == nil {
err = fmt.Errorf("failed to fetch %d messages for unknown reasons", len(cidIndex))
}
return err
}
return nil
+6 -2
View File
@@ -1526,7 +1526,7 @@ func (syncer *Syncer) iterFullTipsets(ctx context.Context, headers []*types.TipS
ss.SetStage(api.StageMessages)
if batchErr != nil {
return xerrors.Errorf("failed to fetch messages: %w", err)
return xerrors.Errorf("failed to fetch messages: %w", batchErr)
}
for bsi := 0; bsi < len(bstout); bsi++ {
@@ -1726,7 +1726,7 @@ func VerifyElectionPoStVRF(ctx context.Context, worker address.Address, rand []b
return gen.VerifyVRF(ctx, worker, rand, evrf)
}
func (syncer *Syncer) State() []SyncerState {
func (syncer *Syncer) State() []SyncerStateSnapshot {
return syncer.syncmgr.State()
}
@@ -1740,6 +1740,10 @@ func (syncer *Syncer) UnmarkBad(blk cid.Cid) {
syncer.bad.Remove(blk)
}
func (syncer *Syncer) UnmarkAllBad() {
syncer.bad.Purge()
}
func (syncer *Syncer) CheckBadBlockCache(blk cid.Cid) (string, bool) {
bbr, ok := syncer.bad.Has(blk)
return bbr.String(), ok
+9 -6
View File
@@ -38,7 +38,7 @@ type SyncManager interface {
SetPeerHead(ctx context.Context, p peer.ID, ts *types.TipSet)
// State retrieves the state of the sync workers.
State() []SyncerState
State() []SyncerStateSnapshot
}
type syncManager struct {
@@ -79,7 +79,7 @@ type syncResult struct {
const syncWorkerCount = 3
func NewSyncManager(sync SyncFunc) SyncManager {
return &syncManager{
sm := &syncManager{
bspThresh: 1,
peerHeads: make(map[peer.ID]*types.TipSet),
syncTargets: make(chan *types.TipSet),
@@ -90,6 +90,10 @@ func NewSyncManager(sync SyncFunc) SyncManager {
doSync: sync,
stop: make(chan struct{}),
}
for i := range sm.syncStates {
sm.syncStates[i] = new(SyncerState)
}
return sm
}
func (sm *syncManager) Start() {
@@ -128,8 +132,8 @@ func (sm *syncManager) SetPeerHead(ctx context.Context, p peer.ID, ts *types.Tip
sm.incomingTipSets <- ts
}
func (sm *syncManager) State() []SyncerState {
ret := make([]SyncerState, 0, len(sm.syncStates))
func (sm *syncManager) State() []SyncerStateSnapshot {
ret := make([]SyncerStateSnapshot, 0, len(sm.syncStates))
for _, s := range sm.syncStates {
ret = append(ret, s.Snapshot())
}
@@ -405,8 +409,7 @@ func (sm *syncManager) scheduleWorkSent() {
}
func (sm *syncManager) syncWorker(id int) {
ss := &SyncerState{}
sm.syncStates[id] = ss
ss := sm.syncStates[id]
for {
select {
case ts, ok := <-sm.syncTargets:
+6 -6
View File
@@ -221,8 +221,7 @@ func (tu *syncTestUtil) addSourceNode(gen int) {
sourceRepo, genesis, blocks := tu.repoWithChain(tu.t, gen)
var out api.FullNode
// TODO: Don't ignore stop
_, err := node.New(tu.ctx,
stop, err := node.New(tu.ctx,
node.FullAPI(&out),
node.Online(),
node.Repo(sourceRepo),
@@ -232,6 +231,7 @@ func (tu *syncTestUtil) addSourceNode(gen int) {
node.Override(new(modules.Genesis), modules.LoadGenesis(genesis)),
)
require.NoError(tu.t, err)
tu.t.Cleanup(func() { _ = stop(context.Background()) })
lastTs := blocks[len(blocks)-1].Blocks
for _, lastB := range lastTs {
@@ -253,8 +253,7 @@ func (tu *syncTestUtil) addClientNode() int {
var out api.FullNode
// TODO: Don't ignore stop
_, err := node.New(tu.ctx,
stop, err := node.New(tu.ctx,
node.FullAPI(&out),
node.Online(),
node.Repo(repo.NewMemory(nil)),
@@ -264,6 +263,7 @@ func (tu *syncTestUtil) addClientNode() int {
node.Override(new(modules.Genesis), modules.LoadGenesis(tu.genesis)),
)
require.NoError(tu.t, err)
tu.t.Cleanup(func() { _ = stop(context.Background()) })
tu.nds = append(tu.nds, out)
return len(tu.nds) - 1
@@ -593,7 +593,7 @@ func TestDuplicateNonce(t *testing.T) {
GasPremium: types.NewInt(0),
}
sig, err := tu.g.Wallet().Sign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes())
sig, err := tu.g.Wallet().WalletSign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes(), api.MsgMeta{})
require.NoError(t, err)
return &types.SignedMessage{
@@ -685,7 +685,7 @@ func TestBadNonce(t *testing.T) {
GasPremium: types.NewInt(0),
}
sig, err := tu.g.Wallet().Sign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes())
sig, err := tu.g.Wallet().WalletSign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes(), api.MsgMeta{})
require.NoError(t, err)
return &types.SignedMessage{
+21 -25
View File
@@ -11,8 +11,7 @@ import (
"github.com/filecoin-project/lotus/chain/types"
)
type SyncerState struct {
lk sync.Mutex
type SyncerStateSnapshot struct {
Target *types.TipSet
Base *types.TipSet
Stage api.SyncStateStage
@@ -22,6 +21,11 @@ type SyncerState struct {
End time.Time
}
type SyncerState struct {
lk sync.Mutex
data SyncerStateSnapshot
}
func (ss *SyncerState) SetStage(v api.SyncStateStage) {
if ss == nil {
return
@@ -29,9 +33,9 @@ func (ss *SyncerState) SetStage(v api.SyncStateStage) {
ss.lk.Lock()
defer ss.lk.Unlock()
ss.Stage = v
ss.data.Stage = v
if v == api.StageSyncComplete {
ss.End = build.Clock.Now()
ss.data.End = build.Clock.Now()
}
}
@@ -42,13 +46,13 @@ func (ss *SyncerState) Init(base, target *types.TipSet) {
ss.lk.Lock()
defer ss.lk.Unlock()
ss.Target = target
ss.Base = base
ss.Stage = api.StageHeaders
ss.Height = 0
ss.Message = ""
ss.Start = build.Clock.Now()
ss.End = time.Time{}
ss.data.Target = target
ss.data.Base = base
ss.data.Stage = api.StageHeaders
ss.data.Height = 0
ss.data.Message = ""
ss.data.Start = build.Clock.Now()
ss.data.End = time.Time{}
}
func (ss *SyncerState) SetHeight(h abi.ChainEpoch) {
@@ -58,7 +62,7 @@ func (ss *SyncerState) SetHeight(h abi.ChainEpoch) {
ss.lk.Lock()
defer ss.lk.Unlock()
ss.Height = h
ss.data.Height = h
}
func (ss *SyncerState) Error(err error) {
@@ -68,21 +72,13 @@ func (ss *SyncerState) Error(err error) {
ss.lk.Lock()
defer ss.lk.Unlock()
ss.Message = err.Error()
ss.Stage = api.StageSyncErrored
ss.End = build.Clock.Now()
ss.data.Message = err.Error()
ss.data.Stage = api.StageSyncErrored
ss.data.End = build.Clock.Now()
}
func (ss *SyncerState) Snapshot() SyncerState {
func (ss *SyncerState) Snapshot() SyncerStateSnapshot {
ss.lk.Lock()
defer ss.lk.Unlock()
return SyncerState{
Base: ss.Base,
Target: ss.Target,
Stage: ss.Stage,
Height: ss.Height,
Message: ss.Message,
Start: ss.Start,
End: ss.End,
}
return ss.data
}
+6 -2
View File
@@ -9,6 +9,7 @@ import (
"github.com/filecoin-project/go-state-types/crypto"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
@@ -22,7 +23,7 @@ func Address(i uint64) address.Address {
return a
}
func MkMessage(from, to address.Address, nonce uint64, w *wallet.Wallet) *types.SignedMessage {
func MkMessage(from, to address.Address, nonce uint64, w *wallet.LocalWallet) *types.SignedMessage {
msg := &types.Message{
To: to,
From: from,
@@ -33,7 +34,7 @@ func MkMessage(from, to address.Address, nonce uint64, w *wallet.Wallet) *types.
GasPremium: types.NewInt(1),
}
sig, err := w.Sign(context.TODO(), from, msg.Cid().Bytes())
sig, err := w.WalletSign(context.TODO(), from, msg.Cid().Bytes(), api.MsgMeta{})
if err != nil {
panic(err)
}
@@ -59,9 +60,11 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
var pcids []cid.Cid
var height abi.ChainEpoch
weight := types.NewInt(weightInc)
var timestamp uint64
if parents != nil {
pcids = parents.Cids()
height = parents.Height() + 1
timestamp = parents.MinTimestamp() + build.BlockDelaySecs
weight = types.BigAdd(parents.Blocks()[0].ParentWeight, weight)
}
@@ -79,6 +82,7 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
ParentWeight: weight,
Messages: c,
Height: height,
Timestamp: timestamp,
ParentStateRoot: pstateRoot,
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")},
ParentBaseFee: types.NewInt(uint64(build.MinimumBaseFee)),
+5 -4
View File
@@ -1,6 +1,7 @@
package main
import (
"context"
"encoding/json"
"fmt"
"math/rand"
@@ -61,11 +62,11 @@ func MakeMessageSigningVectors() []vectors.MessageSigningVector {
panic(err)
}
blsk, err := w.GenerateKey(crypto.SigTypeBLS)
blsk, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
if err != nil {
panic(err)
}
bki, err := w.Export(blsk)
bki, err := w.WalletExport(context.Background(), blsk)
if err != nil {
panic(err)
}
@@ -85,11 +86,11 @@ func MakeMessageSigningVectors() []vectors.MessageSigningVector {
Signature: &bmsg.Signature,
}
secpk, err := w.GenerateKey(crypto.SigTypeBLS)
secpk, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
if err != nil {
panic(err)
}
ski, err := w.Export(secpk)
ski, err := w.WalletExport(context.Background(), secpk)
if err != nil {
panic(err)
}
+81
View File
@@ -0,0 +1,81 @@
package wallet
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
)
func GenerateKey(typ crypto.SigType) (*Key, error) {
pk, err := sigs.Generate(typ)
if err != nil {
return nil, err
}
ki := types.KeyInfo{
Type: kstoreSigType(typ),
PrivateKey: pk,
}
return NewKey(ki)
}
type Key struct {
types.KeyInfo
PublicKey []byte
Address address.Address
}
func NewKey(keyinfo types.KeyInfo) (*Key, error) {
k := &Key{
KeyInfo: keyinfo,
}
var err error
k.PublicKey, err = sigs.ToPublic(ActSigType(k.Type), k.PrivateKey)
if err != nil {
return nil, err
}
switch k.Type {
case KTSecp256k1:
k.Address, err = address.NewSecp256k1Address(k.PublicKey)
if err != nil {
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
}
case KTBLS:
k.Address, err = address.NewBLSAddress(k.PublicKey)
if err != nil {
return nil, xerrors.Errorf("converting BLS to address: %w", err)
}
default:
return nil, xerrors.Errorf("unknown key type")
}
return k, nil
}
func kstoreSigType(typ crypto.SigType) string {
switch typ {
case crypto.SigTypeBLS:
return KTBLS
case crypto.SigTypeSecp256k1:
return KTSecp256k1
default:
return ""
}
}
func ActSigType(typ string) crypto.SigType {
switch typ {
case KTBLS:
return crypto.SigTypeBLS
case KTSecp256k1:
return crypto.SigTypeSecp256k1
default:
return 0
}
}
+42
View File
@@ -0,0 +1,42 @@
package remotewallet
import (
"context"
"go.uber.org/fx"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/client"
cliutil "github.com/filecoin-project/lotus/cli/util"
"github.com/filecoin-project/lotus/node/modules/helpers"
)
type RemoteWallet struct {
api.WalletAPI
}
func SetupRemoteWallet(info string) func(mctx helpers.MetricsCtx, lc fx.Lifecycle) (*RemoteWallet, error) {
return func(mctx helpers.MetricsCtx, lc fx.Lifecycle) (*RemoteWallet, error) {
ai := cliutil.ParseApiInfo(info)
url, err := ai.DialArgs()
if err != nil {
return nil, err
}
wapi, closer, err := client.NewWalletRPC(mctx, url, ai.AuthHeader())
if err != nil {
return nil, xerrors.Errorf("creating jsonrpc client: %w", err)
}
lc.Append(fx.Hook{
OnStop: func(ctx context.Context) error {
closer()
return nil
},
})
return &RemoteWallet{wapi}, nil
}
}
+48 -87
View File
@@ -12,6 +12,7 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" // enable bls signatures
_ "github.com/filecoin-project/lotus/lib/sigs/secp" // enable secp signatures
@@ -29,15 +30,20 @@ const (
KTSecp256k1 = "secp256k1"
)
type Wallet struct {
type LocalWallet struct {
keys map[address.Address]*Key
keystore types.KeyStore
lk sync.Mutex
}
func NewWallet(keystore types.KeyStore) (*Wallet, error) {
w := &Wallet{
type Default interface {
GetDefault() (address.Address, error)
SetDefault(a address.Address) error
}
func NewWallet(keystore types.KeyStore) (*LocalWallet, error) {
w := &LocalWallet{
keys: make(map[address.Address]*Key),
keystore: keystore,
}
@@ -45,18 +51,18 @@ func NewWallet(keystore types.KeyStore) (*Wallet, error) {
return w, nil
}
func KeyWallet(keys ...*Key) *Wallet {
func KeyWallet(keys ...*Key) *LocalWallet {
m := make(map[address.Address]*Key)
for _, key := range keys {
m[key.Address] = key
}
return &Wallet{
return &LocalWallet{
keys: m,
}
}
func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*crypto.Signature, error) {
func (w *LocalWallet) WalletSign(ctx context.Context, addr address.Address, msg []byte, meta api.MsgMeta) (*crypto.Signature, error) {
ki, err := w.findKey(addr)
if err != nil {
return nil, err
@@ -68,7 +74,7 @@ func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*c
return sigs.Sign(ActSigType(ki.Type), ki.PrivateKey, msg)
}
func (w *Wallet) findKey(addr address.Address) (*Key, error) {
func (w *LocalWallet) findKey(addr address.Address) (*Key, error) {
w.lk.Lock()
defer w.lk.Unlock()
@@ -96,7 +102,7 @@ func (w *Wallet) findKey(addr address.Address) (*Key, error) {
return k, nil
}
func (w *Wallet) tryFind(addr address.Address) (types.KeyInfo, error) {
func (w *LocalWallet) tryFind(addr address.Address) (types.KeyInfo, error) {
ki, err := w.keystore.Get(KNamePrefix + addr.String())
if err == nil {
@@ -110,14 +116,12 @@ func (w *Wallet) tryFind(addr address.Address) (types.KeyInfo, error) {
// We got an ErrKeyInfoNotFound error
// Try again, this time with the testnet prefix
aChars := []rune(addr.String())
prefixRunes := []rune(address.TestnetPrefix)
if len(prefixRunes) != 1 {
return types.KeyInfo{}, xerrors.Errorf("unexpected prefix length: %d", len(prefixRunes))
tAddress, err := swapMainnetForTestnetPrefix(addr.String())
if err != nil {
return types.KeyInfo{}, err
}
aChars[0] = prefixRunes[0]
ki, err = w.keystore.Get(KNamePrefix + string(aChars))
ki, err = w.keystore.Get(KNamePrefix + tAddress)
if err != nil {
return types.KeyInfo{}, err
}
@@ -132,16 +136,19 @@ func (w *Wallet) tryFind(addr address.Address) (types.KeyInfo, error) {
return ki, nil
}
func (w *Wallet) Export(addr address.Address) (*types.KeyInfo, error) {
func (w *LocalWallet) WalletExport(ctx context.Context, addr address.Address) (*types.KeyInfo, error) {
k, err := w.findKey(addr)
if err != nil {
return nil, xerrors.Errorf("failed to find key to export: %w", err)
}
if k == nil {
return nil, xerrors.Errorf("key not found")
}
return &k.KeyInfo, nil
}
func (w *Wallet) Import(ki *types.KeyInfo) (address.Address, error) {
func (w *LocalWallet) WalletImport(ctx context.Context, ki *types.KeyInfo) (address.Address, error) {
w.lk.Lock()
defer w.lk.Unlock()
@@ -157,7 +164,7 @@ func (w *Wallet) Import(ki *types.KeyInfo) (address.Address, error) {
return k.Address, nil
}
func (w *Wallet) ListAddrs() ([]address.Address, error) {
func (w *LocalWallet) WalletList(ctx context.Context) ([]address.Address, error) {
all, err := w.keystore.List()
if err != nil {
return nil, xerrors.Errorf("listing keystore: %w", err)
@@ -190,7 +197,7 @@ func (w *Wallet) ListAddrs() ([]address.Address, error) {
return out, nil
}
func (w *Wallet) GetDefault() (address.Address, error) {
func (w *LocalWallet) GetDefault() (address.Address, error) {
w.lk.Lock()
defer w.lk.Unlock()
@@ -207,7 +214,7 @@ func (w *Wallet) GetDefault() (address.Address, error) {
return k.Address, nil
}
func (w *Wallet) SetDefault(a address.Address) error {
func (w *LocalWallet) SetDefault(a address.Address) error {
w.lk.Lock()
defer w.lk.Unlock()
@@ -229,19 +236,7 @@ func (w *Wallet) SetDefault(a address.Address) error {
return nil
}
func GenerateKey(typ crypto.SigType) (*Key, error) {
pk, err := sigs.Generate(typ)
if err != nil {
return nil, err
}
ki := types.KeyInfo{
Type: kstoreSigType(typ),
PrivateKey: pk,
}
return NewKey(ki)
}
func (w *Wallet) GenerateKey(typ crypto.SigType) (address.Address, error) {
func (w *LocalWallet) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
w.lk.Lock()
defer w.lk.Unlock()
@@ -269,7 +264,7 @@ func (w *Wallet) GenerateKey(typ crypto.SigType) (address.Address, error) {
return k.Address, nil
}
func (w *Wallet) HasKey(addr address.Address) (bool, error) {
func (w *LocalWallet) WalletHas(ctx context.Context, addr address.Address) (bool, error) {
k, err := w.findKey(addr)
if err != nil {
return false, err
@@ -277,11 +272,14 @@ func (w *Wallet) HasKey(addr address.Address) (bool, error) {
return k != nil, nil
}
func (w *Wallet) DeleteKey(addr address.Address) error {
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)
}
if k == nil {
return nil // already not there
}
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)
@@ -291,63 +289,26 @@ func (w *Wallet) DeleteKey(addr address.Address) error {
return xerrors.Errorf("failed to delete key %s: %w", addr, err)
}
tAddr, err := swapMainnetForTestnetPrefix(addr.String())
if err != nil {
return xerrors.Errorf("failed to swap prefixes: %w", err)
}
// TODO: Does this always error in the not-found case? Just ignoring an error return for now.
_ = w.keystore.Delete(KNamePrefix + tAddr)
return nil
}
type Key struct {
types.KeyInfo
var _ api.WalletAPI = &LocalWallet{}
PublicKey []byte
Address address.Address
}
func NewKey(keyinfo types.KeyInfo) (*Key, error) {
k := &Key{
KeyInfo: keyinfo,
}
var err error
k.PublicKey, err = sigs.ToPublic(ActSigType(k.Type), k.PrivateKey)
if err != nil {
return nil, err
}
switch k.Type {
case KTSecp256k1:
k.Address, err = address.NewSecp256k1Address(k.PublicKey)
if err != nil {
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
}
case KTBLS:
k.Address, err = address.NewBLSAddress(k.PublicKey)
if err != nil {
return nil, xerrors.Errorf("converting BLS to address: %w", err)
}
default:
return nil, xerrors.Errorf("unknown key type")
func swapMainnetForTestnetPrefix(addr string) (string, error) {
aChars := []rune(addr)
prefixRunes := []rune(address.TestnetPrefix)
if len(prefixRunes) != 1 {
return "", xerrors.Errorf("unexpected prefix length: %d", len(prefixRunes))
}
return k, nil
}
func kstoreSigType(typ crypto.SigType) string {
switch typ {
case crypto.SigTypeBLS:
return KTBLS
case crypto.SigTypeSecp256k1:
return KTSecp256k1
default:
return ""
}
}
func ActSigType(typ string) crypto.SigType {
switch typ {
case KTBLS:
return crypto.SigTypeBLS
case KTSecp256k1:
return crypto.SigTypeSecp256k1
default:
return 0
}
aChars[0] = prefixRunes[0]
return string(aChars), nil
}
+3 -2
View File
@@ -521,8 +521,9 @@ var chainInspectUsage = &cli.Command{
}
var chainListCmd = &cli.Command{
Name: "list",
Usage: "View a segment of the chain",
Name: "list",
Aliases: []string{"love"},
Usage: "View a segment of the chain",
Flags: []cli.Flag{
&cli.Uint64Flag{Name: "height"},
&cli.IntFlag{Name: "count", Value: 30},
+17 -69
View File
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"net/http"
"net/url"
"os"
"os/signal"
"strings"
@@ -12,8 +11,6 @@ import (
logging "github.com/ipfs/go-log/v2"
"github.com/mitchellh/go-homedir"
"github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
@@ -21,6 +18,7 @@ import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/client"
cliutil "github.com/filecoin-project/lotus/cli/util"
"github.com/filecoin-project/lotus/node/repo"
)
@@ -47,57 +45,6 @@ func NewCliError(s string) error {
// ApiConnector returns API instance
type ApiConnector func() api.FullNode
type APIInfo struct {
Addr string
Token []byte
}
func (a APIInfo) DialArgs() (string, error) {
ma, err := multiaddr.NewMultiaddr(a.Addr)
if err == nil {
_, addr, err := manet.DialArgs(ma)
if err != nil {
return "", err
}
return "ws://" + addr + "/rpc/v0", nil
}
_, err = url.Parse(a.Addr)
if err != nil {
return "", err
}
return a.Addr + "/rpc/v0", nil
}
func (a APIInfo) Host() (string, error) {
ma, err := multiaddr.NewMultiaddr(a.Addr)
if err == nil {
_, addr, err := manet.DialArgs(ma)
if err != nil {
return "", err
}
return addr, nil
}
spec, err := url.Parse(a.Addr)
if err != nil {
return "", err
}
return spec.Host, nil
}
func (a APIInfo) AuthHeader() http.Header {
if len(a.Token) != 0 {
headers := http.Header{}
headers.Add("Authorization", "Bearer "+string(a.Token))
return headers
}
log.Warn("API Token not set and requested, capabilities might be limited.")
return nil
}
// The flag passed on the command line with the listen address of the API
// server (only used by the tests)
func flagForAPI(t repo.RepoType) string {
@@ -153,7 +100,7 @@ func envForRepoDeprecation(t repo.RepoType) string {
}
}
func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) {
func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (cliutil.APIInfo, error) {
// Check if there was a flag passed with the listen address of the API
// server (only used by the tests)
apiFlag := flagForAPI(t)
@@ -161,7 +108,7 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) {
strma := ctx.String(apiFlag)
strma = strings.TrimSpace(strma)
return APIInfo{Addr: strma}, nil
return cliutil.APIInfo{Addr: strma}, nil
}
envKey := envForRepo(t)
@@ -175,32 +122,24 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) {
}
}
if ok {
sp := strings.SplitN(env, ":", 2)
if len(sp) != 2 {
log.Warnf("invalid env(%s) value, missing token or address", envKey)
} else {
return APIInfo{
Addr: sp[1],
Token: []byte(sp[0]),
}, nil
}
return cliutil.ParseApiInfo(env), nil
}
repoFlag := flagForRepo(t)
p, err := homedir.Expand(ctx.String(repoFlag))
if err != nil {
return APIInfo{}, xerrors.Errorf("could not expand home dir (%s): %w", repoFlag, err)
return cliutil.APIInfo{}, xerrors.Errorf("could not expand home dir (%s): %w", repoFlag, err)
}
r, err := repo.NewFS(p)
if err != nil {
return APIInfo{}, xerrors.Errorf("could not open repo at path: %s; %w", p, err)
return cliutil.APIInfo{}, xerrors.Errorf("could not open repo at path: %s; %w", p, err)
}
ma, err := r.APIEndpoint()
if err != nil {
return APIInfo{}, xerrors.Errorf("could not get api endpoint: %w", err)
return cliutil.APIInfo{}, xerrors.Errorf("could not get api endpoint: %w", err)
}
token, err := r.APIToken()
@@ -208,7 +147,7 @@ func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) {
log.Warnf("Couldn't load CLI token, capabilities may be limited: %v", err)
}
return APIInfo{
return cliutil.APIInfo{
Addr: ma.String(),
Token: token,
}, nil
@@ -289,6 +228,15 @@ func GetWorkerAPI(ctx *cli.Context) (api.WorkerAPI, jsonrpc.ClientCloser, error)
return client.NewWorkerRPC(ctx.Context, addr, headers)
}
func GetGatewayAPI(ctx *cli.Context) (api.GatewayAPI, jsonrpc.ClientCloser, error) {
addr, headers, err := GetRawAPI(ctx, repo.FullNode)
if err != nil {
return nil, nil, err
}
return client.NewGatewayRPC(ctx.Context, addr, headers)
}
func DaemonContext(cctx *cli.Context) context.Context {
if mtCtx, ok := cctx.App.Metadata[metadataTraceContext]; ok {
return mtCtx.(context.Context)
+1 -1
View File
@@ -35,7 +35,7 @@ func RunApp(app *cli.App) {
if os.Getenv("LOTUS_DEV") != "" {
log.Warnf("%+v", err)
} else {
fmt.Printf("ERROR: %s\n\n", err)
fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err) // nolint:errcheck
}
var phe *PrintHelpErr
if xerrors.As(err, &phe) {
+44 -5
View File
@@ -3,8 +3,10 @@ package cli
import (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"reflect"
"sort"
"strconv"
"text/tabwriter"
@@ -14,6 +16,8 @@ import (
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/stmgr"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/go-state-types/big"
@@ -174,6 +178,10 @@ var msigInspectCmd = &cli.Command{
Name: "vesting",
Usage: "Include vesting details",
},
&cli.BoolFlag{
Name: "decode-params",
Usage: "Decode parameters of transaction proposals",
},
},
Action: func(cctx *cli.Context) error {
if !cctx.Args().Present() {
@@ -204,6 +212,11 @@ var msigInspectCmd = &cli.Command{
return err
}
ownId, err := api.StateLookupID(ctx, maddr, types.EmptyTSK)
if err != nil {
return err
}
mstate, err := multisig.Load(store, act)
if err != nil {
return err
@@ -256,6 +269,7 @@ var msigInspectCmd = &cli.Command{
return xerrors.Errorf("reading pending transactions: %w", err)
}
decParams := cctx.Bool("decode-params")
fmt.Println("Transactions: ", len(pending))
if len(pending) > 0 {
var txids []int64
@@ -266,11 +280,36 @@ var msigInspectCmd = &cli.Command{
return txids[i] < txids[j]
})
w := tabwriter.NewWriter(os.Stdout, 8, 4, 0, ' ', 0)
w := tabwriter.NewWriter(os.Stdout, 8, 4, 2, ' ', 0)
fmt.Fprintf(w, "ID\tState\tApprovals\tTo\tValue\tMethod\tParams\n")
for _, txid := range txids {
tx := pending[txid]
fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%d\t%x\n", txid, "pending", len(tx.Approved), tx.To, types.FIL(tx.Value), tx.Method, tx.Params)
target := tx.To.String()
if tx.To == ownId {
target += " (self)"
}
targAct, err := api.StateGetActor(ctx, tx.To, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("failed to resolve 'To' address of multisig transaction %d: %w", txid, err)
}
method := stmgr.MethodsMap[targAct.Code][tx.Method]
paramStr := fmt.Sprintf("%x", tx.Params)
if decParams && tx.Method != 0 {
ptyp := reflect.New(method.Params.Elem()).Interface().(cbg.CBORUnmarshaler)
if err := ptyp.UnmarshalCBOR(bytes.NewReader(tx.Params)); err != nil {
return xerrors.Errorf("failed to decode parameters of transaction %d: %w", txid, err)
}
b, err := json.Marshal(ptyp)
if err != nil {
return xerrors.Errorf("could not json marshal parameter type: %w", err)
}
paramStr = string(b)
}
fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), method.Name, tx.Method, paramStr)
}
if err := w.Flush(); err != nil {
return xerrors.Errorf("flushing output: %+v", err)
@@ -398,7 +437,7 @@ var msigProposeCmd = &cli.Command{
var msigApproveCmd = &cli.Command{
Name: "approve",
Usage: "Approve a multisig message",
ArgsUsage: "[multisigAddress messageId proposerAddress destination value <methodId methodParams> (optional)]",
ArgsUsage: "<multisigAddress messageId> [proposerAddress destination value [methodId methodParams]]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
@@ -484,7 +523,7 @@ var msigApproveCmd = &cli.Command{
from = defaddr
}
msgCid, err := api.MsigApprove(ctx, msig, txid, proposer, dest, types.BigInt(value), from, method, params)
msgCid, err := api.MsigApproveTxnHash(ctx, msig, txid, proposer, dest, types.BigInt(value), from, method, params)
if err != nil {
return err
}
@@ -1129,7 +1168,7 @@ var msigLockApproveCmd = &cli.Command{
return actErr
}
msgCid, err := api.MsigApprove(ctx, msig, txid, prop, msig, big.Zero(), from, uint64(builtin2.MethodsMultisig.LockBalance), params)
msgCid, err := api.MsigApproveTxnHash(ctx, msig, txid, prop, msig, big.Zero(), from, uint64(builtin2.MethodsMultisig.LockBalance), params)
if err != nil {
return err
}
+3 -3
View File
@@ -121,13 +121,13 @@ func TestPaymentChannelStatus(t *testing.T) {
create := make(chan string)
go func() {
// creator: paych add-funds <creator> <receiver> <amount>
cmd = []string{creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)}
cmd := []string{creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)}
create <- creatorCLI.runCmd(paychAddFundsCmd, cmd)
}()
// Wait for the output to stop being "Channel does not exist"
for regexp.MustCompile(noChannelState).MatchString(out) {
cmd = []string{creatorAddr.String(), receiverAddr.String()}
cmd := []string{creatorAddr.String(), receiverAddr.String()}
out = creatorCLI.runCmd(paychStatusByFromToCmd, cmd)
}
fmt.Println(out)
@@ -390,7 +390,7 @@ func checkVoucherOutput(t *testing.T, list string, vouchers []voucherSpec) {
}
func startTwoNodesOneMiner(ctx context.Context, t *testing.T, blocktime time.Duration) ([]test.TestNode, []address.Address) {
n, sn := builder.RPCMockSbBuilder(t, 2, test.OneMiner)
n, sn := builder.RPCMockSbBuilder(t, test.TwoFull, test.OneMiner)
paymentCreator := n[0]
paymentReceiver := n[1]
+12 -2
View File
@@ -122,8 +122,14 @@ var syncMarkBadCmd = &cli.Command{
}
var syncUnmarkBadCmd = &cli.Command{
Name: "unmark-bad",
Usage: "Unmark the given block as bad, makes it possible to sync to a chain containing it",
Name: "unmark-bad",
Usage: "Unmark the given block as bad, makes it possible to sync to a chain containing it",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "all",
Usage: "drop the entire bad block cache",
},
},
ArgsUsage: "[blockCid]",
Action: func(cctx *cli.Context) error {
napi, closer, err := GetFullNodeAPI(cctx)
@@ -133,6 +139,10 @@ var syncUnmarkBadCmd = &cli.Command{
defer closer()
ctx := ReqContext(cctx)
if cctx.Bool("all") {
return napi.SyncUnmarkAllBad(ctx)
}
if !cctx.Args().Present() {
return fmt.Errorf("must specify block cid to unmark")
}
+83
View File
@@ -0,0 +1,83 @@
package cliutil
import (
"net/http"
"net/url"
"regexp"
"strings"
logging "github.com/ipfs/go-log/v2"
"github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
)
var log = logging.Logger("cliutil")
var (
infoWithToken = regexp.MustCompile("^[a-zA-Z0-9\\-_]+?\\.[a-zA-Z0-9\\-_]+?\\.([a-zA-Z0-9\\-_]+)?:.+$")
)
type APIInfo struct {
Addr string
Token []byte
}
func ParseApiInfo(s string) APIInfo {
var tok []byte
if infoWithToken.Match([]byte(s)) {
sp := strings.SplitN(s, ":", 2)
tok = []byte(sp[0])
s = sp[1]
}
return APIInfo{
Addr: s,
Token: tok,
}
}
func (a APIInfo) DialArgs() (string, error) {
ma, err := multiaddr.NewMultiaddr(a.Addr)
if err == nil {
_, addr, err := manet.DialArgs(ma)
if err != nil {
return "", err
}
return "ws://" + addr + "/rpc/v0", nil
}
_, err = url.Parse(a.Addr)
if err != nil {
return "", err
}
return a.Addr + "/rpc/v0", nil
}
func (a APIInfo) Host() (string, error) {
ma, err := multiaddr.NewMultiaddr(a.Addr)
if err == nil {
_, addr, err := manet.DialArgs(ma)
if err != nil {
return "", err
}
return addr, nil
}
spec, err := url.Parse(a.Addr)
if err != nil {
return "", err
}
return spec.Host, nil
}
func (a APIInfo) AuthHeader() http.Header {
if len(a.Token) != 0 {
headers := http.Header{}
headers.Add("Authorization", "Bearer "+string(a.Token))
return headers
}
log.Warn("API Token not set and requested, capabilities might be limited.")
return nil
}
+1 -1
View File
@@ -183,7 +183,7 @@ var importBenchCmd = &cli.Command{
return nil
}
cs := store.NewChainStore(bs, ds, vm.Syscalls(verifier))
cs := store.NewChainStore(bs, ds, vm.Syscalls(verifier), nil)
stm := stmgr.NewStateManager(cs)
if cctx.Bool("global-profile") {
+131 -42
View File
@@ -6,85 +6,174 @@ import (
"time"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/impl/full"
"github.com/ipfs/go-cid"
"go.opencensus.io/trace"
)
const LookbackCap = time.Hour
const (
LookbackCap = time.Hour
stateWaitLookbackLimit = abi.ChainEpoch(20)
)
var (
ErrLookbackTooLong = fmt.Errorf("lookbacks of more than %s are disallowed", LookbackCap)
)
type GatewayAPI struct {
api api.FullNode
// gatewayDepsAPI defines the API methods that the GatewayAPI depends on
// (to make it easy to mock for tests)
type gatewayDepsAPI interface {
ChainHead(ctx context.Context) (*types.TipSet, error)
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, 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)
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error)
}
func (a *GatewayAPI) getTipsetTimestamp(ctx context.Context, tsk types.TipSetKey) (time.Time, error) {
type GatewayAPI struct {
api gatewayDepsAPI
}
func (a *GatewayAPI) checkTipsetKey(ctx context.Context, tsk types.TipSetKey) error {
if tsk.IsEmpty() {
return time.Now(), nil
return nil
}
ts, err := a.api.ChainGetTipSet(ctx, tsk)
if err != nil {
return time.Time{}, err
}
return time.Unix(int64(ts.Blocks()[0].Timestamp), 0), nil
}
func (a *GatewayAPI) checkTipset(ctx context.Context, ts types.TipSetKey) error {
when, err := a.getTipsetTimestamp(ctx, ts)
if err != nil {
return err
}
if time.Since(when) > time.Hour {
return a.checkTipset(ts)
}
func (a *GatewayAPI) checkTipset(ts *types.TipSet) error {
at := time.Unix(int64(ts.Blocks()[0].Timestamp), 0)
if err := a.checkTimestamp(at); err != nil {
return fmt.Errorf("bad tipset: %w", err)
}
return nil
}
func (a *GatewayAPI) checkTipsetHeight(ts *types.TipSet, h abi.ChainEpoch) error {
tsBlock := ts.Blocks()[0]
heightDelta := time.Duration(uint64(tsBlock.Height-h)*build.BlockDelaySecs) * time.Second
timeAtHeight := time.Unix(int64(tsBlock.Timestamp), 0).Add(-heightDelta)
if err := a.checkTimestamp(timeAtHeight); err != nil {
return fmt.Errorf("bad tipset height: %w", err)
}
return nil
}
func (a *GatewayAPI) checkTimestamp(at time.Time) error {
if time.Since(at) > LookbackCap {
return ErrLookbackTooLong
}
return nil
}
func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
ctx, span := trace.StartSpan(ctx, "StateGetActor")
defer span.End()
if err := a.checkTipset(ctx, ts); err != nil {
return nil, fmt.Errorf("bad tipset: %w", err)
}
return a.api.StateGetActor(ctx, actor, ts)
}
func (a *GatewayAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
ctx, span := trace.StartSpan(ctx, "ChainHead")
defer span.End()
// TODO: cache and invalidate cache when timestamp is up (or have internal ChainNotify)
return a.api.ChainHead(ctx)
}
func (a *GatewayAPI) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
ctx, span := trace.StartSpan(ctx, "ChainGetTipSet")
defer span.End()
if err := a.checkTipset(ctx, tsk); err != nil {
return nil, fmt.Errorf("bad tipset: %w", err)
}
// TODO: since we're limiting lookbacks, should just cache this (could really even cache the json response bytes)
return a.api.ChainGetTipSet(ctx, tsk)
}
func (a *GatewayAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
ts, err := a.api.ChainGetTipSet(ctx, tsk)
if err != nil {
return nil, err
}
// Check if the tipset key refers to a tipset that's too far in the past
if err := a.checkTipset(ts); err != nil {
return nil, err
}
// Check if the height is too far in the past
if err := a.checkTipsetHeight(ts, h); err != nil {
return nil, err
}
return a.api.ChainGetTipSetByHeight(ctx, h, tsk)
}
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
}
return a.api.GasEstimateMessageGas(ctx, msg, spec, tsk)
}
func (a *GatewayAPI) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
ctx, span := trace.StartSpan(ctx, "MpoolPush")
defer span.End()
// TODO: additional anti-spam checks
return a.api.MpoolPushUntrusted(ctx, sm)
}
func (a *GatewayAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return types.NewInt(0), err
}
return a.api.MsigGetAvailableBalance(ctx, addr, tsk)
}
func (a *GatewayAPI) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
if err := a.checkTipsetKey(ctx, start); err != nil {
return types.NewInt(0), err
}
if err := a.checkTipsetKey(ctx, end); err != nil {
return types.NewInt(0), err
}
return a.api.MsigGetVested(ctx, addr, start, end)
}
func (a *GatewayAPI) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
if err := a.checkTipsetKey(ctx, tsk); err != nil {
return address.Undef, err
}
return a.api.StateAccountKey(ctx, addr, 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
}
return a.api.StateGetActor(ctx, actor, 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
}
return a.api.StateLookupID(ctx, addr, tsk)
}
func (a *GatewayAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
return a.api.StateWaitMsgLimited(ctx, msg, confidence, stateWaitLookbackLimit)
}
var _ api.GatewayAPI = (*GatewayAPI)(nil)
var _ full.ChainModuleAPI = (*GatewayAPI)(nil)
var _ full.GasModuleAPI = (*GatewayAPI)(nil)
var _ full.MpoolModuleAPI = (*GatewayAPI)(nil)
var _ full.StateModuleAPI = (*GatewayAPI)(nil)
+191
View File
@@ -0,0 +1,191 @@
package main
import (
"context"
"sync"
"testing"
"time"
"github.com/filecoin-project/lotus/build"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/lotus/chain/types/mock"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
)
func TestGatewayAPIChainGetTipSetByHeight(t *testing.T) {
ctx := context.Background()
lookbackTimestamp := uint64(time.Now().Unix()) - uint64(LookbackCap.Seconds())
type args struct {
h abi.ChainEpoch
tskh abi.ChainEpoch
genesisTS uint64
}
tests := []struct {
name string
args args
expErr bool
}{{
name: "basic",
args: args{
h: abi.ChainEpoch(1),
tskh: abi.ChainEpoch(5),
},
}, {
name: "genesis",
args: args{
h: abi.ChainEpoch(0),
tskh: abi.ChainEpoch(5),
},
}, {
name: "same epoch as tipset",
args: args{
h: abi.ChainEpoch(5),
tskh: abi.ChainEpoch(5),
},
}, {
name: "tipset too old",
args: args{
// Tipset height is 5, genesis is at LookbackCap - 10 epochs.
// So resulting tipset height will be 5 epochs earlier than LookbackCap.
h: abi.ChainEpoch(1),
tskh: abi.ChainEpoch(5),
genesisTS: lookbackTimestamp - build.BlockDelaySecs*10,
},
expErr: true,
}, {
name: "lookup height too old",
args: args{
// Tipset height is 5, lookup height is 1, genesis is at LookbackCap - 3 epochs.
// So
// - lookup height will be 2 epochs earlier than LookbackCap.
// - tipset height will be 2 epochs later than LookbackCap.
h: abi.ChainEpoch(1),
tskh: abi.ChainEpoch(5),
genesisTS: lookbackTimestamp - build.BlockDelaySecs*3,
},
expErr: true,
}, {
name: "tipset and lookup height within acceptable range",
args: args{
// Tipset height is 5, lookup height is 1, genesis is at LookbackCap.
// So
// - lookup height will be 1 epoch later than LookbackCap.
// - tipset height will be 5 epochs later than LookbackCap.
h: abi.ChainEpoch(1),
tskh: abi.ChainEpoch(5),
genesisTS: lookbackTimestamp,
},
}}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
mock := &mockGatewayDepsAPI{}
a := &GatewayAPI{api: mock}
// Create tipsets from genesis up to tskh and return the highest
ts := mock.createTipSets(tt.args.tskh, tt.args.genesisTS)
got, err := a.ChainGetTipSetByHeight(ctx, tt.args.h, ts.Key())
if tt.expErr {
require.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, tt.args.h, got.Height())
}
})
}
}
type mockGatewayDepsAPI struct {
lk sync.RWMutex
tipsets []*types.TipSet
}
func (m *mockGatewayDepsAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
m.lk.RLock()
defer m.lk.RUnlock()
return m.tipsets[len(m.tipsets)-1], nil
}
func (m *mockGatewayDepsAPI) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
m.lk.RLock()
defer m.lk.RUnlock()
for _, ts := range m.tipsets {
if ts.Key() == tsk {
return ts, nil
}
}
return nil, nil
}
// createTipSets creates tipsets from genesis up to tskh and returns the highest
func (m *mockGatewayDepsAPI) createTipSets(h abi.ChainEpoch, genesisTimestamp uint64) *types.TipSet {
m.lk.Lock()
defer m.lk.Unlock()
targeth := h + 1 // add one for genesis block
if genesisTimestamp == 0 {
genesisTimestamp = uint64(time.Now().Unix()) - build.BlockDelaySecs*uint64(targeth)
}
var currts *types.TipSet
for currh := abi.ChainEpoch(0); currh < targeth; currh++ {
blks := mock.MkBlock(currts, 1, 1)
if currh == 0 {
blks.Timestamp = genesisTimestamp
}
currts = mock.TipSet(blks)
m.tipsets = append(m.tipsets, currts)
}
return m.tipsets[len(m.tipsets)-1]
}
func (m *mockGatewayDepsAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
m.lk.Lock()
defer m.lk.Unlock()
return m.tipsets[h], nil
}
func (m *mockGatewayDepsAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) MpoolPushUntrusted(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
panic("implement me")
}
func (m *mockGatewayDepsAPI) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error) {
panic("implement me")
}
+211
View File
@@ -0,0 +1,211 @@
package main
import (
"bytes"
"context"
"fmt"
"os"
"testing"
"time"
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/client"
"github.com/filecoin-project/lotus/api/test"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/node"
builder "github.com/filecoin-project/lotus/node/test"
)
func init() {
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
}
// TestEndToEnd tests that API calls can be made on a lite node that is
// connected through a gateway to a full API node
func TestEndToEnd(t *testing.T) {
_ = os.Setenv("BELLMAN_NO_GPU", "1")
blocktime := 5 * time.Millisecond
ctx := context.Background()
full, lite, closer := startNodes(ctx, t, blocktime)
defer closer()
// The full node starts with a wallet
fullWalletAddr, err := full.WalletDefaultAddress(ctx)
require.NoError(t, err)
// Check the full node's wallet balance from the lite node
balance, err := lite.WalletBalance(ctx, fullWalletAddr)
require.NoError(t, err)
fmt.Println(balance)
// Create a wallet on the lite node
liteWalletAddr, err := lite.WalletNew(ctx, wallet.ActSigType("secp256k1"))
require.NoError(t, err)
// Send some funds from the full node to the lite node
err = sendFunds(ctx, t, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18))
require.NoError(t, err)
// Send some funds from the lite node back to the full node
err = sendFunds(ctx, t, lite, liteWalletAddr, fullWalletAddr, types.NewInt(100))
require.NoError(t, err)
// Sign some data with the lite node wallet address
data := []byte("hello")
sig, err := lite.WalletSign(ctx, liteWalletAddr, data)
require.NoError(t, err)
// Verify the signature
ok, err := lite.WalletVerify(ctx, liteWalletAddr, data, sig)
require.NoError(t, err)
require.True(t, ok)
// Create some wallets on the lite node to use for testing multisig
var walletAddrs []address.Address
for i := 0; i < 4; i++ {
addr, err := lite.WalletNew(ctx, wallet.ActSigType("secp256k1"))
require.NoError(t, err)
walletAddrs = append(walletAddrs, addr)
err = sendFunds(ctx, t, lite, liteWalletAddr, addr, types.NewInt(1e15))
require.NoError(t, err)
}
// Create an msig with three of the addresses and threshold of two sigs
msigAddrs := walletAddrs[:3]
amt := types.NewInt(1000)
addProposal, err := lite.MsigCreate(ctx, 2, msigAddrs, abi.ChainEpoch(50), amt, liteWalletAddr, types.NewInt(0))
require.NoError(t, err)
res, err := lite.StateWaitMsg(ctx, addProposal, 1)
require.NoError(t, err)
require.EqualValues(t, 0, res.Receipt.ExitCode)
var execReturn init0.ExecReturn
err = execReturn.UnmarshalCBOR(bytes.NewReader(res.Receipt.Return))
require.NoError(t, err)
// Get available balance of msig: should be greater than zero and less
// than initial amount
msig := execReturn.IDAddress
msigBalance, err := lite.MsigGetAvailableBalance(ctx, msig, types.EmptyTSK)
require.NoError(t, err)
require.Greater(t, msigBalance.Int64(), int64(0))
require.Less(t, msigBalance.Int64(), amt.Int64())
// Propose to add a new address to the msig
addProposal, err = lite.MsigAddPropose(ctx, msig, walletAddrs[0], walletAddrs[3], false)
require.NoError(t, err)
res, err = lite.StateWaitMsg(ctx, addProposal, 1)
require.NoError(t, err)
require.EqualValues(t, 0, res.Receipt.ExitCode)
var proposeReturn multisig.ProposeReturn
err = proposeReturn.UnmarshalCBOR(bytes.NewReader(res.Receipt.Return))
require.NoError(t, err)
// Approve proposal (proposer is first (implicit) signer, approver is
// second signer
txnID := uint64(proposeReturn.TxnID)
approval1, err := lite.MsigAddApprove(ctx, msig, walletAddrs[1], txnID, walletAddrs[0], walletAddrs[3], false)
require.NoError(t, err)
res, err = lite.StateWaitMsg(ctx, approval1, 1)
require.NoError(t, err)
require.EqualValues(t, 0, res.Receipt.ExitCode)
var approveReturn multisig.ApproveReturn
err = approveReturn.UnmarshalCBOR(bytes.NewReader(res.Receipt.Return))
require.NoError(t, err)
require.True(t, approveReturn.Applied)
}
func sendFunds(ctx context.Context, t *testing.T, 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
}
func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration) (test.TestNode, test.TestNode, jsonrpc.ClientCloser) {
var closer jsonrpc.ClientCloser
// Create one miner and two full nodes.
// - Put a gateway server in front of full node 1
// - Start full node 2 in lite mode
// - Connect lite node -> gateway server -> full node
opts := append(
// Full node
test.OneFull,
// Lite node
test.FullNodeOpts{
Lite: true,
Opts: func(nodes []test.TestNode) node.Option {
fullNode := nodes[0]
// Create a gateway server in front of the full node
_, addr, err := builder.CreateRPCServer(&GatewayAPI{api: fullNode})
require.NoError(t, err)
// Create a gateway client API that connects to the gateway server
var gapi api.GatewayAPI
gapi, closer, err = client.NewGatewayRPC(ctx, addr, nil)
require.NoError(t, err)
// Provide the gateway API to dependency injection
return node.Override(new(api.GatewayAPI), gapi)
},
},
)
n, sn := builder.RPCMockSbBuilder(t, opts, test.OneMiner)
full := n[0]
lite := n[1]
miner := sn[0]
// Get the listener address for the full node
fullAddr, err := full.NetAddrsListen(ctx)
require.NoError(t, err)
// Connect the miner and the full node
err = miner.NetConnect(ctx, fullAddr)
require.NoError(t, err)
// Start mining blocks
bm := test.NewBlockMiner(ctx, t, miner, blocktime)
bm.MineBlocks()
return full, lite, closer
}
+2 -2
View File
@@ -40,12 +40,12 @@ func main() {
return fmt.Errorf("unrecognized key type: %q", cctx.String("type"))
}
kaddr, err := w.GenerateKey(kt)
kaddr, err := w.WalletNew(cctx.Context, kt)
if err != nil {
return err
}
ki, err := w.Export(kaddr)
ki, err := w.WalletExport(cctx.Context, kaddr)
if err != nil {
return err
}
+2 -2
View File
@@ -173,7 +173,7 @@ var chainBalanceStateCmd = &cli.Command{
bs := blockstore.NewBlockstore(ds)
cs := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier))
cs := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier), nil)
cst := cbor.NewCborStore(bs)
store := adt.WrapStore(ctx, cst)
@@ -343,7 +343,7 @@ var chainPledgeCmd = &cli.Command{
bs := blockstore.NewBlockstore(ds)
cs := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier))
cs := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier), nil)
cst := cbor.NewCborStore(bs)
store := adt.WrapStore(ctx, cst)
+2 -1
View File
@@ -15,6 +15,7 @@ import (
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
cliutil "github.com/filecoin-project/lotus/cli/util"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/multiformats/go-multiaddr"
"github.com/urfave/cli/v2"
@@ -111,7 +112,7 @@ var consensusCheckCmd = &cli.Command{
if err != nil {
return err
}
ainfo := lcli.APIInfo{Addr: apima.String()}
ainfo := cliutil.APIInfo{Addr: apima.String()}
addr, err := ainfo.DialArgs()
if err != nil {
return err
+1 -1
View File
@@ -83,7 +83,7 @@ var exportChainCmd = &cli.Command{
bs := blockstore.NewBlockstore(ds)
cs := store.NewChainStore(bs, mds, nil)
cs := store.NewChainStore(bs, mds, nil, nil)
if err := cs.Load(); err != nil {
return err
}
+1 -1
View File
@@ -52,7 +52,7 @@ var genesisVerifyCmd = &cli.Command{
}
bs := blockstore.NewBlockstore(datastore.NewMapDatastore())
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), nil)
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), nil, nil)
cf := cctx.Args().Get(0)
f, err := os.Open(cf)
+2 -2
View File
@@ -105,7 +105,7 @@ var keyinfoVerifyCmd = &cli.Command{
return err
}
if _, err := w.Import(&keyInfo); err != nil {
if _, err := w.WalletImport(cctx.Context, &keyInfo); err != nil {
return err
}
@@ -220,7 +220,7 @@ var keyinfoImportCmd = &cli.Command{
return err
}
addr, err := w.Import(&keyInfo)
addr, err := w.WalletImport(cctx.Context, &keyInfo)
if err != nil {
return err
}
+1 -1
View File
@@ -162,7 +162,7 @@ var stateTreePruneCmd = &cli.Command{
bs := blockstore.NewBlockstore(ds)
cs := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier))
cs := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier), nil)
if err := cs.Load(); err != nil {
return fmt.Errorf("loading chainstore: %w", err)
}
+2 -4
View File
@@ -5,8 +5,6 @@ import (
"testing"
"time"
"github.com/filecoin-project/lotus/node"
logging "github.com/ipfs/go-log/v2"
"github.com/stretchr/testify/require"
"github.com/urfave/cli/v2"
@@ -64,8 +62,8 @@ func TestMinerAllInfo(t *testing.T) {
require.NoError(t, infoAllCmd.Action(cctx))
}
bp := func(t *testing.T, nFull int, storage []test.StorageMiner, opts ...node.Option) ([]test.TestNode, []test.TestStorageNode) {
n, sn = builder.Builder(t, nFull, storage, opts...)
bp := func(t *testing.T, fullOpts []test.FullNodeOpts, storage []test.StorageMiner) ([]test.TestNode, []test.TestStorageNode) {
n, sn = builder.Builder(t, fullOpts, storage)
t.Run("pre-info-all", run)
+3 -4
View File
@@ -464,13 +464,12 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode,
return err
}
if jrnl, err := journal.OpenFSJournal(lr, journal.DefaultDisabledEvents); err == nil {
journal.J = jrnl
} else {
j, err := journal.OpenFSJournal(lr, journal.EnvDisabledEvents())
if err != nil {
return fmt.Errorf("failed to open filesystem journal: %w", err)
}
m := miner.NewMiner(api, epp, a, slashfilter.New(mds))
m := miner.NewMiner(api, epp, a, slashfilter.New(mds), j)
{
if err := m.Start(ctx); err != nil {
return xerrors.Errorf("failed to start up genesis miner: %w", err)
+94
View File
@@ -0,0 +1,94 @@
package main
import (
"bytes"
"context"
"encoding/hex"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
)
type LoggedWallet struct {
under api.WalletAPI
}
func (c *LoggedWallet) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
n, err := typ.Name()
if err != nil {
return address.Address{}, err
}
log.Infow("WalletNew", "type", n)
return c.under.WalletNew(ctx, typ)
}
func (c *LoggedWallet) WalletHas(ctx context.Context, addr address.Address) (bool, error) {
log.Infow("WalletHas", "address", addr)
return c.under.WalletHas(ctx, addr)
}
func (c *LoggedWallet) WalletList(ctx context.Context) ([]address.Address, error) {
log.Infow("WalletList")
return c.under.WalletList(ctx)
}
func (c *LoggedWallet) WalletSign(ctx context.Context, k address.Address, msg []byte, meta api.MsgMeta) (*crypto.Signature, error) {
switch meta.Type {
case api.MTChainMsg:
var cmsg types.Message
if err := cmsg.UnmarshalCBOR(bytes.NewReader(meta.Extra)); err != nil {
return nil, xerrors.Errorf("unmarshalling message: %w", err)
}
_, bc, err := cid.CidFromBytes(msg)
if err != nil {
return nil, xerrors.Errorf("getting cid from signing bytes: %w", err)
}
if !cmsg.Cid().Equals(bc) {
return nil, xerrors.Errorf("cid(meta.Extra).bytes() != msg")
}
log.Infow("WalletSign",
"address", k,
"type", meta.Type,
"from", cmsg.From,
"to", cmsg.To,
"value", types.FIL(cmsg.Value),
"feecap", types.FIL(cmsg.RequiredFunds()),
"method", cmsg.Method,
"params", hex.EncodeToString(cmsg.Params))
default:
log.Infow("WalletSign", "address", k, "type", meta.Type)
}
return c.under.WalletSign(ctx, k, msg, meta)
}
func (c *LoggedWallet) WalletExport(ctx context.Context, a address.Address) (*types.KeyInfo, error) {
log.Infow("WalletExport", "address", a)
return c.under.WalletExport(ctx, a)
}
func (c *LoggedWallet) WalletImport(ctx context.Context, ki *types.KeyInfo) (address.Address, error) {
log.Infow("WalletImport", "type", ki.Type)
return c.under.WalletImport(ctx, ki)
}
func (c *LoggedWallet) WalletDelete(ctx context.Context, addr address.Address) error {
log.Infow("WalletDelete", "address", addr)
return c.under.WalletDelete(ctx, addr)
}
+141
View File
@@ -0,0 +1,141 @@
package main
import (
"context"
"net"
"net/http"
"os"
"github.com/gorilla/mux"
logging "github.com/ipfs/go-log/v2"
"github.com/urfave/cli/v2"
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/wallet"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/lib/lotuslog"
"github.com/filecoin-project/lotus/node/repo"
)
var log = logging.Logger("main")
const FlagWalletRepo = "wallet-repo"
func main() {
lotuslog.SetupLogLevels()
local := []*cli.Command{
runCmd,
}
app := &cli.App{
Name: "lotus-wallet",
Usage: "Basic external wallet",
Version: build.UserVersion(),
Flags: []cli.Flag{
&cli.StringFlag{
Name: FlagWalletRepo,
EnvVars: []string{"WALLET_PATH"},
Value: "~/.lotuswallet", // TODO: Consider XDG_DATA_HOME
},
},
Commands: local,
}
app.Setup()
if err := app.Run(os.Args); err != nil {
log.Warnf("%+v", err)
return
}
}
var runCmd = &cli.Command{
Name: "run",
Usage: "Start lotus wallet",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "listen",
Usage: "host address and port the wallet api will listen on",
Value: "0.0.0.0:1777",
},
},
Action: func(cctx *cli.Context) error {
log.Info("Starting lotus wallet")
ctx := lcli.ReqContext(cctx)
ctx, cancel := context.WithCancel(ctx)
defer cancel()
repoPath := cctx.String(FlagWalletRepo)
r, err := repo.NewFS(repoPath)
if err != nil {
return err
}
ok, err := r.Exists()
if err != nil {
return err
}
if !ok {
if err := r.Init(repo.Worker); err != nil {
return err
}
}
lr, err := r.Lock(repo.Wallet)
if err != nil {
return err
}
ks, err := lr.KeyStore()
if err != nil {
return err
}
w, err := wallet.NewWallet(ks)
if err != nil {
return err
}
address := cctx.String("listen")
mux := mux.NewRouter()
log.Info("Setting up API endpoint at " + address)
rpcServer := jsonrpc.NewServer()
rpcServer.Register("Filecoin", &LoggedWallet{under: w})
mux.Handle("/rpc/v0", rpcServer)
mux.PathPrefix("/").Handler(http.DefaultServeMux) // pprof
/*ah := &auth.Handler{
Verify: nodeApi.AuthVerify,
Next: mux.ServeHTTP,
}*/
srv := &http.Server{
Handler: mux,
BaseContext: func(listener net.Listener) context.Context {
return ctx
},
}
go func() {
<-ctx.Done()
log.Warn("Shutting down...")
if err := srv.Shutdown(context.TODO()); err != nil {
log.Errorf("shutting down RPC server failed: %s", err)
}
log.Warn("Graceful shutdown successful")
}()
nl, err := net.Listen("tcp", address)
if err != nil {
return err
}
return srv.Serve(nl)
},
}
+38 -7
View File
@@ -15,8 +15,6 @@ import (
"runtime/pprof"
"strings"
"github.com/filecoin-project/lotus/chain/types"
paramfetch "github.com/filecoin-project/go-paramfetch"
"github.com/mitchellh/go-homedir"
"github.com/multiformats/go-multiaddr"
@@ -32,9 +30,11 @@ import (
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
"github.com/filecoin-project/lotus/journal"
"github.com/filecoin-project/lotus/lib/blockstore"
"github.com/filecoin-project/lotus/lib/peermgr"
"github.com/filecoin-project/lotus/lib/ulimit"
@@ -114,6 +114,11 @@ var DaemonCmd = &cli.Command{
Name: "halt-after-import",
Usage: "halt the process after importing chain from file",
},
&cli.BoolFlag{
Name: "lite",
Usage: "start lotus in lite mode",
Hidden: true,
},
&cli.StringFlag{
Name: "pprof",
Usage: "specify name of file for writing cpu profile to",
@@ -133,6 +138,8 @@ var DaemonCmd = &cli.Command{
},
},
Action: func(cctx *cli.Context) error {
isLite := cctx.Bool("lite")
err := runmetrics.Enable(runmetrics.RunMetricOptions{
EnableCPU: true,
EnableMemory: true,
@@ -192,8 +199,10 @@ var DaemonCmd = &cli.Command{
return xerrors.Errorf("repo init error: %w", err)
}
if err := paramfetch.GetParams(lcli.ReqContext(cctx), build.ParametersJSON(), 0); err != nil {
return xerrors.Errorf("fetching proof parameters: %w", err)
if !isLite {
if err := paramfetch.GetParams(lcli.ReqContext(cctx), build.ParametersJSON(), 0); err != nil {
return xerrors.Errorf("fetching proof parameters: %w", err)
}
}
var genBytes []byte
@@ -240,10 +249,23 @@ var DaemonCmd = &cli.Command{
shutdownChan := make(chan struct{})
// If the daemon is started in "lite mode", provide a GatewayAPI
// for RPC calls
liteModeDeps := node.Options()
if isLite {
gapi, closer, err := lcli.GetGatewayAPI(cctx)
if err != nil {
return err
}
defer closer()
liteModeDeps = node.Override(new(api.GatewayAPI), gapi)
}
var api api.FullNode
stop, err := node.New(ctx,
node.FullAPI(&api),
node.FullAPI(&api, node.Lite(isLite)),
node.Override(new(dtypes.Bootstrapper), isBootstrapper),
node.Override(new(dtypes.ShutdownChan), shutdownChan),
@@ -251,6 +273,7 @@ var DaemonCmd = &cli.Command{
node.Repo(r),
genesis,
liteModeDeps,
node.ApplyIf(func(s *node.Settings) bool { return cctx.IsSet("api") },
node.Override(node.SetApiEndpointKey, func(lr repo.LockedRepo) error {
@@ -388,7 +411,11 @@ func ImportChain(r repo.Repo, fname string, snapshot bool) (err error) {
bs := blockstore.NewBlockstore(ds)
cst := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier))
j, err := journal.OpenFSJournal(lr, journal.EnvDisabledEvents())
if err != nil {
return xerrors.Errorf("failed to open journal: %w", err)
}
cst := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier), j)
log.Infof("importing chain from %s...", fname)
@@ -409,6 +436,10 @@ func ImportChain(r repo.Repo, fname string, snapshot bool) (err error) {
return xerrors.Errorf("importing chain failed: %w", err)
}
if err := cst.FlushValidationCache(); err != nil {
return xerrors.Errorf("flushing validation cache failed: %w", err)
}
gb, err := cst.GetTipsetByHeight(context.TODO(), 0, ts, true)
if err != nil {
return err
@@ -428,7 +459,7 @@ func ImportChain(r repo.Repo, fname string, snapshot bool) (err error) {
}
}
log.Info("accepting %s as new head", ts.Cids())
log.Infof("accepting %s as new head", ts.Cids())
if err := cst.SetHead(ts); err != nil {
return err
}
+1 -1
View File
@@ -87,7 +87,7 @@ func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, preroot
syscalls = vm.Syscalls(ffiwrapper.ProofVerifier)
vmRand = NewFixedRand()
cs = store.NewChainStore(bs, ds, syscalls)
cs = store.NewChainStore(bs, ds, syscalls, nil)
sm = stmgr.NewStateManager(cs)
)
File diff suppressed because it is too large Load Diff
+1 -5
View File
@@ -290,10 +290,6 @@ func (sb *Sealer) UnsealPiece(ctx context.Context, sector abi.SectorID, offset s
defer opr.Close() // nolint
padwriter := fr32.NewPadWriter(out)
if err != nil {
perr = xerrors.Errorf("creating new padded writer: %w", err)
return
}
bsize := uint64(size.Padded())
if bsize > uint64(runtime.NumCPU())*fr32.MTTresh {
@@ -302,7 +298,7 @@ func (sb *Sealer) UnsealPiece(ctx context.Context, sector abi.SectorID, offset s
bw := bufio.NewWriterSize(padwriter, int(abi.PaddedPieceSize(bsize).Unpadded()))
_, err = io.CopyN(bw, opr, int64(size))
_, err := io.CopyN(bw, opr, int64(size))
if err != nil {
perr = xerrors.Errorf("copying data: %w", err)
return
+3 -3
View File
@@ -30,16 +30,16 @@ require (
github.com/filecoin-project/go-data-transfer v0.6.7
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f
github.com/filecoin-project/go-fil-markets v0.7.1
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20201008195726-68c6a2704e49
github.com/filecoin-project/go-multistore v0.0.3
github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261
github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab
github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe
github.com/filecoin-project/go-statestore v0.1.0
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b
github.com/filecoin-project/specs-actors v0.9.12
github.com/filecoin-project/specs-actors/v2 v2.0.1
github.com/filecoin-project/specs-actors/v2 v2.1.0
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796
github.com/filecoin-project/test-vectors/schema v0.0.4
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
+6 -4
View File
@@ -252,8 +252,8 @@ github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CW
github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24=
github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM=
github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0/go.mod h1:7aWZdaQ1b16BVoQUYR+eEvrDCGJoPLxFpDynFjYfBjI=
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52 h1:FXtCp0ybqdQL9knb3OGDpkNTaBbPxgkqPeWKotUwkH0=
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4=
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20201008195726-68c6a2704e49 h1:FSY245KeXFCUgyfFEu+bhrZNk8BGGJyfpSmQl2aiPU8=
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20201008195726-68c6a2704e49/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4=
github.com/filecoin-project/go-multistore v0.0.3 h1:vaRBY4YiA2UZFPK57RNuewypB8u0DzzQwqsL0XarpnI=
github.com/filecoin-project/go-multistore v0.0.3/go.mod h1:kaNqCC4IhU4B1uyr7YWFHd23TL4KM32aChS0jNkyUvQ=
github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 h1:+/4aUeUoKr6AKfPE3mBhXA5spIV6UcKdTYDPNU2Tdmg=
@@ -265,6 +265,8 @@ github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4/go
github.com/filecoin-project/go-state-types v0.0.0-20200905071437-95828685f9df/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I=
github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab h1:cEDC5Ei8UuT99hPWhCjA72SM9AuRtnpvdSTIYbnzN8I=
github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g=
github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b h1:bMUfG6Sy6YSMbsjQAO1Q2vEZldbSdsbRy/FX3OlTck0=
github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g=
github.com/filecoin-project/go-statemachine v0.0.0-20200714194326-a77c3ae20989/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw=
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
@@ -276,8 +278,8 @@ github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07
github.com/filecoin-project/specs-actors v0.9.7/go.mod h1:wM2z+kwqYgXn5Z7scV1YHLyd1Q1cy0R8HfTIWQ0BFGU=
github.com/filecoin-project/specs-actors v0.9.12 h1:iIvk58tuMtmloFNHhAOQHG+4Gci6Lui0n7DYQGi3cJk=
github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao=
github.com/filecoin-project/specs-actors/v2 v2.0.1 h1:bf08x6tqCDfClzrv2q/rmt/A/UbBOy1KgaoogQEcLhU=
github.com/filecoin-project/specs-actors/v2 v2.0.1/go.mod h1:v2NZVYinNIKA9acEMBm5wWXxqv5+frFEbekBFemYghY=
github.com/filecoin-project/specs-actors/v2 v2.1.0 h1:ocEuGz8DG2cUWw32c/tvF8D6xT+dGVWJTr5yDevU00g=
github.com/filecoin-project/specs-actors/v2 v2.1.0/go.mod h1:E7fAX4CZkDVQvDNRCxfq+hc3nx56KcCKyuZf0hlQJ20=
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 h1:dJsTPWpG2pcTeojO2pyn0c6l+x/3MZYCBgo/9d11JEk=
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g=
github.com/filecoin-project/test-vectors/schema v0.0.4 h1:QTRd0gb/NP4ZOTM7Dib5U3xE1/ToGDKnYLfxkC3t/m8=
+19
View File
@@ -0,0 +1,19 @@
package journal
import (
"os"
)
// envJournalDisabledEvents is the environment variable through which disabled
// journal events can be customized.
const envDisabledEvents = "LOTUS_JOURNAL_DISABLED_EVENTS"
func EnvDisabledEvents() DisabledEvents {
if env, ok := os.LookupEnv(envDisabledEvents); ok {
if ret, err := ParseDisabledEvents(env); err == nil {
return ret
}
}
// fallback if env variable is not set, or if it failed to parse.
return DefaultDisabledEvents
}
-9
View File
@@ -1,9 +0,0 @@
package journal
var (
// J is a globally accessible Journal. It starts being NilJournal, and early
// during the Lotus initialization routine, it is reset to whichever Journal
// is configured (by default, the filesystem journal). Components can safely
// record in the journal by calling: journal.J.RecordEvent(...).
J Journal = NilJournal() // nolint
)
+8 -8
View File
@@ -28,9 +28,9 @@ type RetrievalProviderEvt struct {
}
// StorageClientJournaler records journal events from the storage client.
func StorageClientJournaler(evtType journal.EventType) func(event storagemarket.ClientEvent, deal storagemarket.ClientDeal) {
func StorageClientJournaler(j journal.Journal, evtType journal.EventType) func(event storagemarket.ClientEvent, deal storagemarket.ClientDeal) {
return func(event storagemarket.ClientEvent, deal storagemarket.ClientDeal) {
journal.J.RecordEvent(evtType, func() interface{} {
j.RecordEvent(evtType, func() interface{} {
return StorageClientEvt{
Event: storagemarket.ClientEvents[event],
Deal: deal,
@@ -40,9 +40,9 @@ func StorageClientJournaler(evtType journal.EventType) func(event storagemarket.
}
// StorageProviderJournaler records journal events from the storage provider.
func StorageProviderJournaler(evtType journal.EventType) func(event storagemarket.ProviderEvent, deal storagemarket.MinerDeal) {
func StorageProviderJournaler(j journal.Journal, evtType journal.EventType) func(event storagemarket.ProviderEvent, deal storagemarket.MinerDeal) {
return func(event storagemarket.ProviderEvent, deal storagemarket.MinerDeal) {
journal.J.RecordEvent(evtType, func() interface{} {
j.RecordEvent(evtType, func() interface{} {
return StorageProviderEvt{
Event: storagemarket.ProviderEvents[event],
Deal: deal,
@@ -52,9 +52,9 @@ func StorageProviderJournaler(evtType journal.EventType) func(event storagemarke
}
// RetrievalClientJournaler records journal events from the retrieval client.
func RetrievalClientJournaler(evtType journal.EventType) func(event retrievalmarket.ClientEvent, deal retrievalmarket.ClientDealState) {
func RetrievalClientJournaler(j journal.Journal, evtType journal.EventType) func(event retrievalmarket.ClientEvent, deal retrievalmarket.ClientDealState) {
return func(event retrievalmarket.ClientEvent, deal retrievalmarket.ClientDealState) {
journal.J.RecordEvent(evtType, func() interface{} {
j.RecordEvent(evtType, func() interface{} {
return RetrievalClientEvt{
Event: retrievalmarket.ClientEvents[event],
Deal: deal,
@@ -64,9 +64,9 @@ func RetrievalClientJournaler(evtType journal.EventType) func(event retrievalmar
}
// RetrievalProviderJournaler records journal events from the retrieval provider.
func RetrievalProviderJournaler(evtType journal.EventType) func(event retrievalmarket.ProviderEvent, deal retrievalmarket.ProviderDealState) {
func RetrievalProviderJournaler(j journal.Journal, evtType journal.EventType) func(event retrievalmarket.ProviderEvent, deal retrievalmarket.ProviderDealState) {
return func(event retrievalmarket.ProviderEvent, deal retrievalmarket.ProviderDealState) {
journal.J.RecordEvent(evtType, func() interface{} {
j.RecordEvent(evtType, func() interface{} {
return RetrievalProviderEvt{
Event: retrievalmarket.ProviderEvents[event],
Deal: deal,
+15 -9
View File
@@ -6,19 +6,22 @@ import (
"bytes"
"context"
"github.com/filecoin-project/go-state-types/big"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
"golang.org/x/xerrors"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-address"
cborutil "github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/go-fil-markets/shared"
"github.com/filecoin-project/go-fil-markets/storagemarket"
"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/go-state-types/exitcode"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
"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/events"
@@ -30,7 +33,6 @@ import (
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/markets/utils"
"github.com/filecoin-project/lotus/node/impl/full"
"github.com/ipfs/go-cid"
)
type ClientNodeAdapter struct {
@@ -187,7 +189,7 @@ func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal stor
}
// TODO: timeout
_, ret, _, err := c.sm.WaitForMessage(ctx, *deal.PublishMessage, build.MessageConfidence)
_, ret, _, err := c.sm.WaitForMessage(ctx, *deal.PublishMessage, build.MessageConfidence, stmgr.LookbackNoLimit)
if err != nil {
return 0, xerrors.Errorf("waiting for deal publish message: %w", err)
}
@@ -422,7 +424,9 @@ func (c *ClientNodeAdapter) SignProposal(ctx context.Context, signer address.Add
return nil, err
}
sig, err := c.Wallet.Sign(ctx, signer, buf)
sig, err := c.Wallet.WalletSign(ctx, signer, buf, api.MsgMeta{
Type: api.MTDealProposal,
})
if err != nil {
return nil, err
}
@@ -434,7 +438,7 @@ func (c *ClientNodeAdapter) SignProposal(ctx context.Context, signer address.Add
}
func (c *ClientNodeAdapter) GetDefaultWalletAddress(ctx context.Context) (address.Address, error) {
addr, err := c.Wallet.GetDefault()
addr, err := c.DefWallet.GetDefault()
return addr, err
}
@@ -475,7 +479,9 @@ func (c *ClientNodeAdapter) SignBytes(ctx context.Context, signer address.Addres
return nil, err
}
localSignature, err := c.Wallet.Sign(ctx, signer, b)
localSignature, err := c.Wallet.WalletSign(ctx, signer, b, api.MsgMeta{
Type: api.MTUnknown, // TODO: pass type here
})
if err != nil {
return nil, err
}
+6 -3
View File
@@ -49,7 +49,7 @@ func randTimeOffset(width time.Duration) time.Duration {
return val - (width / 2)
}
func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf *slashfilter.SlashFilter) *Miner {
func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf *slashfilter.SlashFilter, j journal.Journal) *Miner {
arc, err := lru.NewARC(10000)
if err != nil {
panic(err)
@@ -74,8 +74,9 @@ func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address,
sf: sf,
minedBlockHeights: arc,
evtTypes: [...]journal.EventType{
evtTypeBlockMined: journal.J.RegisterEventType("miner", "block_mined"),
evtTypeBlockMined: j.RegisterEventType("miner", "block_mined"),
},
journal: j,
}
}
@@ -97,6 +98,7 @@ type Miner struct {
minedBlockHeights *lru.ARCCache
evtTypes [1]journal.EventType
journal journal.Journal
}
func (m *Miner) Address() address.Address {
@@ -239,7 +241,7 @@ minerLoop:
onDone(b != nil, h, nil)
if b != nil {
journal.J.RecordEvent(m.evtTypes[evtTypeBlockMined], func() interface{} {
m.journal.RecordEvent(m.evtTypes[evtTypeBlockMined], func() interface{} {
return map[string]interface{}{
"parents": base.TipSet.Cids(),
"nulls": base.NullRounds,
@@ -327,6 +329,7 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error)
}
ltsw, err := m.api.ChainTipSetWeight(ctx, m.lastWork.TipSet.Key())
if err != nil {
m.lastWork = nil
return nil, err
}
+2
View File
@@ -11,6 +11,7 @@ import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/gen/slashfilter"
"github.com/filecoin-project/lotus/journal"
)
type MineReq struct {
@@ -32,6 +33,7 @@ func NewTestMiner(nextCh <-chan MineReq, addr address.Address) func(api.FullNode
minedBlockHeights: arc,
address: addr,
sf: slashfilter.New(ds.NewMapDatastore()),
journal: journal.NilJournal(),
}
if err := m.Start(context.TODO()); err != nil {
+62 -38
View File
@@ -3,9 +3,15 @@ package node
import (
"context"
"errors"
"os"
"time"
"github.com/filecoin-project/lotus/chain"
"github.com/filecoin-project/lotus/chain/exchange"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/node/hello"
logging "github.com/ipfs/go-log"
ci "github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/host"
@@ -29,9 +35,7 @@ import (
storage2 "github.com/filecoin-project/specs-storage/storage"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain"
"github.com/filecoin-project/lotus/chain/beacon"
"github.com/filecoin-project/lotus/chain/exchange"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/gen/slashfilter"
"github.com/filecoin-project/lotus/chain/market"
@@ -39,10 +43,8 @@ import (
"github.com/filecoin-project/lotus/chain/messagesigner"
"github.com/filecoin-project/lotus/chain/metrics"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/chain/wallet/remotewallet"
sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
@@ -56,9 +58,9 @@ import (
"github.com/filecoin-project/lotus/markets/storageadapter"
"github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/lotus/node/config"
"github.com/filecoin-project/lotus/node/hello"
"github.com/filecoin-project/lotus/node/impl"
"github.com/filecoin-project/lotus/node/impl/common"
"github.com/filecoin-project/lotus/node/impl/full"
"github.com/filecoin-project/lotus/node/modules"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/modules/helpers"
@@ -71,10 +73,6 @@ import (
"github.com/filecoin-project/lotus/storage/sectorblocks"
)
// EnvJournalDisabledEvents is the environment variable through which disabled
// journal events can be customized.
const EnvJournalDisabledEvents = "LOTUS_JOURNAL_DISABLED_EVENTS"
//nolint:deadcode,varcheck
var log = logging.Logger("builder")
@@ -158,25 +156,14 @@ type Settings struct {
Online bool // Online option applied
Config bool // Config option applied
Lite bool // Start node in "lite" mode
}
func defaults() []Option {
return []Option{
// global system journal.
Override(new(journal.DisabledEvents), func() journal.DisabledEvents {
if env, ok := os.LookupEnv(EnvJournalDisabledEvents); ok {
if ret, err := journal.ParseDisabledEvents(env); err == nil {
return ret
}
}
// fallback if env variable is not set, or if it failed to parse.
return journal.DefaultDisabledEvents
}),
Override(new(journal.DisabledEvents), journal.EnvDisabledEvents),
Override(new(journal.Journal), modules.OpenFilesystemJournal),
Override(InitJournalKey, func(j journal.Journal) {
journal.J = j // eagerly sets the global journal through fx.Invoke.
}),
Override(new(helpers.MetricsCtx), context.Background),
Override(new(record.Validator), modules.RecordValidator),
@@ -232,6 +219,10 @@ func isType(t repo.RepoType) func(s *Settings) bool {
// Online sets up basic libp2p node
func Online() Option {
isFullOrLiteNode := func(s *Settings) bool { return s.nodeType == repo.FullNode }
isFullNode := func(s *Settings) bool { return s.nodeType == repo.FullNode && !s.Lite }
isLiteNode := func(s *Settings) bool { return s.nodeType == repo.FullNode && s.Lite }
return Options(
// make sure that online is applied before Config.
// This is important because Config overrides some of Online units
@@ -245,23 +236,23 @@ func Online() Option {
// common
Override(new(*slashfilter.SlashFilter), modules.NewSlashFilter),
// Full node
ApplyIf(isType(repo.FullNode),
// Full node or lite node
ApplyIf(isFullOrLiteNode,
// TODO: Fix offline mode
Override(new(dtypes.BootstrapPeers), modules.BuiltinBootstrap),
Override(new(dtypes.DrandBootstrap), modules.DrandBootstrap),
Override(new(dtypes.DrandSchedule), modules.BuiltinDrandConfig),
Override(HandleIncomingMessagesKey, modules.HandleIncomingMessages),
Override(new(ffiwrapper.Verifier), ffiwrapper.ProofVerifier),
Override(new(vm.SyscallBuilder), vm.Syscalls),
Override(new(*store.ChainStore), modules.ChainStore),
Override(new(stmgr.UpgradeSchedule), stmgr.DefaultUpgradeSchedule()),
Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule),
Override(new(*wallet.Wallet), wallet.NewWallet),
Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))),
Override(new(*wallet.LocalWallet), wallet.NewWallet),
Override(new(api.WalletAPI), From(new(*wallet.LocalWallet))),
Override(new(wallet.Default), From(new(*wallet.LocalWallet))),
Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner),
Override(new(dtypes.ChainGCLocker), blockstore.NewGCLocker),
@@ -288,12 +279,6 @@ func Online() Option {
Override(new(dtypes.Graphsync), modules.Graphsync),
Override(new(*dtypes.MpoolLocker), new(dtypes.MpoolLocker)),
Override(RunHelloKey, modules.RunHello),
Override(RunChainExchangeKey, modules.RunChainExchange),
Override(RunPeerMgrKey, modules.RunPeerMgr),
Override(HandleIncomingBlocksKey, modules.HandleIncomingBlocks),
Override(new(*discoveryimpl.Local), modules.NewLocalDiscovery),
Override(new(discovery.PeerResolver), modules.RetrievalResolver),
@@ -312,8 +297,34 @@ func Online() Option {
Override(SettlePaymentChannelsKey, settler.SettlePaymentChannels),
),
// Lite node
ApplyIf(isLiteNode,
Override(new(messagesigner.MpoolNonceAPI), From(new(modules.MpoolNonceAPI))),
Override(new(full.ChainModuleAPI), From(new(api.GatewayAPI))),
Override(new(full.GasModuleAPI), From(new(api.GatewayAPI))),
Override(new(full.MpoolModuleAPI), From(new(api.GatewayAPI))),
Override(new(full.StateModuleAPI), From(new(api.GatewayAPI))),
Override(new(stmgr.StateManagerAPI), modules.NewRPCStateManager),
),
// Full node
ApplyIf(isFullNode,
Override(new(messagesigner.MpoolNonceAPI), From(new(*messagepool.MessagePool))),
Override(new(full.ChainModuleAPI), From(new(full.ChainModule))),
Override(new(full.GasModuleAPI), From(new(full.GasModule))),
Override(new(full.MpoolModuleAPI), From(new(full.MpoolModule))),
Override(new(full.StateModuleAPI), From(new(full.StateModule))),
Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))),
Override(RunHelloKey, modules.RunHello),
Override(RunChainExchangeKey, modules.RunChainExchange),
Override(RunPeerMgrKey, modules.RunPeerMgr),
Override(HandleIncomingMessagesKey, modules.HandleIncomingMessages),
Override(HandleIncomingBlocksKey, modules.HandleIncomingBlocks),
),
// miner
ApplyIf(func(s *Settings) bool { return s.nodeType == repo.StorageMiner },
ApplyIf(isType(repo.StorageMiner),
Override(new(api.Common), From(new(common.CommonAPI))),
Override(new(sectorstorage.StorageAuth), modules.StorageAuth),
@@ -448,6 +459,9 @@ func ConfigFullNode(c interface{}) Option {
If(cfg.Metrics.HeadNotifs,
Override(HeadMetricsKey, metrics.SendHeadNotifs(cfg.Metrics.Nickname)),
),
If(cfg.Wallet.RemoteBackend != "",
Override(new(api.WalletAPI), remotewallet.SetupRemoteWallet(cfg.Wallet.RemoteBackend)),
),
)
}
@@ -507,12 +521,22 @@ func Repo(r repo.Repo) Option {
}
}
func FullAPI(out *api.FullNode) Option {
type FullOption = Option
func Lite(enable bool) FullOption {
return func(s *Settings) error {
s.Lite = enable
return nil
}
}
func FullAPI(out *api.FullNode, fopts ...FullOption) Option {
return Options(
func(s *Settings) error {
s.nodeType = repo.FullNode
return nil
},
Options(fopts...),
func(s *Settings) error {
resAPI := &impl.FullNodeAPI{}
s.invokes[ExtractApiKey] = fx.Populate(resAPI)
+5
View File
@@ -22,6 +22,7 @@ type FullNode struct {
Common
Client Client
Metrics Metrics
Wallet Wallet
}
// // Common
@@ -107,6 +108,10 @@ type Client struct {
IpfsUseForRetrieval bool
}
type Wallet struct {
RemoteBackend string
}
func defCommon() Common {
return Common{
API: API{
+24 -16
View File
@@ -462,13 +462,19 @@ type retrievalSubscribeEvent struct {
state rm.ClientDealState
}
func readSubscribeEvents(ctx context.Context, subscribeEvents chan retrievalSubscribeEvent, events chan marketevents.RetrievalEvent) error {
func readSubscribeEvents(ctx context.Context, dealID retrievalmarket.DealID, subscribeEvents chan retrievalSubscribeEvent, events chan marketevents.RetrievalEvent) error {
for {
var subscribeEvent retrievalSubscribeEvent
select {
case <-ctx.Done():
return xerrors.New("Retrieval Timed Out")
case subscribeEvent = <-subscribeEvents:
if subscribeEvent.state.ID != dealID {
// we can't check the deal ID ahead of time because:
// 1. We need to subscribe before retrieving.
// 2. We won't know the deal ID until after retrieving.
continue
}
}
select {
@@ -531,19 +537,6 @@ func (a *API) clientRetrieve(ctx context.Context, order api.RetrievalOrder, ref
return err
}*/
var dealID retrievalmarket.DealID
subscribeEvents := make(chan retrievalSubscribeEvent, 1)
subscribeCtx, cancel := context.WithCancel(ctx)
defer cancel()
unsubscribe := a.Retrieval.SubscribeToEvents(func(event rm.ClientEvent, state rm.ClientDealState) {
if state.PayloadCID.Equals(order.Root) && state.ID == dealID {
select {
case <-subscribeCtx.Done():
case subscribeEvents <- retrievalSubscribeEvent{event, state}:
}
}
})
ppb := types.BigDiv(order.Total, types.NewInt(order.Size))
params, err := rm.NewParamsV1(ppb, order.PaymentInterval, order.PaymentIntervalIncrease, shared.AllSelector(), order.Piece, order.UnsealPrice)
@@ -562,7 +555,21 @@ func (a *API) clientRetrieve(ctx context.Context, order api.RetrievalOrder, ref
_ = a.RetrievalStoreMgr.ReleaseStore(store)
}()
dealID, err = a.Retrieval.Retrieve(
// Subscribe to events before retrieving to avoid losing events.
subscribeEvents := make(chan retrievalSubscribeEvent, 1)
subscribeCtx, cancel := context.WithCancel(ctx)
defer cancel()
unsubscribe := a.Retrieval.SubscribeToEvents(func(event rm.ClientEvent, state rm.ClientDealState) {
// We'll check the deal IDs inside readSubscribeEvents.
if state.PayloadCID.Equals(order.Root) {
select {
case <-subscribeCtx.Done():
case subscribeEvents <- retrievalSubscribeEvent{event, state}:
}
}
})
dealID, err := a.Retrieval.Retrieve(
ctx,
order.Root,
params,
@@ -573,11 +580,12 @@ func (a *API) clientRetrieve(ctx context.Context, order api.RetrievalOrder, ref
store.StoreID())
if err != nil {
unsubscribe()
finish(xerrors.Errorf("Retrieve failed: %w", err))
return
}
err = readSubscribeEvents(ctx, subscribeEvents, events)
err = readSubscribeEvents(ctx, dealID, subscribeEvents, events)
unsubscribe()
if err != nil {
+25 -7
View File
@@ -39,10 +39,28 @@ import (
var log = logging.Logger("fullnode")
type ChainModuleAPI interface {
ChainHead(context.Context) (*types.TipSet, error)
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
}
// ChainModule provides a default implementation of ChainModuleAPI.
// It can be swapped out with another implementation through Dependency
// Injection (for example with a thin RPC client).
type ChainModule struct {
fx.In
Chain *store.ChainStore
}
var _ ChainModuleAPI = (*ChainModule)(nil)
type ChainAPI struct {
fx.In
WalletAPI
ChainModuleAPI
Chain *store.ChainStore
}
@@ -51,8 +69,8 @@ func (a *ChainAPI) ChainNotify(ctx context.Context) (<-chan []*api.HeadChange, e
return a.Chain.SubHeadChanges(ctx), nil
}
func (a *ChainAPI) ChainHead(context.Context) (*types.TipSet, error) {
return a.Chain.GetHeaviestTipSet(), nil
func (m *ChainModule) ChainHead(context.Context) (*types.TipSet, error) {
return m.Chain.GetHeaviestTipSet(), nil
}
func (a *ChainAPI) ChainGetRandomnessFromTickets(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) {
@@ -77,8 +95,8 @@ func (a *ChainAPI) ChainGetBlock(ctx context.Context, msg cid.Cid) (*types.Block
return a.Chain.GetBlock(msg)
}
func (a *ChainAPI) ChainGetTipSet(ctx context.Context, key types.TipSetKey) (*types.TipSet, error) {
return a.Chain.LoadTipSet(key)
func (m *ChainModule) ChainGetTipSet(ctx context.Context, key types.TipSetKey) (*types.TipSet, error) {
return m.Chain.LoadTipSet(key)
}
func (a *ChainAPI) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (*api.BlockMessages, error) {
@@ -180,12 +198,12 @@ func (a *ChainAPI) ChainGetParentReceipts(ctx context.Context, bcid cid.Cid) ([]
return out, nil
}
func (a *ChainAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
func (m *ChainModule) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return a.Chain.GetTipsetByHeight(ctx, h, ts, true)
return m.Chain.GetTipsetByHeight(ctx, h, ts, true)
}
func (a *ChainAPI) ChainReadObj(ctx context.Context, obj cid.Cid) ([]byte, error) {
+82 -21
View File
@@ -26,8 +26,27 @@ import (
"github.com/filecoin-project/lotus/chain/types"
)
type GasModuleAPI interface {
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
}
// GasModule provides a default implementation of GasModuleAPI.
// It can be swapped out with another implementation through Dependency
// Injection (for example with a thin RPC client).
type GasModule struct {
fx.In
Stmgr *stmgr.StateManager
Chain *store.ChainStore
Mpool *messagepool.MessagePool
}
var _ GasModuleAPI = (*GasModule)(nil)
type GasAPI struct {
fx.In
GasModuleAPI
Stmgr *stmgr.StateManager
Chain *store.ChainStore
Mpool *messagepool.MessagePool
@@ -36,9 +55,24 @@ type GasAPI struct {
const MinGasPremium = 100e3
const MaxSpendOnFeeDenom = 100
func (a *GasAPI) GasEstimateFeeCap(ctx context.Context, msg *types.Message, maxqueueblks int64,
tsk types.TipSetKey) (types.BigInt, error) {
ts := a.Chain.GetHeaviestTipSet()
func (a *GasAPI) GasEstimateFeeCap(
ctx context.Context,
msg *types.Message,
maxqueueblks int64,
tsk types.TipSetKey,
) (types.BigInt, error) {
return gasEstimateFeeCap(a.Chain, msg, maxqueueblks)
}
func (m *GasModule) GasEstimateFeeCap(
ctx context.Context,
msg *types.Message,
maxqueueblks int64,
tsk types.TipSetKey,
) (types.BigInt, error) {
return gasEstimateFeeCap(m.Chain, msg, maxqueueblks)
}
func gasEstimateFeeCap(cstore *store.ChainStore, msg *types.Message, maxqueueblks int64) (types.BigInt, error) {
ts := cstore.GetHeaviestTipSet()
parentBaseFee := ts.Blocks()[0].ParentBaseFee
increaseFactor := math.Pow(1.+1./float64(build.BaseFeeMaxChangeDenom), float64(maxqueueblks))
@@ -82,9 +116,25 @@ func medianGasPremium(prices []gasMeta, blocks int) abi.TokenAmount {
return premium
}
func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
sender address.Address, gaslimit int64, _ types.TipSetKey) (types.BigInt, error) {
func (a *GasAPI) GasEstimateGasPremium(
ctx context.Context,
nblocksincl uint64,
sender address.Address,
gaslimit int64,
_ types.TipSetKey,
) (types.BigInt, error) {
return gasEstimateGasPremium(a.Chain, nblocksincl)
}
func (m *GasModule) GasEstimateGasPremium(
ctx context.Context,
nblocksincl uint64,
sender address.Address,
gaslimit int64,
_ types.TipSetKey,
) (types.BigInt, error) {
return gasEstimateGasPremium(m.Chain, nblocksincl)
}
func gasEstimateGasPremium(cstore *store.ChainStore, nblocksincl uint64) (types.BigInt, error) {
if nblocksincl == 0 {
nblocksincl = 1
}
@@ -92,20 +142,20 @@ func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
var prices []gasMeta
var blocks int
ts := a.Chain.GetHeaviestTipSet()
ts := cstore.GetHeaviestTipSet()
for i := uint64(0); i < nblocksincl*2; i++ {
if ts.Height() == 0 {
break // genesis
}
pts, err := a.Chain.LoadTipSet(ts.Parents())
pts, err := cstore.LoadTipSet(ts.Parents())
if err != nil {
return types.BigInt{}, err
}
blocks += len(pts.Blocks())
msgs, err := a.Chain.MessagesForTipset(pts)
msgs, err := cstore.MessagesForTipset(pts)
if err != nil {
return types.BigInt{}, xerrors.Errorf("loading messages: %w", err)
}
@@ -142,19 +192,30 @@ func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
}
func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message, _ types.TipSetKey) (int64, error) {
return gasEstimateGasLimit(ctx, a.Chain, a.Stmgr, a.Mpool, msgIn)
}
func (m *GasModule) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message, _ types.TipSetKey) (int64, error) {
return gasEstimateGasLimit(ctx, m.Chain, m.Stmgr, m.Mpool, msgIn)
}
func gasEstimateGasLimit(
ctx context.Context,
cstore *store.ChainStore,
smgr *stmgr.StateManager,
mpool *messagepool.MessagePool,
msgIn *types.Message,
) (int64, error) {
msg := *msgIn
msg.GasLimit = build.BlockGasLimit
msg.GasFeeCap = types.NewInt(uint64(build.MinimumBaseFee) + 1)
msg.GasPremium = types.NewInt(1)
currTs := a.Chain.GetHeaviestTipSet()
fromA, err := a.Stmgr.ResolveToKeyAddress(ctx, msgIn.From, currTs)
currTs := cstore.GetHeaviestTipSet()
fromA, err := smgr.ResolveToKeyAddress(ctx, msgIn.From, currTs)
if err != nil {
return -1, xerrors.Errorf("getting key address: %w", err)
}
pending, ts := a.Mpool.PendingFor(fromA)
pending, ts := mpool.PendingFor(fromA)
priorMsgs := make([]types.ChainMsg, 0, len(pending))
for _, m := range pending {
priorMsgs = append(priorMsgs, m)
@@ -163,11 +224,11 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
// Try calling until we find a height with no migration.
var res *api.InvocResult
for {
res, err = a.Stmgr.CallWithGas(ctx, &msg, priorMsgs, ts)
res, err = smgr.CallWithGas(ctx, &msg, priorMsgs, ts)
if err != stmgr.ErrExpensiveFork {
break
}
ts, err = a.Chain.GetTipSetFromKey(ts.Parents())
ts, err = cstore.GetTipSetFromKey(ts.Parents())
if err != nil {
return -1, xerrors.Errorf("getting parent tipset: %w", err)
}
@@ -180,7 +241,7 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
}
// Special case for PaymentChannel collect, which is deleting actor
st, err := a.Stmgr.ParentState(ts)
st, err := smgr.ParentState(ts)
if err != nil {
_ = err
// somewhat ignore it as it can happen and we just want to detect
@@ -206,17 +267,17 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
return res.MsgRct.GasUsed + 76e3, nil
}
func (a *GasAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, _ types.TipSetKey) (*types.Message, error) {
func (m *GasModule) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, _ types.TipSetKey) (*types.Message, error) {
if msg.GasLimit == 0 {
gasLimit, err := a.GasEstimateGasLimit(ctx, msg, types.TipSetKey{})
gasLimit, err := m.GasEstimateGasLimit(ctx, msg, types.TipSetKey{})
if err != nil {
return nil, xerrors.Errorf("estimating gas used: %w", err)
}
msg.GasLimit = int64(float64(gasLimit) * a.Mpool.GetConfig().GasLimitOverestimation)
msg.GasLimit = int64(float64(gasLimit) * m.Mpool.GetConfig().GasLimitOverestimation)
}
if msg.GasPremium == types.EmptyInt || types.BigCmp(msg.GasPremium, types.NewInt(0)) == 0 {
gasPremium, err := a.GasEstimateGasPremium(ctx, 2, msg.From, msg.GasLimit, types.TipSetKey{})
gasPremium, err := m.GasEstimateGasPremium(ctx, 2, msg.From, msg.GasLimit, types.TipSetKey{})
if err != nil {
return nil, xerrors.Errorf("estimating gas price: %w", err)
}
@@ -224,7 +285,7 @@ func (a *GasAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message,
}
if msg.GasFeeCap == types.EmptyInt || types.BigCmp(msg.GasFeeCap, types.NewInt(0)) == 0 {
feeCap, err := a.GasEstimateFeeCap(ctx, msg, 20, types.EmptyTSK)
feeCap, err := m.GasEstimateFeeCap(ctx, msg, 20, types.EmptyTSK)
if err != nil {
return nil, xerrors.Errorf("estimating fee cap: %w", err)
}
+21 -3
View File
@@ -10,14 +10,32 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/lotus/chain/messagesigner"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes"
)
type MpoolModuleAPI interface {
MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error)
}
// MpoolModule provides a default implementation of MpoolModuleAPI.
// It can be swapped out with another implementation through Dependency
// Injection (for example with a thin RPC client).
type MpoolModule struct {
fx.In
Mpool *messagepool.MessagePool
}
var _ MpoolModuleAPI = (*MpoolModule)(nil)
type MpoolAPI struct {
fx.In
MpoolModuleAPI
WalletAPI
GasAPI
@@ -106,8 +124,8 @@ func (a *MpoolAPI) MpoolClear(ctx context.Context, local bool) error {
return nil
}
func (a *MpoolAPI) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) {
return a.Mpool.Push(smsg)
func (m *MpoolModule) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) {
return m.Mpool.Push(smsg)
}
func (a *MpoolAPI) MpoolPushUntrusted(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) {
@@ -162,7 +180,7 @@ func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message, spe
// Sign and push the message
return a.MessageSigner.SignMessage(ctx, msg, func(smsg *types.SignedMessage) error {
if _, err := a.Mpool.Push(smsg); err != nil {
if _, err := a.MpoolModuleAPI.MpoolPush(ctx, smsg); err != nil {
return xerrors.Errorf("mpool push: failed to push message: %w", err)
}
return nil
+69 -9
View File
@@ -23,9 +23,8 @@ import (
type MsigAPI struct {
fx.In
WalletAPI WalletAPI
StateAPI StateAPI
MpoolAPI MpoolAPI
StateAPI StateAPI
MpoolAPI MpoolAPI
}
func (a *MsigAPI) messageBuilder(ctx context.Context, from address.Address) (multisig.MessageBuilder, error) {
@@ -95,7 +94,7 @@ func (a *MsigAPI) MsigAddApprove(ctx context.Context, msig address.Address, src
return cid.Undef, actErr
}
return a.MsigApprove(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.AddSigner), enc)
return a.MsigApproveTxnHash(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.AddSigner), enc)
}
func (a *MsigAPI) MsigAddCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, newAdd address.Address, inc bool) (cid.Cid, error) {
@@ -122,7 +121,7 @@ func (a *MsigAPI) MsigSwapApprove(ctx context.Context, msig address.Address, src
return cid.Undef, actErr
}
return a.MsigApprove(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.SwapSigner), enc)
return a.MsigApproveTxnHash(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.SwapSigner), enc)
}
func (a *MsigAPI) MsigSwapCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
@@ -134,15 +133,64 @@ func (a *MsigAPI) MsigSwapCancel(ctx context.Context, msig address.Address, src
return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(builtin0.MethodsMultisig.SwapSigner), enc)
}
func (a *MsigAPI) MsigApprove(ctx context.Context, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
return a.msigApproveOrCancel(ctx, api.MsigApprove, msig, txID, proposer, to, amt, src, method, params)
func (a *MsigAPI) MsigApprove(ctx context.Context, msig address.Address, txID uint64, src address.Address) (cid.Cid, error) {
return a.msigApproveOrCancelSimple(ctx, api.MsigApprove, msig, txID, src)
}
func (a *MsigAPI) MsigApproveTxnHash(ctx context.Context, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
return a.msigApproveOrCancelTxnHash(ctx, api.MsigApprove, msig, txID, proposer, to, amt, src, method, params)
}
func (a *MsigAPI) MsigCancel(ctx context.Context, msig address.Address, txID uint64, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
return a.msigApproveOrCancel(ctx, api.MsigCancel, msig, txID, src, to, amt, src, method, params)
return a.msigApproveOrCancelTxnHash(ctx, api.MsigCancel, msig, txID, src, to, amt, src, method, params)
}
func (a *MsigAPI) msigApproveOrCancel(ctx context.Context, operation api.MsigProposeResponse, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
func (a *MsigAPI) MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error) {
enc, actErr := serializeRemoveParams(toRemove, decrease)
if actErr != nil {
return cid.Undef, actErr
}
return a.MsigPropose(ctx, msig, msig, types.NewInt(0), proposer, uint64(builtin0.MethodsMultisig.RemoveSigner), enc)
}
func (a *MsigAPI) msigApproveOrCancelSimple(ctx context.Context, operation api.MsigProposeResponse, msig address.Address, txID uint64, src address.Address) (cid.Cid, error) {
if msig == address.Undef {
return cid.Undef, xerrors.Errorf("must provide multisig address")
}
if src == address.Undef {
return cid.Undef, xerrors.Errorf("must provide source address")
}
mb, err := a.messageBuilder(ctx, src)
if err != nil {
return cid.Undef, err
}
var msg *types.Message
switch operation {
case api.MsigApprove:
msg, err = mb.Approve(msig, txID, nil)
case api.MsigCancel:
msg, err = mb.Cancel(msig, txID, nil)
default:
return cid.Undef, xerrors.Errorf("Invalid operation for msigApproveOrCancel")
}
if err != nil {
return cid.Undef, err
}
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, msg, nil)
if err != nil {
return cid.Undef, err
}
return smsg.Cid(), nil
}
func (a *MsigAPI) msigApproveOrCancelTxnHash(ctx context.Context, operation api.MsigProposeResponse, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
if msig == address.Undef {
return cid.Undef, xerrors.Errorf("must provide multisig address")
}
@@ -216,3 +264,15 @@ func serializeSwapParams(old address.Address, new address.Address) ([]byte, erro
return enc, nil
}
func serializeRemoveParams(rem address.Address, dec bool) ([]byte, error) {
enc, actErr := actors.SerializeParams(&multisig0.RemoveSignerParams{
Signer: rem,
Decrease: dec,
})
if actErr != nil {
return nil, actErr
}
return enc, nil
}
+68 -39
View File
@@ -5,14 +5,6 @@ import (
"context"
"strconv"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/actors/builtin/verifreg"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/go-state-types/network"
cid "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"go.uber.org/fx"
@@ -22,14 +14,19 @@ import (
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
"github.com/filecoin-project/lotus/chain/actors/builtin/verifreg"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/beacon"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/state"
@@ -42,12 +39,36 @@ import (
"github.com/filecoin-project/lotus/node/modules/dtypes"
)
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)
}
// StateModule provides a default implementation of StateModuleAPI.
// It can be swapped out with another implementation through Dependency
// Injection (for example with a thin RPC client).
type StateModule struct {
fx.In
StateManager *stmgr.StateManager
Chain *store.ChainStore
}
var _ StateModuleAPI = (*StateModule)(nil)
type StateAPI struct {
fx.In
// TODO: the wallet here is only needed because we have the MinerCreateBlock
// API attached to the state API. It probably should live somewhere better
Wallet *wallet.Wallet
Wallet api.WalletAPI
DefWallet wallet.Default
StateModuleAPI
ProofVerifier ffiwrapper.Verifier
StateManager *stmgr.StateManager
@@ -349,27 +370,33 @@ func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.
}, nil
}
func (a *StateAPI) stateForTs(ctx context.Context, ts *types.TipSet) (*state.StateTree, error) {
func stateForTs(ctx context.Context, ts *types.TipSet, cstore *store.ChainStore, smgr *stmgr.StateManager) (*state.StateTree, error) {
if ts == nil {
ts = a.Chain.GetHeaviestTipSet()
ts = cstore.GetHeaviestTipSet()
}
st, _, err := a.StateManager.TipSetState(ctx, ts)
st, _, err := smgr.TipSetState(ctx, ts)
if err != nil {
return nil, err
}
buf := bufbstore.NewBufferedBstore(a.Chain.Blockstore())
buf := bufbstore.NewBufferedBstore(cstore.Blockstore())
cst := cbor.NewCborStore(buf)
return state.LoadStateTree(cst, st)
}
func (a *StateAPI) stateForTs(ctx context.Context, ts *types.TipSet) (*state.StateTree, error) {
return stateForTs(ctx, ts, a.Chain, a.StateManager)
}
func (m *StateModule) stateForTs(ctx context.Context, ts *types.TipSet) (*state.StateTree, error) {
return stateForTs(ctx, ts, m.Chain, m.StateManager)
}
func (a *StateAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
func (m *StateModule) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
state, err := a.stateForTs(ctx, ts)
state, err := m.stateForTs(ctx, ts)
if err != nil {
return nil, xerrors.Errorf("computing tipset state failed: %w", err)
}
@@ -377,26 +404,22 @@ func (a *StateAPI) StateGetActor(ctx context.Context, actor address.Address, tsk
return state.GetActor(actor)
}
func (a *StateAPI) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
func (m *StateModule) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return address.Undef, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
state, err := a.stateForTs(ctx, ts)
if err != nil {
return address.Undef, err
}
return state.LookupID(addr)
return m.StateManager.LookupID(ctx, addr, ts)
}
func (a *StateAPI) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
func (m *StateModule) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return address.Undef, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return a.StateManager.ResolveToKeyAddress(ctx, addr, ts)
return m.StateManager.ResolveToKeyAddress(ctx, addr, ts)
}
func (a *StateAPI) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) {
@@ -453,22 +476,28 @@ func (a *StateAPI) MinerCreateBlock(ctx context.Context, bt *api.BlockTemplate)
return &out, nil
}
func (a *StateAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
ts, recpt, found, err := a.StateManager.WaitForMessage(ctx, msg, confidence)
func (m *StateModule) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence uint64) (*api.MsgLookup, error) {
return stateWaitMsgLimited(ctx, m.StateManager, m.Chain, msg, confidence, stmgr.LookbackNoLimit)
}
func (a *StateAPI) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, lookbackLimit abi.ChainEpoch) (*api.MsgLookup, error) {
return stateWaitMsgLimited(ctx, a.StateManager, a.Chain, msg, confidence, lookbackLimit)
}
func stateWaitMsgLimited(ctx context.Context, smgr *stmgr.StateManager, cstore *store.ChainStore, msg cid.Cid, confidence uint64, lookbackLimit abi.ChainEpoch) (*api.MsgLookup, error) {
ts, recpt, found, err := smgr.WaitForMessage(ctx, msg, confidence, lookbackLimit)
if err != nil {
return nil, err
}
var returndec interface{}
if recpt.ExitCode == 0 && len(recpt.Return) > 0 {
cmsg, err := a.Chain.GetCMessage(msg)
cmsg, err := cstore.GetCMessage(msg)
if err != nil {
return nil, xerrors.Errorf("failed to load message after successful receipt search: %w", err)
}
vmsg := cmsg.VMMessage()
t, err := stmgr.GetReturnType(ctx, a.StateManager, vmsg.To, vmsg.Method, ts)
t, err := stmgr.GetReturnType(ctx, smgr, vmsg.To, vmsg.Method, ts)
if err != nil {
return nil, xerrors.Errorf("failed to get return type: %w", err)
}
@@ -799,17 +828,17 @@ func (a *StateAPI) StateCompute(ctx context.Context, height abi.ChainEpoch, msgs
}, nil
}
func (a *StateAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
func (m *StateModule) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) {
ts, err := m.Chain.GetTipSetFromKey(tsk)
if err != nil {
return types.EmptyInt, 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 types.EmptyInt, xerrors.Errorf("failed to load multisig actor: %w", err)
}
msas, err := multisig.Load(a.Chain.Store(ctx), act)
msas, err := multisig.Load(m.Chain.Store(ctx), act)
if err != nil {
return types.EmptyInt, xerrors.Errorf("failed to load multisig actor state: %w", err)
}
@@ -858,13 +887,13 @@ func (a *StateAPI) MsigGetVestingSchedule(ctx context.Context, addr address.Addr
}, nil
}
func (a *StateAPI) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
startTs, err := a.Chain.GetTipSetFromKey(start)
func (m *StateModule) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
startTs, err := m.Chain.GetTipSetFromKey(start)
if err != nil {
return types.EmptyInt, xerrors.Errorf("loading start tipset %s: %w", start, err)
}
endTs, err := a.Chain.GetTipSetFromKey(end)
endTs, err := m.Chain.GetTipSetFromKey(end)
if err != nil {
return types.EmptyInt, xerrors.Errorf("loading end tipset %s: %w", end, err)
}
@@ -875,12 +904,12 @@ func (a *StateAPI) MsigGetVested(ctx context.Context, addr address.Address, star
return big.Zero(), nil
}
act, err := a.StateManager.LoadActor(ctx, addr, endTs)
act, err := m.StateManager.LoadActor(ctx, addr, endTs)
if err != nil {
return types.EmptyInt, xerrors.Errorf("failed to load multisig actor at end epoch: %w", err)
}
msas, err := multisig.Load(a.Chain.Store(ctx), act)
msas, err := multisig.Load(m.Chain.Store(ctx), act)
if err != nil {
return types.EmptyInt, xerrors.Errorf("failed to load multisig actor state: %w", err)
}

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