Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8bb84acbc5 | ||
|
|
22f49f8946 | ||
|
|
1350079503 | ||
|
|
251374eca7 | ||
|
|
a50a5366b2 | ||
|
|
52800f5dca | ||
|
|
958f169267 | ||
|
|
df6f4a572c | ||
|
|
698b49b7ef | ||
|
|
7e5b1ac272 | ||
|
|
86e30729bf | ||
|
|
7ccb2aabf0 | ||
|
|
811f1304e6 | ||
|
|
6de82364e9 | ||
|
|
d02d4bc275 | ||
|
|
39670df6af | ||
|
|
28823fb8e9 | ||
|
|
ddade32bd3 | ||
|
|
15fe998c68 | ||
|
|
4b38809c0b | ||
|
|
e2fbbdcb15 | ||
|
|
bbc6de94fc | ||
|
|
ea1349205b | ||
|
|
470a565c34 | ||
|
|
04bbeface6 | ||
|
|
8df58064e3 | ||
|
|
01de4cb2ec | ||
|
|
b060569fe9 | ||
|
|
dfd6fbfaa4 | ||
|
|
d3d304bfd7 | ||
|
|
ab4f051b83 | ||
|
|
00a5083146 | ||
|
|
c6ed6a0d65 | ||
|
|
4ad8d85b13 | ||
|
|
465703b618 | ||
|
|
30dd5d9644 | ||
|
|
41bfeb56e2 | ||
|
|
2e7cd024df | ||
|
|
bf619862c3 | ||
|
|
29e54c40be | ||
|
|
308144ee6a | ||
|
|
ce54110228 | ||
|
|
458ea277fc | ||
|
|
58662b79b3 | ||
|
|
7dbc8965be | ||
|
|
2426700821 | ||
|
|
9c6ee802cc | ||
|
|
b61281ba4b | ||
|
|
d5cea9f402 | ||
|
|
ce548c8f95 | ||
|
|
8987defb9d | ||
|
|
1a70dbe37d | ||
|
|
87cd8c6725 | ||
|
|
1eb2d0ae50 | ||
|
|
5fd0bf11ba | ||
|
|
4edebcec2b | ||
|
|
07d0b67628 | ||
|
|
9b4cac9612 | ||
|
|
8232cc8415 | ||
|
|
be74a13736 | ||
|
|
195d96ccc0 | ||
|
|
49155ace62 | ||
|
|
83624a8858 | ||
|
|
96e1dfd8d7 | ||
|
|
61661fb1f0 | ||
|
|
6c08120628 | ||
|
|
8d769f0c07 | ||
|
|
79c5d2c6d2 | ||
|
|
224a96431f | ||
|
|
8001ed3030 | ||
|
|
2855c2bc49 | ||
|
|
65883cbb6b | ||
|
|
443131b214 | ||
|
|
8b648cf77c | ||
|
|
c0961fb63d | ||
|
|
dc4e73c737 | ||
|
|
a6b2180756 | ||
|
|
160f209f6a | ||
|
|
a9d8bc7c45 | ||
|
|
92177b5738 | ||
|
|
4ac2bee81c | ||
|
|
a2e0832a12 | ||
|
|
8fd9b5f235 | ||
|
|
a95e343dee | ||
|
|
c296e1bbca | ||
|
|
ae366972a9 | ||
|
|
b4215e5f46 | ||
|
|
df7ee610cd | ||
|
|
fda8b932ba | ||
|
|
7b4a5fc7ca | ||
|
|
d6c8276c7a | ||
|
|
2b21fdef33 | ||
|
|
6a232e7214 | ||
|
|
7ee6bafd23 | ||
|
|
753d7b71a9 | ||
|
|
bb6a354b62 | ||
|
|
8ae66d6c6a | ||
|
|
2c92157233 | ||
|
|
66d6113340 | ||
|
|
99791a6953 | ||
|
|
b35f9b56b4 | ||
|
|
23470bc38f | ||
|
|
40b2e2d0c1 | ||
|
|
85be11fb75 | ||
|
|
00620aac57 | ||
|
|
32d95fc97a | ||
|
|
a491fc97b9 | ||
|
|
151577f04e | ||
|
|
c463582528 | ||
|
|
7245ac2b69 | ||
|
|
58f13a7d5a | ||
|
|
e7d3b2503e | ||
|
|
ee8b8b8174 | ||
|
|
4fa6afad13 | ||
|
|
a80e98dc05 | ||
|
|
23f5a99117 | ||
|
|
651522cbaa | ||
|
|
388c9afce0 | ||
|
|
9a26896c69 | ||
|
|
2db8b7efa7 | ||
|
|
18e58467f8 | ||
|
|
f3abd1ae82 | ||
|
|
85abca4b16 | ||
|
|
6610a247cf | ||
|
|
f32b3bf99b | ||
|
|
e0dcb0ec49 | ||
|
|
4cca3f19a3 | ||
|
|
ef3987e2ab |
@@ -1,5 +1,65 @@
|
||||
# Lotus changelog
|
||||
|
||||
# 0.10.2 / 2020-10-14
|
||||
|
||||
This is an optional release of Lotus that updates markets to 0.9.1, which fixes an issue affecting deals that were mid-transfer when the node was upgraded to 0.9.0. This release also includes some tweaks to default gas values and minor performance improvements.
|
||||
|
||||
## Changes
|
||||
|
||||
- Use updated stored ask API (https://github.com/filecoin-project/lotus/pull/4384)
|
||||
- tvx: trace puts to blockstore for inclusion in CAR. (https://github.com/filecoin-project/lotus/pull/4278)
|
||||
- Add propose remove (https://github.com/filecoin-project/lotus/pull/4311)
|
||||
- Update to 0.9.1 bugfix release (https://github.com/filecoin-project/lotus/pull/4402)
|
||||
- Update drand endpoints (https://github.com/filecoin-project/lotus/pull/4125)
|
||||
- fix: return true when deadlines changed (https://github.com/filecoin-project/lotus/pull/4403)
|
||||
- sync wait --watch (https://github.com/filecoin-project/lotus/pull/4396)
|
||||
- reduce garbage in blockstore (https://github.com/filecoin-project/lotus/pull/4406)
|
||||
- give the TimeCacheBS tests a bit more time (https://github.com/filecoin-project/lotus/pull/4407)
|
||||
- Improve gas defaults (https://github.com/filecoin-project/lotus/pull/4408)
|
||||
- Change default gas premium to for 10 block inclusion (https://github.com/filecoin-project/lotus/pull/4222)
|
||||
|
||||
# 0.10.1 / 2020-10-14
|
||||
|
||||
This is an optional release of Lotus that updates markets to 0.9.0, which adds the ability to restart data transfers. This release also introduces Ledger support, and various UX improvements.
|
||||
|
||||
## Changes
|
||||
|
||||
- Test the tape upgrade (https://github.com/filecoin-project/lotus/pull/4328)
|
||||
- Adding in Ledger support (https://github.com/filecoin-project/lotus/pull/4290)
|
||||
- Improve the UX for lotus-miner sealing workers (https://github.com/filecoin-project/lotus/pull/4329)
|
||||
- Add a CLI tool for miner's to repay debt (https://github.com/filecoin-project/lotus/pull/4319)
|
||||
- Rename params_testnet to params_mainnet (https://github.com/filecoin-project/lotus/pull/4336)
|
||||
- Use seal-duration in calculating the earliest StartEpoch (https://github.com/filecoin-project/lotus/pull/4337)
|
||||
- Reject deals that are > 7 days in the future in the BasicDealFilter (https://github.com/filecoin-project/lotus/pull/4173)
|
||||
- Add an API endpoint to calculate the exact circulating supply (https://github.com/filecoin-project/lotus/pull/4148)
|
||||
- lotus-pcr: ignore all other market messages (https://github.com/filecoin-project/lotus/pull/4341)
|
||||
- Add message CID to InvocResult (https://github.com/filecoin-project/lotus/pull/4382)
|
||||
- types: Add CID fields to messages in json marshalers (https://github.com/filecoin-project/lotus/pull/4338)
|
||||
- fix(sync state): set state height to actual tipset height (https://github.com/filecoin-project/lotus/pull/4347)
|
||||
- Fix off by one tipset in searchBackForMsg (https://github.com/filecoin-project/lotus/pull/4367)
|
||||
- fix a panic on startup when we fail to load the tipset (https://github.com/filecoin-project/lotus/pull/4376)
|
||||
- Avoid having the same message CID show up in execution traces (https://github.com/filecoin-project/lotus/pull/4350)
|
||||
- feat(markets): update markets 0.9.0 and add data transfer restart (https://github.com/filecoin-project/lotus/pull/4363)
|
||||
|
||||
# 0.10.0 / 2020-10-12
|
||||
|
||||
This is a consensus-breaking hotfix that addresses an issue in specs-actors v2.0.3 that made it impossible to pledge new 32GiB sectors. The change in Lotus is to update to actors v2.1.0, behind the new network version 5.
|
||||
|
||||
## Changes
|
||||
|
||||
- make pledge test pass with the race detector (https://github.com/filecoin-project/lotus/pull/4291)
|
||||
- fix a race in tipset cache usage (https://github.com/filecoin-project/lotus/pull/4282)
|
||||
- add an api for removing multisig signers (https://github.com/filecoin-project/lotus/pull/4274)
|
||||
- cli: Don't output errors to stdout (https://github.com/filecoin-project/lotus/pull/4298)
|
||||
- Fix panic in wallet export when key is not found (https://github.com/filecoin-project/lotus/pull/4299)
|
||||
- Dump the block validation cache whenever we perform an import (https://github.com/filecoin-project/lotus/pull/4287)
|
||||
- Fix two races (https://github.com/filecoin-project/lotus/pull/4301)
|
||||
- sync unmark-bad --all (https://github.com/filecoin-project/lotus/pull/4296)
|
||||
- decode parameters for multisig transactions in inspect (https://github.com/filecoin-project/lotus/pull/4312)
|
||||
- Chain is love (https://github.com/filecoin-project/lotus/pull/4321)
|
||||
- lotus-stats: optmize getting miner power (https://github.com/filecoin-project/lotus/pull/4315)
|
||||
- implement tape upgrade (https://github.com/filecoin-project/lotus/pull/4322)
|
||||
|
||||
# 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.
|
||||
|
||||
+3
-9
@@ -2,9 +2,7 @@
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
For *critical* bugs, please send an email to security@filecoin.org.
|
||||
|
||||
The bug reporting process differs between bugs that are critical and may crash the network, and others that are unlikely to cause problems if malicious parties know about it. For non-critical bugs, please simply file a GitHub [issue](https://github.com/filecoin-project/lotus/issues/new?template=bug_report.md).
|
||||
For *critical* bugs, please consult our Security Policy and Responsible Disclosure Program information at https://github.com/filecoin-project/community/blob/master/SECURITY.md
|
||||
|
||||
Please try to provide a clear description of any bugs reported, along with how to reproduce the bug if possible. More detailed bug reports (especially those with a PoC included) will help us move forward much faster. Additionally, please avoid reporting bugs that already have open issues. Take a moment to search the issue list of the related GitHub repositories before writing up a new report.
|
||||
|
||||
@@ -20,10 +18,6 @@ Here are some examples of bugs we would consider 'critical':
|
||||
|
||||
This is not an exhaustive list, but should provide some idea of what we consider 'critical'.
|
||||
|
||||
## Supported Versions
|
||||
## Reporting a non security bug
|
||||
|
||||
* TODO: This should be defined and set up by Mainnet launch.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| Testnet | :white_check_mark: |
|
||||
For non-critical bugs, please simply file a GitHub [issue](https://github.com/filecoin-project/lotus/issues/new?template=bug_report.md).
|
||||
|
||||
+35
-6
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
@@ -172,6 +173,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)
|
||||
@@ -226,7 +230,9 @@ type FullNode interface {
|
||||
// MethodGroup: Wallet
|
||||
|
||||
// WalletNew creates a new address in the wallet with the given sigType.
|
||||
WalletNew(context.Context, crypto.SigType) (address.Address, error)
|
||||
// Available key types: bls, secp256k1, secp256k1-ledger
|
||||
// Support for numerical types: 1 - secp256k1, 2 - BLS is deprecated
|
||||
WalletNew(context.Context, types.KeyType) (address.Address, error)
|
||||
// WalletHas indicates whether the given address is in the wallet.
|
||||
WalletHas(context.Context, address.Address) (bool, error)
|
||||
// WalletList lists all the addresses in the wallet.
|
||||
@@ -293,6 +299,8 @@ type FullNode interface {
|
||||
// ClientListTransfers returns the status of all ongoing transfers of data
|
||||
ClientListDataTransfers(ctx context.Context) ([]DataTransferChannel, error)
|
||||
ClientDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error)
|
||||
// ClientRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer
|
||||
ClientRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error
|
||||
// ClientRetrieveTryRestartInsufficientFunds attempts to restart stalled retrievals on a given payment channel
|
||||
// which are stuck due to insufficient funds
|
||||
ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error
|
||||
@@ -411,8 +419,12 @@ type FullNode interface {
|
||||
// can issue. It takes the deal size and verified status as parameters.
|
||||
StateDealProviderCollateralBounds(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (DealCollateralBounds, error)
|
||||
|
||||
// StateCirculatingSupply returns the circulating supply of Filecoin at the given tipset
|
||||
StateCirculatingSupply(context.Context, types.TipSetKey) (CirculatingSupply, error)
|
||||
// StateCirculatingSupply returns the exact circulating supply of Filecoin at the given tipset.
|
||||
// This is not used anywhere in the protocol itself, and is only for external consumption.
|
||||
StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error)
|
||||
// StateVMCirculatingSupplyInternal returns an approximation of the circulating supply of Filecoin at the given tipset.
|
||||
// This is the value reported by the runtime interface to actors code.
|
||||
StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (CirculatingSupply, error)
|
||||
// StateNetworkVersion returns the network version at the given tipset
|
||||
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
|
||||
|
||||
@@ -435,12 +447,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
|
||||
@@ -468,6 +489,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
|
||||
|
||||
@@ -709,6 +737,7 @@ type RetrievalOrder struct {
|
||||
}
|
||||
|
||||
type InvocResult struct {
|
||||
MsgCid cid.Cid
|
||||
Msg *types.Message
|
||||
MsgRct *types.MessageReceipt
|
||||
ExecutionTrace types.ExecutionTrace
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ type MsgMeta struct {
|
||||
}
|
||||
|
||||
type WalletAPI interface {
|
||||
WalletNew(context.Context, crypto.SigType) (address.Address, error)
|
||||
WalletNew(context.Context, types.KeyType) (address.Address, error)
|
||||
WalletHas(context.Context, address.Address) (bool, error)
|
||||
WalletList(context.Context) ([]address.Address, error)
|
||||
|
||||
|
||||
+35
-9
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-bitfield"
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
"github.com/filecoin-project/go-fil-markets/piecestore"
|
||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||
@@ -111,6 +112,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"`
|
||||
|
||||
@@ -132,7 +134,7 @@ type FullNodeStruct struct {
|
||||
MinerGetBaseInfo func(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"`
|
||||
MinerCreateBlock func(context.Context, *api.BlockTemplate) (*types.BlockMsg, error) `perm:"write"`
|
||||
|
||||
WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"`
|
||||
WalletNew func(context.Context, types.KeyType) (address.Address, error) `perm:"write"`
|
||||
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
|
||||
WalletList func(context.Context) ([]address.Address, error) `perm:"write"`
|
||||
WalletBalance func(context.Context, address.Address) (types.BigInt, error) `perm:"read"`
|
||||
@@ -164,6 +166,7 @@ type FullNodeStruct struct {
|
||||
ClientDealSize func(ctx context.Context, root cid.Cid) (api.DataSize, error) `perm:"read"`
|
||||
ClientListDataTransfers func(ctx context.Context) ([]api.DataTransferChannel, error) `perm:"write"`
|
||||
ClientDataTransferUpdates func(ctx context.Context) (<-chan api.DataTransferChannel, error) `perm:"write"`
|
||||
ClientRestartDataTransfer func(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error `perm:"write"`
|
||||
ClientRetrieveTryRestartInsufficientFunds func(ctx context.Context, paymentChannel address.Address) error `perm:"write"`
|
||||
|
||||
StateNetworkName func(context.Context) (dtypes.NetworkName, error) `perm:"read"`
|
||||
@@ -209,7 +212,8 @@ type FullNodeStruct struct {
|
||||
StateVerifiedClientStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"`
|
||||
StateVerifiedRegistryRootKey func(ctx context.Context, tsk types.TipSetKey) (address.Address, error) `perm:"read"`
|
||||
StateDealProviderCollateralBounds func(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (api.DealCollateralBounds, error) `perm:"read"`
|
||||
StateCirculatingSupply func(context.Context, types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"`
|
||||
StateCirculatingSupply func(context.Context, types.TipSetKey) (abi.TokenAmount, error) `perm:"read"`
|
||||
StateVMCirculatingSupplyInternal func(context.Context, types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"`
|
||||
StateNetworkVersion func(context.Context, types.TipSetKey) (stnetwork.Version, error) `perm:"read"`
|
||||
|
||||
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||
@@ -217,7 +221,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"`
|
||||
@@ -225,6 +230,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"`
|
||||
|
||||
@@ -381,7 +387,7 @@ type GatewayStruct struct {
|
||||
|
||||
type WalletStruct struct {
|
||||
Internal struct {
|
||||
WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"`
|
||||
WalletNew func(context.Context, types.KeyType) (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"`
|
||||
@@ -548,6 +554,10 @@ func (c *FullNodeStruct) ClientDataTransferUpdates(ctx context.Context) (<-chan
|
||||
return c.Internal.ClientDataTransferUpdates(ctx)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ClientRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error {
|
||||
return c.Internal.ClientRestartDataTransfer(ctx, transferID, otherPeer, isInitiator)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error {
|
||||
return c.Internal.ClientRetrieveTryRestartInsufficientFunds(ctx, paymentChannel)
|
||||
}
|
||||
@@ -628,7 +638,7 @@ func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.Chain
|
||||
return c.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
|
||||
func (c *FullNodeStruct) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) {
|
||||
return c.Internal.WalletNew(ctx, typ)
|
||||
}
|
||||
|
||||
@@ -780,6 +790,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)
|
||||
}
|
||||
@@ -956,10 +970,14 @@ func (c *FullNodeStruct) StateDealProviderCollateralBounds(ctx context.Context,
|
||||
return c.Internal.StateDealProviderCollateralBounds(ctx, size, verified, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
|
||||
func (c *FullNodeStruct) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (abi.TokenAmount, error) {
|
||||
return c.Internal.StateCirculatingSupply(ctx, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
|
||||
return c.Internal.StateVMCirculatingSupplyInternal(ctx, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) {
|
||||
return c.Internal.StateNetworkVersion(ctx, tsk)
|
||||
}
|
||||
@@ -984,8 +1002,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) {
|
||||
@@ -1016,6 +1038,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)
|
||||
}
|
||||
@@ -1450,7 +1476,7 @@ func (g GatewayStruct) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence
|
||||
return g.Internal.StateWaitMsg(ctx, msg, confidence)
|
||||
}
|
||||
|
||||
func (c *WalletStruct) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
|
||||
func (c *WalletStruct) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) {
|
||||
return c.Internal.WalletNew(ctx, typ)
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ func init() {
|
||||
addExample(abi.RegisteredPoStProof_StackedDrgWindow32GiBV1)
|
||||
addExample(abi.ChainEpoch(10101))
|
||||
addExample(crypto.SigTypeBLS)
|
||||
addExample(types.KTBLS)
|
||||
addExample(int64(9))
|
||||
addExample(12.3)
|
||||
addExample(123)
|
||||
|
||||
+1
-2
@@ -26,7 +26,6 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/events"
|
||||
"github.com/filecoin-project/lotus/chain/events/state"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
)
|
||||
|
||||
func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
@@ -58,7 +57,7 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
bm.MineBlocks()
|
||||
|
||||
// send some funds to register the receiver
|
||||
receiverAddr, err := paymentReceiver.WalletNew(ctx, wallet.ActSigType("secp256k1"))
|
||||
receiverAddr, err := paymentReceiver.WalletNew(ctx, types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
|
||||
"github.com/filecoin-project/lotus/node"
|
||||
"github.com/filecoin-project/lotus/node/impl"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTapeFix(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
t.Run("before", func(t *testing.T) { testTapeFix(t, b, blocktime, false) })
|
||||
t.Run("after", func(t *testing.T) { testTapeFix(t, b, blocktime, true) })
|
||||
}
|
||||
func testTapeFix(t *testing.T, b APIBuilder, blocktime time.Duration, after bool) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
upgradeSchedule := stmgr.UpgradeSchedule{{
|
||||
Network: build.ActorUpgradeNetworkVersion,
|
||||
Height: 1,
|
||||
Migration: stmgr.UpgradeActorsV2,
|
||||
}}
|
||||
if after {
|
||||
upgradeSchedule = append(upgradeSchedule, stmgr.Upgrade{
|
||||
Network: network.Version5,
|
||||
Height: 2,
|
||||
})
|
||||
}
|
||||
|
||||
n, sn := b(t, []FullNodeOpts{{Opts: func(_ []TestNode) node.Option {
|
||||
return node.Override(new(stmgr.UpgradeSchedule), upgradeSchedule)
|
||||
}}}, OneMiner)
|
||||
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
|
||||
addrinfo, err := client.NetAddrsListen(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := miner.NetConnect(ctx, addrinfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
build.Clock.Sleep(time.Second)
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
for ctx.Err() == nil {
|
||||
build.Clock.Sleep(blocktime)
|
||||
if err := sn[0].MineOne(ctx, MineNext); err != nil {
|
||||
if ctx.Err() != nil {
|
||||
// context was canceled, ignore the error.
|
||||
return
|
||||
}
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
cancel()
|
||||
<-done
|
||||
}()
|
||||
|
||||
err = miner.PledgeSector(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Wait till done.
|
||||
var sectorNo abi.SectorNumber
|
||||
for {
|
||||
s, err := miner.SectorsList(ctx) // Note - the test builder doesn't import genesis sectors into FSM
|
||||
require.NoError(t, err)
|
||||
fmt.Printf("Sectors: %d\n", len(s))
|
||||
if len(s) == 1 {
|
||||
sectorNo = s[0]
|
||||
break
|
||||
}
|
||||
|
||||
build.Clock.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
fmt.Printf("All sectors is fsm\n")
|
||||
|
||||
// If before, we expect the precommit to fail
|
||||
successState := api.SectorState(sealing.CommitFailed)
|
||||
failureState := api.SectorState(sealing.Proving)
|
||||
if after {
|
||||
// otherwise, it should succeed.
|
||||
successState, failureState = failureState, successState
|
||||
}
|
||||
|
||||
for {
|
||||
st, err := miner.SectorsStatus(ctx, sectorNo, false)
|
||||
require.NoError(t, err)
|
||||
if st.State == successState {
|
||||
break
|
||||
}
|
||||
require.NotEqual(t, failureState, st.State)
|
||||
build.Clock.Sleep(100 * time.Millisecond)
|
||||
fmt.Println("WaitSeal")
|
||||
}
|
||||
|
||||
}
|
||||
+50
-1
@@ -3,8 +3,10 @@ package test
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
|
||||
@@ -12,6 +14,8 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/miner"
|
||||
@@ -74,6 +78,7 @@ func TestApis(t *testing.T, b APIBuilder) {
|
||||
t.Run("testConnectTwo", ts.testConnectTwo)
|
||||
t.Run("testMining", ts.testMining)
|
||||
t.Run("testMiningReal", ts.testMiningReal)
|
||||
t.Run("testSearchMsg", ts.testSearchMsg)
|
||||
}
|
||||
|
||||
func DefaultFullOpts(nFull int) []FullNodeOpts {
|
||||
@@ -96,7 +101,8 @@ 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,
|
||||
// Skip directly to tape height so precommits work.
|
||||
Network: network.Version5,
|
||||
Height: upgradeHeight,
|
||||
Migration: stmgr.UpgradeActorsV2,
|
||||
}})
|
||||
@@ -118,6 +124,49 @@ func (ts *testSuite) testVersion(t *testing.T) {
|
||||
require.Equal(t, v.Version, build.BuildVersion)
|
||||
}
|
||||
|
||||
func (ts *testSuite) testSearchMsg(t *testing.T) {
|
||||
apis, miners := ts.makeNodes(t, OneFull, OneMiner)
|
||||
|
||||
api := apis[0]
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
senderAddr, err := api.WalletDefaultAddress(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
From: senderAddr,
|
||||
To: senderAddr,
|
||||
Value: big.Zero(),
|
||||
}
|
||||
bm := NewBlockMiner(ctx, t, miners[0], 100*time.Millisecond)
|
||||
bm.MineBlocks()
|
||||
defer bm.Stop()
|
||||
|
||||
sm, err := api.MpoolPushMessage(ctx, msg, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
res, err := api.StateWaitMsg(ctx, sm.Cid(), 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if res.Receipt.ExitCode != 0 {
|
||||
t.Fatal("did not successfully send message")
|
||||
}
|
||||
|
||||
searchRes, err := api.StateSearchMsg(ctx, sm.Cid())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if searchRes.TipSet != res.TipSet {
|
||||
t.Fatalf("search ts: %s, different from wait ts: %s", searchRes.TipSet, res.TipSet)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (ts *testSuite) testID(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
|
||||
|
||||
@@ -3,6 +3,7 @@ package test
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"os"
|
||||
"strings"
|
||||
@@ -31,7 +32,9 @@ func init() {
|
||||
}
|
||||
|
||||
func TestPledgeSector(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
|
||||
ctx := context.Background()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
n, sn := b(t, OneFull, OneMiner)
|
||||
client := n[0].FullNode.(*impl.FullNodeAPI)
|
||||
miner := sn[0]
|
||||
@@ -46,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) {
|
||||
|
||||
@@ -62,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
|
||||
}
|
||||
|
||||
|
||||
+1
-10
@@ -35,6 +35,7 @@ var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{
|
||||
"https://api.drand.sh",
|
||||
"https://api2.drand.sh",
|
||||
"https://api3.drand.sh",
|
||||
"https://drand.cloudflare.com",
|
||||
},
|
||||
Relays: []string{
|
||||
"/dnsaddr/api.drand.sh/",
|
||||
@@ -68,16 +69,6 @@ var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{
|
||||
ChainInfoJSON: `{"public_key":"8cda589f88914aa728fd183f383980b35789ce81b274e5daee1f338b77d02566ef4d3fb0098af1f844f10f9c803c1827","period":25,"genesis_time":1595348225,"hash":"e73b7dc3c4f6a236378220c0dd6aa110eb16eed26c11259606e07ee122838d4f","groupHash":"567d4785122a5a3e75a9bc9911d7ea807dd85ff76b78dc4ff06b075712898607"}`,
|
||||
},
|
||||
DrandIncentinet: {
|
||||
Servers: []string{
|
||||
"https://pl-eu.incentinet.drand.sh",
|
||||
"https://pl-us.incentinet.drand.sh",
|
||||
"https://pl-sin.incentinet.drand.sh",
|
||||
},
|
||||
Relays: []string{
|
||||
"/dnsaddr/pl-eu.incentinet.drand.sh/",
|
||||
"/dnsaddr/pl-us.incentinet.drand.sh/",
|
||||
"/dnsaddr/pl-sin.incentinet.drand.sh/",
|
||||
},
|
||||
ChainInfoJSON: `{"public_key":"8cad0c72c606ab27d36ee06de1d5b2db1faf92e447025ca37575ab3a8aac2eaae83192f846fc9e158bc738423753d000","period":30,"genesis_time":1595873820,"hash":"80c8b872c714f4c00fdd3daa465d5514049f457f01f85a4caf68cdcd394ba039","groupHash":"d9406aaed487f7af71851b4399448e311f2328923d454e971536c05398ce2d9b"}`,
|
||||
},
|
||||
}
|
||||
|
||||
+2
-1
@@ -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,
|
||||
|
||||
@@ -30,6 +30,8 @@ const UpgradeRefuelHeight = 130800
|
||||
|
||||
var UpgradeActorsV2Height = abi.ChainEpoch(138720)
|
||||
|
||||
const UpgradeTapeHeight = 140760
|
||||
|
||||
// This signals our tentative epoch for mainnet launch. Can make it later, but not earlier.
|
||||
// Miners, clients, developers, custodians all need time to prepare.
|
||||
// We still have upgrades and state changes to do, but can happen after signaling timing here.
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ func buildType() string {
|
||||
}
|
||||
|
||||
// BuildVersion is the local build version, set by build system
|
||||
const BuildVersion = "0.9.1"
|
||||
const BuildVersion = "0.10.2"
|
||||
|
||||
func UserVersion() string {
|
||||
return BuildVersion + buildType() + CurrentCommit
|
||||
@@ -83,7 +83,7 @@ func VersionForType(nodeType NodeType) (Version, error) {
|
||||
|
||||
// semver versions of the rpc api exposed
|
||||
var (
|
||||
FullAPIVersion = newVer(0, 16, 0)
|
||||
FullAPIVersion = newVer(0, 17, 0)
|
||||
MinerAPIVersion = newVer(0, 15, 0)
|
||||
WorkerAPIVersion = newVer(0, 15, 0)
|
||||
)
|
||||
|
||||
@@ -2,25 +2,28 @@ package builtin
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing"
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/cbor"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
|
||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof"
|
||||
smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing"
|
||||
)
|
||||
|
||||
var SystemActorAddr = builtin0.SystemActorAddr
|
||||
var BurntFundsActorAddr = builtin0.BurntFundsActorAddr
|
||||
var CronActorAddr = builtin0.CronActorAddr
|
||||
var SaftAddress = makeAddress("t0122")
|
||||
var ReserveAddress = makeAddress("t090")
|
||||
var RootVerifierAddress = makeAddress("t080")
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
)
|
||||
|
||||
type DeadlinesDiff map[uint64]*DeadlineDiff
|
||||
type DeadlinesDiff map[uint64]DeadlineDiff
|
||||
|
||||
func DiffDeadlines(pre, cur State) (*DeadlinesDiff, error) {
|
||||
func DiffDeadlines(pre, cur State) (DeadlinesDiff, error) {
|
||||
changed, err := pre.DeadlinesChanged(cur)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -18,11 +18,7 @@ func DiffDeadlines(pre, cur State) (*DeadlinesDiff, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
numDl, err := pre.NumDeadlines()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dlDiff := make(DeadlinesDiff, numDl)
|
||||
dlDiff := make(DeadlinesDiff)
|
||||
if err := pre.ForEachDeadline(func(idx uint64, preDl Deadline) error {
|
||||
curDl, err := cur.LoadDeadline(idx)
|
||||
if err != nil {
|
||||
@@ -39,12 +35,12 @@ func DiffDeadlines(pre, cur State) (*DeadlinesDiff, error) {
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dlDiff, nil
|
||||
return dlDiff, nil
|
||||
}
|
||||
|
||||
type DeadlineDiff map[uint64]*PartitionDiff
|
||||
|
||||
func DiffDeadline(pre, cur Deadline) (*DeadlineDiff, error) {
|
||||
func DiffDeadline(pre, cur Deadline) (DeadlineDiff, error) {
|
||||
changed, err := pre.PartitionsChanged(cur)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -104,7 +100,7 @@ func DiffDeadline(pre, cur Deadline) (*DeadlineDiff, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &partDiff, nil
|
||||
return partDiff, nil
|
||||
}
|
||||
|
||||
type PartitionDiff struct {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package miner
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
@@ -148,6 +149,20 @@ type MinerInfo struct {
|
||||
ConsensusFaultElapsed abi.ChainEpoch
|
||||
}
|
||||
|
||||
func (mi MinerInfo) IsController(addr address.Address) bool {
|
||||
if addr == mi.Owner || addr == mi.Worker {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, ca := range mi.ControlAddresses {
|
||||
if addr == ca {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type SectorExpiration struct {
|
||||
OnTime abi.ChainEpoch
|
||||
|
||||
@@ -182,3 +197,7 @@ type LockedFunds struct {
|
||||
InitialPledgeRequirement abi.TokenAmount
|
||||
PreCommitDeposits abi.TokenAmount
|
||||
}
|
||||
|
||||
func (lf LockedFunds) TotalLockedFunds() abi.TokenAmount {
|
||||
return big.Add(lf.VestingFunds, big.Add(lf.InitialPledgeRequirement, lf.PreCommitDeposits))
|
||||
}
|
||||
|
||||
@@ -47,8 +47,16 @@ type partition0 struct {
|
||||
store adt.Store
|
||||
}
|
||||
|
||||
func (s *state0) AvailableBalance(bal abi.TokenAmount) (abi.TokenAmount, error) {
|
||||
return s.GetAvailableBalance(bal), nil
|
||||
func (s *state0) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmount, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = xerrors.Errorf("failed to get available balance: %w", r)
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
available = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
func (s *state0) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) {
|
||||
@@ -266,7 +274,7 @@ func (s *state0) DeadlinesChanged(other State) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return s.State.Deadlines.Equals(other0.Deadlines), nil
|
||||
return !s.State.Deadlines.Equals(other0.Deadlines), nil
|
||||
}
|
||||
|
||||
func (s *state0) Info() (MinerInfo, error) {
|
||||
@@ -362,7 +370,7 @@ func (d *deadline0) PartitionsChanged(other Deadline) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return d.Deadline.Partitions.Equals(other0.Deadline.Partitions), nil
|
||||
return !d.Deadline.Partitions.Equals(other0.Deadline.Partitions), nil
|
||||
}
|
||||
|
||||
func (d *deadline0) PostSubmissions() (bitfield.BitField, error) {
|
||||
|
||||
@@ -45,8 +45,16 @@ type partition2 struct {
|
||||
store adt.Store
|
||||
}
|
||||
|
||||
func (s *state2) AvailableBalance(bal abi.TokenAmount) (abi.TokenAmount, error) {
|
||||
return s.GetAvailableBalance(bal)
|
||||
func (s *state2) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmount, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = xerrors.Errorf("failed to get available balance: %w", r)
|
||||
available = abi.NewTokenAmount(0)
|
||||
}
|
||||
}()
|
||||
// this panics if the miner doesnt have enough funds to cover their locked pledge
|
||||
available, err = s.GetAvailableBalance(bal)
|
||||
return available, err
|
||||
}
|
||||
|
||||
func (s *state2) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) {
|
||||
@@ -265,7 +273,7 @@ func (s *state2) DeadlinesChanged(other State) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return s.State.Deadlines.Equals(other2.Deadlines), nil
|
||||
return !s.State.Deadlines.Equals(other2.Deadlines), nil
|
||||
}
|
||||
|
||||
func (s *state2) Info() (MinerInfo, error) {
|
||||
@@ -361,7 +369,7 @@ func (d *deadline2) PartitionsChanged(other Deadline) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return d.Deadline.Partitions.Equals(other2.Deadline.Partitions), nil
|
||||
return !d.Deadline.Partitions.Equals(other2.Deadline.Partitions), nil
|
||||
}
|
||||
|
||||
func (d *deadline2) PostSubmissions() (bitfield.BitField, error) {
|
||||
|
||||
@@ -45,6 +45,7 @@ type MessageBuilder interface {
|
||||
|
||||
// this type is the same between v0 and v2
|
||||
type ProposalHashData = multisig2.ProposalHashData
|
||||
type ProposeReturn = multisig2.ProposeReturn
|
||||
|
||||
func txnParams(id uint64, data *ProposalHashData) ([]byte, error) {
|
||||
params := multisig2.TxnIDParams{ID: multisig2.TxnID(id)}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func TestPrintGroupInfo(t *testing.T) {
|
||||
server := build.DrandConfigs[build.DrandIncentinet].Servers[0]
|
||||
server := build.DrandConfigs[build.DrandDevnet].Servers[0]
|
||||
c, err := hclient.New(server, nil, nil)
|
||||
assert.NoError(t, err)
|
||||
cg := c.(interface {
|
||||
|
||||
+24
-2
@@ -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())
|
||||
}
|
||||
|
||||
+2
-2
@@ -155,14 +155,14 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
|
||||
return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err)
|
||||
}
|
||||
|
||||
banker, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
banker, err := w.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
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.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
receievers[r], err = w.WalletNew(context.Background(), types.KTBLS)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to generate receiver key: %w", err)
|
||||
}
|
||||
|
||||
@@ -59,6 +59,8 @@ var MaxUntrustedActorPendingMessages = 10
|
||||
|
||||
var MaxNonceGap = uint64(4)
|
||||
|
||||
var DefaultMaxFee = abi.TokenAmount(types.MustParseFIL("0.007"))
|
||||
|
||||
var (
|
||||
ErrMessageTooBig = errors.New("message too big")
|
||||
|
||||
@@ -183,7 +185,7 @@ func ComputeMinRBF(curPrem abi.TokenAmount) abi.TokenAmount {
|
||||
|
||||
func CapGasFee(msg *types.Message, maxFee abi.TokenAmount) {
|
||||
if maxFee.Equals(big.Zero()) {
|
||||
maxFee = types.NewInt(build.FilecoinPrecision / 10)
|
||||
maxFee = DefaultMaxFee
|
||||
}
|
||||
|
||||
gl := types.NewInt(uint64(msg.GasLimit))
|
||||
@@ -670,6 +672,10 @@ func (mp *MessagePool) addLoaded(m *types.SignedMessage) error {
|
||||
|
||||
curTs := mp.curTs
|
||||
|
||||
if curTs == nil {
|
||||
return xerrors.Errorf("current tipset not loaded")
|
||||
}
|
||||
|
||||
snonce, err := mp.getStateNonce(m.Message.From, curTs)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to look up actor state nonce: %s: %w", err, ErrSoftValidationFailure)
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/lotus/chain/messagepool/gasguess"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/mock"
|
||||
@@ -232,7 +231,7 @@ func TestMessagePool(t *testing.T) {
|
||||
|
||||
a := tma.nextBlock()
|
||||
|
||||
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
sender, err := w.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -273,7 +272,7 @@ func TestMessagePoolMessagesInEachBlock(t *testing.T) {
|
||||
|
||||
a := tma.nextBlock()
|
||||
|
||||
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
sender, err := w.WalletNew(context.Background(), types.KTBLS)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -323,7 +322,7 @@ func TestRevertMessages(t *testing.T) {
|
||||
a := tma.nextBlock()
|
||||
b := tma.nextBlock()
|
||||
|
||||
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
sender, err := w.WalletNew(context.Background(), types.KTBLS)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -386,7 +385,7 @@ func TestPruningSimple(t *testing.T) {
|
||||
a := tma.nextBlock()
|
||||
tma.applyBlock(t, a)
|
||||
|
||||
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
sender, err := w.WalletNew(context.Background(), types.KTBLS)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -433,7 +432,7 @@ func TestLoadLocal(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -443,7 +442,7 @@ func TestLoadLocal(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -505,7 +504,7 @@ func TestClearAll(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -515,7 +514,7 @@ func TestClearAll(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -559,7 +558,7 @@ func TestClearNonLocal(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -569,7 +568,7 @@ func TestClearNonLocal(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -620,7 +619,7 @@ func TestUpdates(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -630,7 +629,7 @@ func TestUpdates(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/lotus/chain/messagepool/gasguess"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/ipfs/go-datastore"
|
||||
@@ -33,7 +33,7 @@ func TestRepubMessages(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -43,7 +43,7 @@ func TestRepubMessages(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
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"
|
||||
"github.com/filecoin-project/lotus/chain/messagepool/gasguess"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@@ -77,7 +76,7 @@ func TestMessageChains(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -87,7 +86,7 @@ func TestMessageChains(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -315,7 +314,7 @@ func TestMessageChainSkipping(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -325,7 +324,7 @@ func TestMessageChainSkipping(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -391,7 +390,7 @@ func TestBasicMessageSelection(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -401,7 +400,7 @@ func TestBasicMessageSelection(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -535,7 +534,7 @@ func TestMessageSelectionTrimming(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -545,7 +544,7 @@ func TestMessageSelectionTrimming(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -598,7 +597,7 @@ func TestPriorityMessageSelection(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -608,7 +607,7 @@ func TestPriorityMessageSelection(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -677,7 +676,7 @@ func TestPriorityMessageSelection2(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -687,7 +686,7 @@ func TestPriorityMessageSelection2(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -746,7 +745,7 @@ func TestPriorityMessageSelection3(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -756,7 +755,7 @@ func TestPriorityMessageSelection3(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -843,7 +842,7 @@ func TestOptimalMessageSelection1(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -853,7 +852,7 @@ func TestOptimalMessageSelection1(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -910,7 +909,7 @@ func TestOptimalMessageSelection2(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -920,7 +919,7 @@ func TestOptimalMessageSelection2(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -994,7 +993,7 @@ func TestOptimalMessageSelection3(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a, err := w.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -1074,7 +1073,7 @@ func testCompetitiveMessageSelection(t *testing.T, rng *rand.Rand, getPremium fu
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a, err := w.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -1344,7 +1343,7 @@ readLoop:
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
||||
a, err := w.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
ds_sync "github.com/ipfs/go-datastore/sync"
|
||||
@@ -47,13 +46,13 @@ func TestMessageSignerSignMessage(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
w, _ := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||
from1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
||||
from1, err := w.WalletNew(ctx, types.KTSecp256k1)
|
||||
require.NoError(t, err)
|
||||
from2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
||||
from2, err := w.WalletNew(ctx, types.KTSecp256k1)
|
||||
require.NoError(t, err)
|
||||
to1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
||||
to1, err := w.WalletNew(ctx, types.KTSecp256k1)
|
||||
require.NoError(t, err)
|
||||
to2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
||||
to2, err := w.WalletNew(ctx, types.KTSecp256k1)
|
||||
require.NoError(t, err)
|
||||
|
||||
type msgSpec struct {
|
||||
|
||||
+4
-2
@@ -61,7 +61,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
|
||||
Rand: store.NewChainRand(sm.cs, ts.Cids()),
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
||||
CircSupplyCalc: sm.GetVMCirculatingSupply,
|
||||
NtwkVersion: sm.GetNtwkVersion,
|
||||
BaseFee: types.NewInt(0),
|
||||
}
|
||||
@@ -113,6 +113,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
|
||||
}
|
||||
|
||||
return &api.InvocResult{
|
||||
MsgCid: msg.Cid(),
|
||||
Msg: msg,
|
||||
MsgRct: &ret.MessageReceipt,
|
||||
ExecutionTrace: ret.ExecutionTrace,
|
||||
@@ -174,7 +175,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
||||
CircSupplyCalc: sm.GetVMCirculatingSupply,
|
||||
NtwkVersion: sm.GetNtwkVersion,
|
||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||
}
|
||||
@@ -228,6 +229,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
|
||||
}
|
||||
|
||||
return &api.InvocResult{
|
||||
MsgCid: msg.Cid(),
|
||||
Msg: msg,
|
||||
MsgRct: &ret.MessageReceipt,
|
||||
ExecutionTrace: ret.ExecutionTrace,
|
||||
|
||||
+108
-47
@@ -79,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,
|
||||
}}
|
||||
|
||||
@@ -165,7 +168,7 @@ func (sm *StateManager) hasExpensiveFork(ctx context.Context, height abi.ChainEp
|
||||
return ok
|
||||
}
|
||||
|
||||
func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address, amt abi.TokenAmount) error {
|
||||
func doTransfer(tree types.StateTree, from, to address.Address, amt abi.TokenAmount, cb func(trace types.ExecutionTrace)) error {
|
||||
fromAct, err := tree.GetActor(from)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get 'from' actor for transfer: %w", err)
|
||||
@@ -198,7 +201,6 @@ func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address,
|
||||
From: from,
|
||||
To: to,
|
||||
Value: amt,
|
||||
Nonce: math.MaxUint64,
|
||||
}
|
||||
fakeRct := &types.MessageReceipt{
|
||||
ExitCode: 0,
|
||||
@@ -206,22 +208,14 @@ func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address,
|
||||
GasUsed: 0,
|
||||
}
|
||||
|
||||
if err := cb(fakeMsg.Cid(), fakeMsg, &vm.ApplyRet{
|
||||
MessageReceipt: *fakeRct,
|
||||
ActorErr: nil,
|
||||
ExecutionTrace: types.ExecutionTrace{
|
||||
Msg: fakeMsg,
|
||||
MsgRct: fakeRct,
|
||||
Error: "",
|
||||
Duration: 0,
|
||||
GasCharges: nil,
|
||||
Subcalls: nil,
|
||||
},
|
||||
Duration: 0,
|
||||
GasCosts: vm.ZeroGasOutputs(),
|
||||
}); err != nil {
|
||||
return xerrors.Errorf("recording transfer: %w", err)
|
||||
}
|
||||
cb(types.ExecutionTrace{
|
||||
Msg: fakeMsg,
|
||||
MsgRct: fakeRct,
|
||||
Error: "",
|
||||
Duration: 0,
|
||||
GasCharges: nil,
|
||||
Subcalls: nil,
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -262,11 +256,6 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
||||
return cid.Undef, xerrors.Errorf("loading state tree failed: %w", err)
|
||||
}
|
||||
|
||||
ReserveAddress, err := address.NewFromString("t090")
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to parse reserve address: %w", err)
|
||||
}
|
||||
|
||||
tree, err := sm.StateTree(root)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
|
||||
@@ -279,6 +268,10 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
||||
}
|
||||
|
||||
var transfers []transfer
|
||||
subcalls := make([]types.ExecutionTrace, 0)
|
||||
transferCb := func(trace types.ExecutionTrace) {
|
||||
subcalls = append(subcalls, trace)
|
||||
}
|
||||
|
||||
// Take all excess funds away, put them into the reserve account
|
||||
err = tree.ForEach(func(addr address.Address, act *types.Actor) error {
|
||||
@@ -292,7 +285,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
||||
if !sysAcc {
|
||||
transfers = append(transfers, transfer{
|
||||
From: addr,
|
||||
To: ReserveAddress,
|
||||
To: builtin.ReserveAddress,
|
||||
Amt: act.Balance,
|
||||
})
|
||||
}
|
||||
@@ -314,11 +307,13 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
||||
available = st.GetAvailableBalance(act.Balance)
|
||||
}
|
||||
|
||||
transfers = append(transfers, transfer{
|
||||
From: addr,
|
||||
To: ReserveAddress,
|
||||
Amt: available,
|
||||
})
|
||||
if !available.IsZero() {
|
||||
transfers = append(transfers, transfer{
|
||||
From: addr,
|
||||
To: builtin.ReserveAddress,
|
||||
Amt: available,
|
||||
})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -328,7 +323,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
||||
|
||||
// Execute transfers from previous step
|
||||
for _, t := range transfers {
|
||||
if err := doTransfer(cb, tree, t.From, t.To, t.Amt); err != nil {
|
||||
if err := doTransfer(tree, t.From, t.To, t.Amt, transferCb); err != nil {
|
||||
return cid.Undef, xerrors.Errorf("transfer %s %s->%s failed: %w", t.Amt, t.From, t.To, err)
|
||||
}
|
||||
}
|
||||
@@ -367,7 +362,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
||||
nbalance := big.Min(prevBalance, AccountCap)
|
||||
if nbalance.Sign() != 0 {
|
||||
transfersBack = append(transfersBack, transfer{
|
||||
From: ReserveAddress,
|
||||
From: builtin.ReserveAddress,
|
||||
To: addr,
|
||||
Amt: nbalance,
|
||||
})
|
||||
@@ -394,7 +389,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
||||
|
||||
mfunds := minerFundsAlloc(power, totalPower)
|
||||
transfersBack = append(transfersBack, transfer{
|
||||
From: ReserveAddress,
|
||||
From: builtin.ReserveAddress,
|
||||
To: minfo.Worker,
|
||||
Amt: mfunds,
|
||||
})
|
||||
@@ -414,7 +409,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
||||
|
||||
if lbsectors.Length() > 0 {
|
||||
transfersBack = append(transfersBack, transfer{
|
||||
From: ReserveAddress,
|
||||
From: builtin.ReserveAddress,
|
||||
To: minfo.Worker,
|
||||
Amt: BaseMinerBalance,
|
||||
})
|
||||
@@ -431,7 +426,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
||||
}
|
||||
|
||||
for _, t := range transfersBack {
|
||||
if err := doTransfer(cb, tree, t.From, t.To, t.Amt); err != nil {
|
||||
if err := doTransfer(tree, t.From, t.To, t.Amt, transferCb); err != nil {
|
||||
return cid.Undef, xerrors.Errorf("transfer %s %s->%s failed: %w", t.Amt, t.From, t.To, err)
|
||||
}
|
||||
}
|
||||
@@ -441,7 +436,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to load burnt funds actor: %w", err)
|
||||
}
|
||||
if err := doTransfer(cb, tree, builtin0.BurntFundsActorAddr, ReserveAddress, burntAct.Balance); err != nil {
|
||||
if err := doTransfer(tree, builtin0.BurntFundsActorAddr, builtin.ReserveAddress, burntAct.Balance, transferCb); err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to unburn funds: %w", err)
|
||||
}
|
||||
|
||||
@@ -457,7 +452,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
||||
}
|
||||
|
||||
difference := types.BigSub(DesiredReimbursementBalance, reimb.Balance)
|
||||
if err := doTransfer(cb, tree, ReserveAddress, reimbAddr, difference); err != nil {
|
||||
if err := doTransfer(tree, builtin.ReserveAddress, reimbAddr, difference, transferCb); err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to top up reimbursement account: %w", err)
|
||||
}
|
||||
|
||||
@@ -476,6 +471,39 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
||||
return cid.Undef, xerrors.Errorf("resultant state tree account balance was not correct: %s", total)
|
||||
}
|
||||
|
||||
if cb != nil {
|
||||
// record the transfer in execution traces
|
||||
|
||||
fakeMsg := &types.Message{
|
||||
From: builtin.SystemActorAddr,
|
||||
To: builtin.SystemActorAddr,
|
||||
Value: big.Zero(),
|
||||
Nonce: uint64(epoch),
|
||||
}
|
||||
fakeRct := &types.MessageReceipt{
|
||||
ExitCode: 0,
|
||||
Return: nil,
|
||||
GasUsed: 0,
|
||||
}
|
||||
|
||||
if err := cb(fakeMsg.Cid(), fakeMsg, &vm.ApplyRet{
|
||||
MessageReceipt: *fakeRct,
|
||||
ActorErr: nil,
|
||||
ExecutionTrace: types.ExecutionTrace{
|
||||
Msg: fakeMsg,
|
||||
MsgRct: fakeRct,
|
||||
Error: "",
|
||||
Duration: 0,
|
||||
GasCharges: nil,
|
||||
Subcalls: subcalls,
|
||||
},
|
||||
Duration: 0,
|
||||
GasCosts: vm.ZeroGasOutputs(),
|
||||
}); err != nil {
|
||||
return cid.Undef, xerrors.Errorf("recording transfers: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return tree.Flush(ctx)
|
||||
}
|
||||
|
||||
@@ -516,12 +544,12 @@ func UpgradeIgnition(ctx context.Context, sm *StateManager, cb ExecCallback, roo
|
||||
return cid.Undef, xerrors.Errorf("resetting genesis msig start epochs: %w", err)
|
||||
}
|
||||
|
||||
err = splitGenesisMultisig(ctx, cb, split1, store, tree, 50)
|
||||
err = splitGenesisMultisig(ctx, cb, split1, store, tree, 50, epoch)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("splitting first msig: %w", err)
|
||||
}
|
||||
|
||||
err = splitGenesisMultisig(ctx, cb, split2, store, tree, 50)
|
||||
err = splitGenesisMultisig(ctx, cb, split2, store, tree, 50, epoch)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("splitting second msig: %w", err)
|
||||
}
|
||||
@@ -542,12 +570,7 @@ func UpgradeRefuel(ctx context.Context, sm *StateManager, cb ExecCallback, root
|
||||
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
|
||||
}
|
||||
|
||||
addr, err := address.NewFromString("t0122")
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("getting address: %w", err)
|
||||
}
|
||||
|
||||
err = resetMultisigVesting(ctx, store, tree, addr, 0, 0, big.Zero())
|
||||
err = resetMultisigVesting(ctx, store, tree, builtin.SaftAddress, 0, 0, big.Zero())
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err)
|
||||
}
|
||||
@@ -652,7 +675,7 @@ func setNetworkName(ctx context.Context, store adt.Store, tree *state.StateTree,
|
||||
return nil
|
||||
}
|
||||
|
||||
func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Address, store adt0.Store, tree *state.StateTree, portions uint64) error {
|
||||
func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Address, store adt0.Store, tree *state.StateTree, portions uint64, epoch abi.ChainEpoch) error {
|
||||
if portions < 1 {
|
||||
return xerrors.Errorf("cannot split into 0 portions")
|
||||
}
|
||||
@@ -721,6 +744,11 @@ func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Add
|
||||
}
|
||||
|
||||
i := uint64(0)
|
||||
subcalls := make([]types.ExecutionTrace, 0, portions)
|
||||
transferCb := func(trace types.ExecutionTrace) {
|
||||
subcalls = append(subcalls, trace)
|
||||
}
|
||||
|
||||
for i < portions {
|
||||
keyAddr, err := makeKeyAddr(addr, i)
|
||||
if err != nil {
|
||||
@@ -737,13 +765,46 @@ func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Add
|
||||
return xerrors.Errorf("setting new msig actor state: %w", err)
|
||||
}
|
||||
|
||||
if err := doTransfer(cb, tree, addr, idAddr, newIbal); err != nil {
|
||||
if err := doTransfer(tree, addr, idAddr, newIbal, transferCb); err != nil {
|
||||
return xerrors.Errorf("transferring split msig balance: %w", err)
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
|
||||
if cb != nil {
|
||||
// record the transfer in execution traces
|
||||
|
||||
fakeMsg := &types.Message{
|
||||
From: builtin.SystemActorAddr,
|
||||
To: addr,
|
||||
Value: big.Zero(),
|
||||
Nonce: uint64(epoch),
|
||||
}
|
||||
fakeRct := &types.MessageReceipt{
|
||||
ExitCode: 0,
|
||||
Return: nil,
|
||||
GasUsed: 0,
|
||||
}
|
||||
|
||||
if err := cb(fakeMsg.Cid(), fakeMsg, &vm.ApplyRet{
|
||||
MessageReceipt: *fakeRct,
|
||||
ActorErr: nil,
|
||||
ExecutionTrace: types.ExecutionTrace{
|
||||
Msg: fakeMsg,
|
||||
MsgRct: fakeRct,
|
||||
Error: "",
|
||||
Duration: 0,
|
||||
GasCharges: nil,
|
||||
Subcalls: subcalls,
|
||||
},
|
||||
Duration: 0,
|
||||
GasCosts: vm.ZeroGasOutputs(),
|
||||
}); err != nil {
|
||||
return xerrors.Errorf("recording transfers: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+108
-29
@@ -7,6 +7,11 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/verifreg"
|
||||
|
||||
_init "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
|
||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
||||
@@ -195,6 +200,7 @@ func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (st c
|
||||
func traceFunc(trace *[]*api.InvocResult) func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
|
||||
return func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
|
||||
ir := &api.InvocResult{
|
||||
MsgCid: mcid,
|
||||
Msg: msg,
|
||||
MsgRct: &ret.MessageReceipt,
|
||||
ExecutionTrace: ret.ExecutionTrace,
|
||||
@@ -229,7 +235,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
||||
CircSupplyCalc: sm.GetVMCirculatingSupply,
|
||||
NtwkVersion: sm.GetNtwkVersion,
|
||||
BaseFee: baseFee,
|
||||
}
|
||||
@@ -242,17 +248,12 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err)
|
||||
}
|
||||
|
||||
runCron := func() error {
|
||||
// TODO: this nonce-getting is a tiny bit ugly
|
||||
ca, err := vmi.StateTree().GetActor(builtin0.SystemActorAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runCron := func(epoch abi.ChainEpoch) error {
|
||||
|
||||
cronMsg := &types.Message{
|
||||
To: builtin0.CronActorAddr,
|
||||
From: builtin0.SystemActorAddr,
|
||||
Nonce: ca.Nonce,
|
||||
Nonce: uint64(epoch),
|
||||
Value: types.NewInt(0),
|
||||
GasFeeCap: types.NewInt(0),
|
||||
GasPremium: types.NewInt(0),
|
||||
@@ -279,7 +280,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
|
||||
for i := parentEpoch; i < epoch; i++ {
|
||||
if i > parentEpoch {
|
||||
// run cron for null rounds if any
|
||||
if err := runCron(); err != nil {
|
||||
if err := runCron(i); err != nil {
|
||||
return cid.Undef, cid.Undef, err
|
||||
}
|
||||
|
||||
@@ -308,7 +309,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
|
||||
}
|
||||
|
||||
var receipts []cbg.CBORMarshaler
|
||||
processedMsgs := map[cid.Cid]bool{}
|
||||
processedMsgs := make(map[cid.Cid]struct{})
|
||||
for _, b := range bms {
|
||||
penalty := types.NewInt(0)
|
||||
gasReward := big.Zero()
|
||||
@@ -332,7 +333,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
|
||||
return cid.Undef, cid.Undef, err
|
||||
}
|
||||
}
|
||||
processedMsgs[m.Cid()] = true
|
||||
processedMsgs[m.Cid()] = struct{}{}
|
||||
}
|
||||
|
||||
params, err := actors.SerializeParams(&reward.AwardBlockRewardParams{
|
||||
@@ -345,15 +346,10 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("failed to serialize award params: %w", err)
|
||||
}
|
||||
|
||||
sysAct, actErr := vmi.StateTree().GetActor(builtin0.SystemActorAddr)
|
||||
if actErr != nil {
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get system actor: %w", actErr)
|
||||
}
|
||||
|
||||
rwMsg := &types.Message{
|
||||
From: builtin0.SystemActorAddr,
|
||||
To: reward.Address,
|
||||
Nonce: sysAct.Nonce,
|
||||
Nonce: uint64(epoch),
|
||||
Value: types.NewInt(0),
|
||||
GasFeeCap: types.NewInt(0),
|
||||
GasPremium: types.NewInt(0),
|
||||
@@ -376,7 +372,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
|
||||
}
|
||||
}
|
||||
|
||||
if err := runCron(); err != nil {
|
||||
if err := runCron(epoch); err != nil {
|
||||
return cid.Cid{}, cid.Cid{}, err
|
||||
}
|
||||
|
||||
@@ -430,12 +426,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, ts *types.TipSet
|
||||
parentEpoch = parent.Height
|
||||
}
|
||||
|
||||
cids := make([]cid.Cid, len(blks))
|
||||
for i, v := range blks {
|
||||
cids[i] = v.Cid()
|
||||
}
|
||||
|
||||
r := store.NewChainRand(sm.cs, cids)
|
||||
r := store.NewChainRand(sm.cs, ts.Cids())
|
||||
|
||||
blkmsgs, err := sm.cs.BlockMsgsForTipset(ts)
|
||||
if err != nil {
|
||||
@@ -733,7 +724,7 @@ func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet
|
||||
}
|
||||
|
||||
if r != nil {
|
||||
return pts, r, foundMsg, nil
|
||||
return cur, r, foundMsg, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1294,7 +1285,16 @@ func GetFilBurnt(ctx context.Context, st *state.StateTree) (abi.TokenAmount, err
|
||||
return burnt.Balance, nil
|
||||
}
|
||||
|
||||
func (sm *StateManager) GetCirculatingSupplyDetailed(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (api.CirculatingSupply, error) {
|
||||
func (sm *StateManager) GetVMCirculatingSupply(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) {
|
||||
cs, err := sm.GetVMCirculatingSupplyDetailed(ctx, height, st)
|
||||
if err != nil {
|
||||
return types.EmptyInt, err
|
||||
}
|
||||
|
||||
return cs.FilCirculating, err
|
||||
}
|
||||
|
||||
func (sm *StateManager) GetVMCirculatingSupplyDetailed(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (api.CirculatingSupply, error) {
|
||||
sm.genesisMsigLk.Lock()
|
||||
defer sm.genesisMsigLk.Unlock()
|
||||
if sm.preIgnitionGenInfos == nil {
|
||||
@@ -1357,12 +1357,91 @@ func (sm *StateManager) GetCirculatingSupplyDetailed(ctx context.Context, height
|
||||
}
|
||||
|
||||
func (sm *StateManager) GetCirculatingSupply(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) {
|
||||
csi, err := sm.GetCirculatingSupplyDetailed(ctx, height, st)
|
||||
circ := big.Zero()
|
||||
unCirc := big.Zero()
|
||||
err := st.ForEach(func(a address.Address, actor *types.Actor) error {
|
||||
switch {
|
||||
case actor.Balance.IsZero():
|
||||
// Do nothing for zero-balance actors
|
||||
break
|
||||
case a == _init.Address ||
|
||||
a == reward.Address ||
|
||||
a == verifreg.Address ||
|
||||
// The power actor itself should never receive funds
|
||||
a == power.Address ||
|
||||
a == builtin.SystemActorAddr ||
|
||||
a == builtin.CronActorAddr ||
|
||||
a == builtin.BurntFundsActorAddr ||
|
||||
a == builtin.SaftAddress ||
|
||||
a == builtin.ReserveAddress:
|
||||
|
||||
unCirc = big.Add(unCirc, actor.Balance)
|
||||
|
||||
case a == market.Address:
|
||||
mst, err := market.Load(sm.cs.Store(ctx), actor)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lb, err := mst.TotalLocked()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
circ = big.Add(circ, big.Sub(actor.Balance, lb))
|
||||
unCirc = big.Add(unCirc, lb)
|
||||
|
||||
case builtin.IsAccountActor(actor.Code) || builtin.IsPaymentChannelActor(actor.Code):
|
||||
circ = big.Add(circ, actor.Balance)
|
||||
|
||||
case builtin.IsStorageMinerActor(actor.Code):
|
||||
mst, err := miner.Load(sm.cs.Store(ctx), actor)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ab, err := mst.AvailableBalance(actor.Balance)
|
||||
|
||||
if err == nil {
|
||||
circ = big.Add(circ, ab)
|
||||
unCirc = big.Add(unCirc, big.Sub(actor.Balance, ab))
|
||||
} else {
|
||||
// Assume any error is because the miner state is "broken" (lower actor balance than locked funds)
|
||||
// In this case, the actor's entire balance is considered "uncirculating"
|
||||
unCirc = big.Add(unCirc, actor.Balance)
|
||||
}
|
||||
|
||||
case builtin.IsMultisigActor(actor.Code):
|
||||
mst, err := multisig.Load(sm.cs.Store(ctx), actor)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lb, err := mst.LockedBalance(height)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ab := big.Sub(actor.Balance, lb)
|
||||
circ = big.Add(circ, big.Max(ab, big.Zero()))
|
||||
unCirc = big.Add(unCirc, big.Min(actor.Balance, lb))
|
||||
default:
|
||||
return xerrors.Errorf("unexpected actor: %s", a)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return big.Zero(), err
|
||||
return types.EmptyInt, err
|
||||
}
|
||||
|
||||
return csi.FilCirculating, nil
|
||||
total := big.Add(circ, unCirc)
|
||||
if !total.Equals(types.TotalFilecoinInt) {
|
||||
return types.EmptyInt, xerrors.Errorf("total filecoin didn't add to expected amount: %s != %s", total, types.TotalFilecoinInt)
|
||||
}
|
||||
|
||||
return circ, nil
|
||||
}
|
||||
|
||||
func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoch) network.Version {
|
||||
|
||||
@@ -383,7 +383,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
||||
CircSupplyCalc: sm.GetVMCirculatingSupply,
|
||||
NtwkVersion: sm.GetNtwkVersion,
|
||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||
}
|
||||
|
||||
+51
-1
@@ -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
|
||||
@@ -446,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 {
|
||||
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/lib/bufbstore"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
"github.com/filecoin-project/lotus/metrics"
|
||||
"github.com/filecoin-project/lotus/node/impl/client"
|
||||
)
|
||||
|
||||
var log = logging.Logger("sub")
|
||||
@@ -44,6 +45,13 @@ var log = logging.Logger("sub")
|
||||
var ErrSoftFailure = errors.New("soft validation failure")
|
||||
var ErrInsufficientPower = errors.New("incoming block's miner does not have minimum power")
|
||||
|
||||
var msgCidPrefix = cid.Prefix{
|
||||
Version: 1,
|
||||
Codec: cid.DagCBOR,
|
||||
MhType: client.DefaultHashFunction,
|
||||
MhLength: 32,
|
||||
}
|
||||
|
||||
func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *chain.Syncer, bs bserv.BlockService, cmgr connmgr.ConnManager) {
|
||||
// Timeout after (block time + propagation delay). This is useless at
|
||||
// this point.
|
||||
@@ -168,6 +176,9 @@ func fetchCids(
|
||||
|
||||
cidIndex := make(map[cid.Cid]int)
|
||||
for i, c := range cids {
|
||||
if c.Prefix() != msgCidPrefix {
|
||||
return fmt.Errorf("invalid msg CID: %s", c)
|
||||
}
|
||||
cidIndex[c] = i
|
||||
}
|
||||
if len(cids) != len(cidIndex) {
|
||||
|
||||
+53
-41
@@ -323,25 +323,35 @@ func (syncer *Syncer) ValidateMsgMeta(fblk *types.FullBlock) error {
|
||||
return xerrors.Errorf("block %s has too many messages (%d)", fblk.Header.Cid(), msgc)
|
||||
}
|
||||
|
||||
// Collect the CIDs of both types of messages separately: BLS and Secpk.
|
||||
var bcids, scids []cid.Cid
|
||||
for _, m := range fblk.BlsMessages {
|
||||
bcids = append(bcids, m.Cid())
|
||||
}
|
||||
|
||||
for _, m := range fblk.SecpkMessages {
|
||||
scids = append(scids, m.Cid())
|
||||
}
|
||||
|
||||
// TODO: IMPORTANT(GARBAGE). These message puts and the msgmeta
|
||||
// computation need to go into the 'temporary' side of the blockstore when
|
||||
// we implement that
|
||||
blockstore := syncer.store.Blockstore()
|
||||
|
||||
bs := cbor.NewCborStore(blockstore)
|
||||
// We use a temporary bstore here to avoid writing intermediate pieces
|
||||
// into the blockstore.
|
||||
blockstore := bstore.NewTemporary()
|
||||
cst := cbor.NewCborStore(blockstore)
|
||||
|
||||
var bcids, scids []cid.Cid
|
||||
|
||||
for _, m := range fblk.BlsMessages {
|
||||
c, err := store.PutMessage(blockstore, m)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("putting bls message to blockstore after msgmeta computation: %w", err)
|
||||
}
|
||||
bcids = append(bcids, c)
|
||||
}
|
||||
|
||||
for _, m := range fblk.SecpkMessages {
|
||||
c, err := store.PutMessage(blockstore, m)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("putting bls message to blockstore after msgmeta computation: %w", err)
|
||||
}
|
||||
scids = append(scids, c)
|
||||
}
|
||||
|
||||
// Compute the root CID of the combined message trie.
|
||||
smroot, err := computeMsgMeta(bs, bcids, scids)
|
||||
smroot, err := computeMsgMeta(cst, bcids, scids)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("validating msgmeta, compute failed: %w", err)
|
||||
}
|
||||
@@ -351,21 +361,8 @@ func (syncer *Syncer) ValidateMsgMeta(fblk *types.FullBlock) error {
|
||||
return xerrors.Errorf("messages in full block did not match msgmeta root in header (%s != %s)", fblk.Header.Messages, smroot)
|
||||
}
|
||||
|
||||
for _, m := range fblk.BlsMessages {
|
||||
_, err := store.PutMessage(blockstore, m)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("putting bls message to blockstore after msgmeta computation: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, m := range fblk.SecpkMessages {
|
||||
_, err := store.PutMessage(blockstore, m)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("putting bls message to blockstore after msgmeta computation: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
// Finally, flush.
|
||||
return vm.Copy(context.TODO(), blockstore, syncer.store.Blockstore(), smroot)
|
||||
}
|
||||
|
||||
func (syncer *Syncer) LocalPeer() peer.ID {
|
||||
@@ -1064,8 +1061,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
|
||||
return err
|
||||
}
|
||||
|
||||
cst := cbor.NewCborStore(syncer.store.Blockstore())
|
||||
st, err := state.LoadStateTree(cst, stateroot)
|
||||
st, err := state.LoadStateTree(syncer.store.Store(ctx), stateroot)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to load base state tree: %w", err)
|
||||
}
|
||||
@@ -1111,21 +1107,28 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
|
||||
return nil
|
||||
}
|
||||
|
||||
store := adt0.WrapStore(ctx, cst)
|
||||
// Validate message arrays in a temporary blockstore.
|
||||
tmpbs := bstore.NewTemporary()
|
||||
tmpstore := adt0.WrapStore(ctx, cbor.NewCborStore(tmpbs))
|
||||
|
||||
bmArr := adt0.MakeEmptyArray(store)
|
||||
bmArr := adt0.MakeEmptyArray(tmpstore)
|
||||
for i, m := range b.BlsMessages {
|
||||
if err := checkMsg(m); err != nil {
|
||||
return xerrors.Errorf("block had invalid bls message at index %d: %w", i, err)
|
||||
}
|
||||
|
||||
c := cbg.CborCid(m.Cid())
|
||||
if err := bmArr.Set(uint64(i), &c); err != nil {
|
||||
c, err := store.PutMessage(tmpbs, m)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to store message %s: %w", m.Cid(), err)
|
||||
}
|
||||
|
||||
k := cbg.CborCid(c)
|
||||
if err := bmArr.Set(uint64(i), &k); err != nil {
|
||||
return xerrors.Errorf("failed to put bls message at index %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
smArr := adt0.MakeEmptyArray(store)
|
||||
smArr := adt0.MakeEmptyArray(tmpstore)
|
||||
for i, m := range b.SecpkMessages {
|
||||
if err := checkMsg(m); err != nil {
|
||||
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
|
||||
@@ -1142,8 +1145,12 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
|
||||
return xerrors.Errorf("secpk message %s has invalid signature: %w", m.Cid(), err)
|
||||
}
|
||||
|
||||
c := cbg.CborCid(m.Cid())
|
||||
if err := smArr.Set(uint64(i), &c); err != nil {
|
||||
c, err := store.PutMessage(tmpbs, m)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to store message %s: %w", m.Cid(), err)
|
||||
}
|
||||
k := cbg.CborCid(c)
|
||||
if err := smArr.Set(uint64(i), &k); err != nil {
|
||||
return xerrors.Errorf("failed to put secpk message at index %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
@@ -1158,7 +1165,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
|
||||
return err
|
||||
}
|
||||
|
||||
mrcid, err := cst.Put(ctx, &types.MsgMeta{
|
||||
mrcid, err := tmpstore.Put(ctx, &types.MsgMeta{
|
||||
BlsMessages: bmroot,
|
||||
SecpkMessages: smroot,
|
||||
})
|
||||
@@ -1170,7 +1177,8 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
|
||||
return fmt.Errorf("messages didnt match message root in header")
|
||||
}
|
||||
|
||||
return nil
|
||||
// Finally, flush.
|
||||
return vm.Copy(ctx, tmpbs, syncer.store.Blockstore(), mrcid)
|
||||
}
|
||||
|
||||
func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig *crypto.Signature, msgs []cid.Cid, pubks [][]byte) error {
|
||||
@@ -1478,7 +1486,7 @@ func (syncer *Syncer) syncFork(ctx context.Context, incoming *types.TipSet, know
|
||||
|
||||
func (syncer *Syncer) syncMessagesAndCheckState(ctx context.Context, headers []*types.TipSet) error {
|
||||
ss := extractSyncState(ctx)
|
||||
ss.SetHeight(0)
|
||||
ss.SetHeight(headers[len(headers)-1].Height())
|
||||
|
||||
return syncer.iterFullTipsets(ctx, headers, func(ctx context.Context, fts *store.FullTipSet) error {
|
||||
log.Debugw("validating tipset", "height", fts.TipSet().Height(), "size", len(fts.TipSet().Cids()))
|
||||
@@ -1726,7 +1734,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 +1748,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
|
||||
|
||||
@@ -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:
|
||||
|
||||
+21
-25
@@ -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
|
||||
}
|
||||
|
||||
@@ -81,5 +81,14 @@ func ParseFIL(s string) (FIL, error) {
|
||||
return FIL{r.Num()}, nil
|
||||
}
|
||||
|
||||
func MustParseFIL(s string) FIL {
|
||||
n, err := ParseFIL(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
var _ encoding.TextMarshaler = (*FIL)(nil)
|
||||
var _ encoding.TextUnmarshaler = (*FIL)(nil)
|
||||
|
||||
+45
-1
@@ -1,7 +1,10 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -9,9 +12,50 @@ var (
|
||||
ErrKeyExists = fmt.Errorf("key already exists")
|
||||
)
|
||||
|
||||
// KeyType defines a type of a key
|
||||
type KeyType string
|
||||
|
||||
func (kt *KeyType) UnmarshalJSON(bb []byte) error {
|
||||
{
|
||||
// first option, try unmarshaling as string
|
||||
var s string
|
||||
err := json.Unmarshal(bb, &s)
|
||||
if err == nil {
|
||||
*kt = KeyType(s)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var b byte
|
||||
err := json.Unmarshal(bb, &b)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not unmarshal KeyType either as string nor integer: %w", err)
|
||||
}
|
||||
bst := crypto.SigType(b)
|
||||
|
||||
switch bst {
|
||||
case crypto.SigTypeBLS:
|
||||
*kt = KTBLS
|
||||
case crypto.SigTypeSecp256k1:
|
||||
*kt = KTSecp256k1
|
||||
default:
|
||||
return fmt.Errorf("unknown sigtype: %d", bst)
|
||||
}
|
||||
log.Warnf("deprecation: integer style 'KeyType' is deprecated, switch to string style")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
KTBLS KeyType = "bls"
|
||||
KTSecp256k1 KeyType = "secp256k1"
|
||||
KTSecp256k1Ledger KeyType = "secp256k1-ledger"
|
||||
)
|
||||
|
||||
// KeyInfo is used for storing keys in KeyStore
|
||||
type KeyInfo struct {
|
||||
Type string
|
||||
Type KeyType
|
||||
PrivateKey []byte
|
||||
}
|
||||
|
||||
|
||||
+16
-1
@@ -2,6 +2,7 @@ package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
@@ -106,6 +107,20 @@ func (m *Message) Cid() cid.Cid {
|
||||
return b.Cid()
|
||||
}
|
||||
|
||||
type mCid struct {
|
||||
*RawMessage
|
||||
CID cid.Cid
|
||||
}
|
||||
|
||||
type RawMessage Message
|
||||
|
||||
func (m *Message) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(&mCid{
|
||||
RawMessage: (*RawMessage)(m),
|
||||
CID: m.Cid(),
|
||||
})
|
||||
}
|
||||
|
||||
func (m *Message) RequiredFunds() BigInt {
|
||||
return BigMul(m.GasFeeCap, NewInt(uint64(m.GasLimit)))
|
||||
}
|
||||
@@ -180,7 +195,7 @@ func (m *Message) ValidForBlockInclusion(minGas int64) error {
|
||||
|
||||
// since prices might vary with time, this is technically semantic validation
|
||||
if m.GasLimit < minGas {
|
||||
return xerrors.New("'GasLimit' field cannot be less than the cost of storing a message on chain")
|
||||
return xerrors.Errorf("'GasLimit' field cannot be less than the cost of storing a message on chain %d < %d", m.GasLimit, minGas)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
)
|
||||
|
||||
@@ -70,3 +73,66 @@ func TestEqualCall(t *testing.T) {
|
||||
require.True(t, m1.EqualCall(m3))
|
||||
require.False(t, m1.EqualCall(m4))
|
||||
}
|
||||
|
||||
func TestMessageJson(t *testing.T) {
|
||||
m := &Message{
|
||||
To: builtin.StoragePowerActorAddr,
|
||||
From: builtin.SystemActorAddr,
|
||||
Nonce: 34,
|
||||
Value: big.Zero(),
|
||||
|
||||
GasLimit: 123,
|
||||
GasFeeCap: big.NewInt(234),
|
||||
GasPremium: big.NewInt(234),
|
||||
|
||||
Method: 6,
|
||||
Params: []byte("hai"),
|
||||
}
|
||||
|
||||
b, err := json.Marshal(m)
|
||||
require.NoError(t, err)
|
||||
|
||||
exp := []byte("{\"Version\":0,\"To\":\"f04\",\"From\":\"f00\",\"Nonce\":34,\"Value\":\"0\",\"GasLimit\":123,\"GasFeeCap\":\"234\",\"GasPremium\":\"234\",\"Method\":6,\"Params\":\"aGFp\",\"CID\":{\"/\":\"bafy2bzaced5rdpz57e64sc7mdwjn3blicglhpialnrph2dlbufhf6iha63dmc\"}}")
|
||||
fmt.Println(string(b))
|
||||
|
||||
require.Equal(t, exp, b)
|
||||
|
||||
var um Message
|
||||
require.NoError(t, json.Unmarshal(b, &um))
|
||||
|
||||
require.EqualValues(t, *m, um)
|
||||
}
|
||||
|
||||
func TestSignedMessageJson(t *testing.T) {
|
||||
m := Message{
|
||||
To: builtin.StoragePowerActorAddr,
|
||||
From: builtin.SystemActorAddr,
|
||||
Nonce: 34,
|
||||
Value: big.Zero(),
|
||||
|
||||
GasLimit: 123,
|
||||
GasFeeCap: big.NewInt(234),
|
||||
GasPremium: big.NewInt(234),
|
||||
|
||||
Method: 6,
|
||||
Params: []byte("hai"),
|
||||
}
|
||||
|
||||
sm := &SignedMessage{
|
||||
Message: m,
|
||||
Signature: crypto.Signature{},
|
||||
}
|
||||
|
||||
b, err := json.Marshal(sm)
|
||||
require.NoError(t, err)
|
||||
|
||||
exp := []byte("{\"Message\":{\"Version\":0,\"To\":\"f04\",\"From\":\"f00\",\"Nonce\":34,\"Value\":\"0\",\"GasLimit\":123,\"GasFeeCap\":\"234\",\"GasPremium\":\"234\",\"Method\":6,\"Params\":\"aGFp\",\"CID\":{\"/\":\"bafy2bzaced5rdpz57e64sc7mdwjn3blicglhpialnrph2dlbufhf6iha63dmc\"}},\"Signature\":{\"Type\":0,\"Data\":null},\"CID\":{\"/\":\"bafy2bzacea5ainifngxj3rygaw2hppnyz2cw72x5pysqty2x6dxmjs5qg2uus\"}}")
|
||||
fmt.Println(string(b))
|
||||
|
||||
require.Equal(t, exp, b)
|
||||
|
||||
var um SignedMessage
|
||||
require.NoError(t, json.Unmarshal(b, &um))
|
||||
|
||||
require.EqualValues(t, *sm, um)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
@@ -62,8 +63,29 @@ func (sm *SignedMessage) Serialize() ([]byte, error) {
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
type smCid struct {
|
||||
*RawSignedMessage
|
||||
CID cid.Cid
|
||||
}
|
||||
|
||||
type RawSignedMessage SignedMessage
|
||||
|
||||
func (sm *SignedMessage) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(&smCid{
|
||||
RawSignedMessage: (*RawSignedMessage)(sm),
|
||||
CID: sm.Cid(),
|
||||
})
|
||||
}
|
||||
|
||||
func (sm *SignedMessage) ChainLength() int {
|
||||
ser, err := sm.Serialize()
|
||||
var ser []byte
|
||||
var err error
|
||||
if sm.Signature.Type == crypto.SigTypeBLS {
|
||||
// BLS chain message length doesn't include signature
|
||||
ser, err = sm.Message.Serialize()
|
||||
} else {
|
||||
ser, err = sm.Serialize()
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@@ -62,7 +61,7 @@ func MakeMessageSigningVectors() []vectors.MessageSigningVector {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
blsk, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
blsk, err := w.WalletNew(context.Background(), types.KTBLS)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -86,7 +85,7 @@ func MakeMessageSigningVectors() []vectors.MessageSigningVector {
|
||||
Signature: &bmsg.Signature,
|
||||
}
|
||||
|
||||
secpk, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
||||
secpk, err := w.WalletNew(context.Background(), types.KTBLS)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
+14
-21
@@ -10,13 +10,17 @@ import (
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
)
|
||||
|
||||
func GenerateKey(typ crypto.SigType) (*Key, error) {
|
||||
pk, err := sigs.Generate(typ)
|
||||
func GenerateKey(typ types.KeyType) (*Key, error) {
|
||||
ctyp := ActSigType(typ)
|
||||
if ctyp == crypto.SigTypeUnknown {
|
||||
return nil, xerrors.Errorf("unknown sig type: %s", typ)
|
||||
}
|
||||
pk, err := sigs.Generate(ctyp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ki := types.KeyInfo{
|
||||
Type: kstoreSigType(typ),
|
||||
Type: typ,
|
||||
PrivateKey: pk,
|
||||
}
|
||||
return NewKey(ki)
|
||||
@@ -41,41 +45,30 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
|
||||
}
|
||||
|
||||
switch k.Type {
|
||||
case KTSecp256k1:
|
||||
case types.KTSecp256k1:
|
||||
k.Address, err = address.NewSecp256k1Address(k.PublicKey)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
|
||||
}
|
||||
case KTBLS:
|
||||
case types.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 nil, xerrors.Errorf("unsupported key type: %s", k.Type)
|
||||
}
|
||||
return k, nil
|
||||
|
||||
}
|
||||
|
||||
func kstoreSigType(typ crypto.SigType) string {
|
||||
func ActSigType(typ types.KeyType) crypto.SigType {
|
||||
switch typ {
|
||||
case crypto.SigTypeBLS:
|
||||
return KTBLS
|
||||
case crypto.SigTypeSecp256k1:
|
||||
return KTSecp256k1
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func ActSigType(typ string) crypto.SigType {
|
||||
switch typ {
|
||||
case KTBLS:
|
||||
case types.KTBLS:
|
||||
return crypto.SigTypeBLS
|
||||
case KTSecp256k1:
|
||||
case types.KTSecp256k1:
|
||||
return crypto.SigTypeSecp256k1
|
||||
default:
|
||||
return 0
|
||||
return crypto.SigTypeUnknown
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
package ledgerwallet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-datastore"
|
||||
"github.com/ipfs/go-datastore/query"
|
||||
logging "github.com/ipfs/go-log"
|
||||
ledgerfil "github.com/whyrusleeping/ledger-filecoin-go"
|
||||
"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"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
var log = logging.Logger("wallet-ledger")
|
||||
|
||||
type LedgerWallet struct {
|
||||
ds datastore.Datastore
|
||||
}
|
||||
|
||||
func NewWallet(ds dtypes.MetadataDS) *LedgerWallet {
|
||||
return &LedgerWallet{ds}
|
||||
}
|
||||
|
||||
type LedgerKeyInfo struct {
|
||||
Address address.Address
|
||||
Path []uint32
|
||||
}
|
||||
|
||||
var _ api.WalletAPI = (*LedgerWallet)(nil)
|
||||
|
||||
func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta api.MsgMeta) (*crypto.Signature, error) {
|
||||
ki, err := lw.getKeyInfo(signer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fl, err := ledgerfil.FindLedgerFilecoinApp()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fl.Close() // nolint:errcheck
|
||||
if meta.Type != api.MTChainMsg {
|
||||
return nil, fmt.Errorf("ledger can only sign chain messages")
|
||||
}
|
||||
|
||||
{
|
||||
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(toSign)
|
||||
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() != toSign")
|
||||
}
|
||||
}
|
||||
|
||||
sig, err := fl.SignSECP256K1(ki.Path, meta.Extra)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &crypto.Signature{
|
||||
Type: crypto.SigTypeSecp256k1,
|
||||
Data: sig.SignatureBytes(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (lw LedgerWallet) getKeyInfo(addr address.Address) (*LedgerKeyInfo, error) {
|
||||
kib, err := lw.ds.Get(keyForAddr(addr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out LedgerKeyInfo
|
||||
if err := json.Unmarshal(kib, &out); err != nil {
|
||||
return nil, xerrors.Errorf("unmarshalling ledger key info: %w", err)
|
||||
}
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func (lw LedgerWallet) WalletDelete(ctx context.Context, k address.Address) error {
|
||||
return lw.ds.Delete(keyForAddr(k))
|
||||
}
|
||||
|
||||
func (lw LedgerWallet) WalletExport(ctx context.Context, k address.Address) (*types.KeyInfo, error) {
|
||||
return nil, fmt.Errorf("cannot export keys from ledger wallets")
|
||||
}
|
||||
|
||||
func (lw LedgerWallet) WalletHas(ctx context.Context, k address.Address) (bool, error) {
|
||||
_, err := lw.ds.Get(keyForAddr(k))
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if err == datastore.ErrNotFound {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
func (lw LedgerWallet) WalletImport(ctx context.Context, kinfo *types.KeyInfo) (address.Address, error) {
|
||||
var ki LedgerKeyInfo
|
||||
if err := json.Unmarshal(kinfo.PrivateKey, &ki); err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
return lw.importKey(ki)
|
||||
}
|
||||
|
||||
func (lw LedgerWallet) importKey(ki LedgerKeyInfo) (address.Address, error) {
|
||||
if ki.Address == address.Undef {
|
||||
return address.Undef, fmt.Errorf("no address given in imported key info")
|
||||
}
|
||||
if len(ki.Path) != filHdPathLen {
|
||||
return address.Undef, fmt.Errorf("bad hd path len: %d, expected: %d", len(ki.Path), filHdPathLen)
|
||||
}
|
||||
bb, err := json.Marshal(ki)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("marshaling key info: %w", err)
|
||||
}
|
||||
|
||||
if err := lw.ds.Put(keyForAddr(ki.Address), bb); err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
return ki.Address, nil
|
||||
}
|
||||
|
||||
func (lw LedgerWallet) WalletList(ctx context.Context) ([]address.Address, error) {
|
||||
res, err := lw.ds.Query(query.Query{Prefix: dsLedgerPrefix})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Close() // nolint:errcheck
|
||||
|
||||
var out []address.Address
|
||||
for {
|
||||
res, ok := res.NextSync()
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
var ki LedgerKeyInfo
|
||||
if err := json.Unmarshal(res.Value, &ki); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, ki.Address)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
const hdHard = 0x80000000
|
||||
|
||||
var filHDBasePath = []uint32{hdHard | 44, hdHard | 461, hdHard, 0}
|
||||
var filHdPathLen = 5
|
||||
|
||||
func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address.Address, error) {
|
||||
if t != types.KTSecp256k1Ledger {
|
||||
return address.Undef, fmt.Errorf("unsupported key type: '%s', only '%s' supported",
|
||||
t, types.KTSecp256k1Ledger)
|
||||
}
|
||||
|
||||
res, err := lw.ds.Query(query.Query{Prefix: dsLedgerPrefix})
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
defer res.Close() // nolint:errcheck
|
||||
|
||||
var maxi int64 = -1
|
||||
for {
|
||||
res, ok := res.NextSync()
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
var ki LedgerKeyInfo
|
||||
if err := json.Unmarshal(res.Value, &ki); err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
if i := ki.Path[filHdPathLen-1]; maxi == -1 || maxi < int64(i) {
|
||||
maxi = int64(i)
|
||||
}
|
||||
}
|
||||
|
||||
fl, err := ledgerfil.FindLedgerFilecoinApp()
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("finding ledger: %w", err)
|
||||
}
|
||||
defer fl.Close() // nolint:errcheck
|
||||
|
||||
path := append(append([]uint32(nil), filHDBasePath...), uint32(maxi+1))
|
||||
_, _, addr, err := fl.GetAddressPubKeySECP256K1(path)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("getting public key from ledger: %w", err)
|
||||
}
|
||||
|
||||
log.Warnf("creating key: %s, accept the key in ledger device", addr)
|
||||
_, _, addr, err = fl.ShowAddressPubKeySECP256K1(path)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("verifying public key with ledger: %w", err)
|
||||
}
|
||||
|
||||
a, err := address.NewFromString(addr)
|
||||
if err != nil {
|
||||
return address.Undef, fmt.Errorf("parsing address: %w", err)
|
||||
}
|
||||
|
||||
var lki LedgerKeyInfo
|
||||
lki.Address = a
|
||||
lki.Path = path
|
||||
|
||||
return lw.importKey(lki)
|
||||
}
|
||||
|
||||
func (lw *LedgerWallet) Get() api.WalletAPI {
|
||||
if lw == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return lw
|
||||
}
|
||||
|
||||
var dsLedgerPrefix = "/ledgerkey/"
|
||||
|
||||
func keyForAddr(addr address.Address) datastore.Key {
|
||||
return datastore.NewKey(dsLedgerPrefix + addr.String())
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package wallet
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.uber.org/fx"
|
||||
"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"
|
||||
ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger"
|
||||
"github.com/filecoin-project/lotus/chain/wallet/remotewallet"
|
||||
)
|
||||
|
||||
type MultiWallet struct {
|
||||
fx.In // "constructed" with fx.In instead of normal constructor
|
||||
|
||||
Local *LocalWallet `optional:"true"`
|
||||
Remote *remotewallet.RemoteWallet `optional:"true"`
|
||||
Ledger *ledgerwallet.LedgerWallet `optional:"true"`
|
||||
}
|
||||
|
||||
type getif interface {
|
||||
api.WalletAPI
|
||||
|
||||
// workaround for the fact that iface(*struct(nil)) != nil
|
||||
Get() api.WalletAPI
|
||||
}
|
||||
|
||||
func firstNonNil(wallets ...getif) api.WalletAPI {
|
||||
for _, w := range wallets {
|
||||
if w.Get() != nil {
|
||||
return w
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func nonNil(wallets ...getif) []api.WalletAPI {
|
||||
var out []api.WalletAPI
|
||||
for _, w := range wallets {
|
||||
if w.Get() == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
out = append(out, w)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (m MultiWallet) find(ctx context.Context, address address.Address, wallets ...getif) (api.WalletAPI, error) {
|
||||
ws := nonNil(wallets...)
|
||||
|
||||
for _, w := range ws {
|
||||
have, err := w.WalletHas(ctx, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if have {
|
||||
return w, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m MultiWallet) WalletNew(ctx context.Context, keyType types.KeyType) (address.Address, error) {
|
||||
var local getif = m.Local
|
||||
if keyType == types.KTSecp256k1Ledger {
|
||||
local = m.Ledger
|
||||
}
|
||||
|
||||
w := firstNonNil(m.Remote, local)
|
||||
if w == nil {
|
||||
return address.Undef, xerrors.Errorf("no wallet backends supporting key type: %s", keyType)
|
||||
}
|
||||
|
||||
return w.WalletNew(ctx, keyType)
|
||||
}
|
||||
|
||||
func (m MultiWallet) WalletHas(ctx context.Context, address address.Address) (bool, error) {
|
||||
w, err := m.find(ctx, address, m.Remote, m.Ledger, m.Local)
|
||||
return w != nil, err
|
||||
}
|
||||
|
||||
func (m MultiWallet) WalletList(ctx context.Context) ([]address.Address, error) {
|
||||
var out []address.Address
|
||||
seen := map[address.Address]struct{}{}
|
||||
|
||||
ws := nonNil(m.Remote, m.Ledger, m.Local)
|
||||
for _, w := range ws {
|
||||
l, err := w.WalletList(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, a := range l {
|
||||
if _, ok := seen[a]; ok {
|
||||
continue
|
||||
}
|
||||
seen[a] = struct{}{}
|
||||
|
||||
out = append(out, a)
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (m MultiWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta api.MsgMeta) (*crypto.Signature, error) {
|
||||
w, err := m.find(ctx, signer, m.Remote, m.Ledger, m.Local)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if w == nil {
|
||||
return nil, xerrors.Errorf("key not found")
|
||||
}
|
||||
|
||||
return w.WalletSign(ctx, signer, toSign, meta)
|
||||
}
|
||||
|
||||
func (m MultiWallet) WalletExport(ctx context.Context, address address.Address) (*types.KeyInfo, error) {
|
||||
w, err := m.find(ctx, address, m.Remote, m.Local)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if w == nil {
|
||||
return nil, xerrors.Errorf("key not found")
|
||||
}
|
||||
|
||||
return w.WalletExport(ctx, address)
|
||||
}
|
||||
|
||||
func (m MultiWallet) WalletImport(ctx context.Context, info *types.KeyInfo) (address.Address, error) {
|
||||
var local getif = m.Local
|
||||
if info.Type == types.KTSecp256k1Ledger {
|
||||
local = m.Ledger
|
||||
}
|
||||
|
||||
w := firstNonNil(m.Remote, local)
|
||||
if w == nil {
|
||||
return address.Undef, xerrors.Errorf("no wallet backends configured")
|
||||
}
|
||||
|
||||
return w.WalletImport(ctx, info)
|
||||
}
|
||||
|
||||
func (m MultiWallet) WalletDelete(ctx context.Context, address address.Address) error {
|
||||
for {
|
||||
w, err := m.find(ctx, address, m.Remote, m.Ledger, m.Local)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if w == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := w.WalletDelete(ctx, address); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var _ api.WalletAPI = MultiWallet{}
|
||||
@@ -40,3 +40,11 @@ func SetupRemoteWallet(info string) func(mctx helpers.MetricsCtx, lc fx.Lifecycl
|
||||
return &RemoteWallet{wapi}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (w *RemoteWallet) Get() api.WalletAPI {
|
||||
if w == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
+28
-3
@@ -26,8 +26,6 @@ const (
|
||||
KNamePrefix = "wallet-"
|
||||
KTrashPrefix = "trash-"
|
||||
KDefault = "default"
|
||||
KTBLS = "bls"
|
||||
KTSecp256k1 = "secp256k1"
|
||||
)
|
||||
|
||||
type LocalWallet struct {
|
||||
@@ -141,6 +139,9 @@ func (w *LocalWallet) WalletExport(ctx context.Context, addr address.Address) (*
|
||||
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
|
||||
}
|
||||
@@ -233,7 +234,7 @@ func (w *LocalWallet) SetDefault(a address.Address) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *LocalWallet) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
|
||||
func (w *LocalWallet) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) {
|
||||
w.lk.Lock()
|
||||
defer w.lk.Unlock()
|
||||
|
||||
@@ -274,6 +275,9 @@ func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) er
|
||||
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)
|
||||
@@ -294,6 +298,14 @@ func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *LocalWallet) Get() api.WalletAPI {
|
||||
if w == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
var _ api.WalletAPI = &LocalWallet{}
|
||||
|
||||
func swapMainnetForTestnetPrefix(addr string) (string, error) {
|
||||
@@ -306,3 +318,16 @@ func swapMainnetForTestnetPrefix(addr string) (string, error) {
|
||||
aChars[0] = prefixRunes[0]
|
||||
return string(aChars), nil
|
||||
}
|
||||
|
||||
type nilDefault struct{}
|
||||
|
||||
func (n nilDefault) GetDefault() (address.Address, error) {
|
||||
return address.Undef, nil
|
||||
}
|
||||
|
||||
func (n nilDefault) SetDefault(a address.Address) error {
|
||||
return xerrors.Errorf("not supported; local wallet disabled")
|
||||
}
|
||||
|
||||
var NilDefault nilDefault
|
||||
var _ Default = NilDefault
|
||||
|
||||
+70
-2
@@ -3,6 +3,7 @@ package cli
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -53,6 +54,7 @@ var chainCmd = &cli.Command{
|
||||
slashConsensusFault,
|
||||
chainGasPriceCmd,
|
||||
chainInspectUsage,
|
||||
chainDecodeCmd,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -521,8 +523,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},
|
||||
@@ -1233,3 +1236,68 @@ var chainGasPriceCmd = &cli.Command{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var chainDecodeCmd = &cli.Command{
|
||||
Name: "decode",
|
||||
Usage: "decode various types",
|
||||
Subcommands: []*cli.Command{
|
||||
chainDecodeParamsCmd,
|
||||
},
|
||||
}
|
||||
|
||||
var chainDecodeParamsCmd = &cli.Command{
|
||||
Name: "params",
|
||||
Usage: "Decode message params",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "tipset",
|
||||
},
|
||||
},
|
||||
ArgsUsage: "[toAddr method hexParams]",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
if cctx.Args().Len() != 3 {
|
||||
return ShowHelp(cctx, fmt.Errorf("incorrect number of arguments"))
|
||||
}
|
||||
|
||||
to, err := address.NewFromString(cctx.Args().First())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parsing toAddr: %w", err)
|
||||
}
|
||||
|
||||
method, err := strconv.ParseInt(cctx.Args().Get(1), 10, 64)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parsing method id: %w", err)
|
||||
}
|
||||
|
||||
params, err := hex.DecodeString(cctx.Args().Get(2))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parsing hex params: %w", err)
|
||||
}
|
||||
|
||||
ts, err := LoadTipSet(ctx, cctx, api)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
act, err := api.StateGetActor(ctx, to, ts.Key())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting actor: %w", err)
|
||||
}
|
||||
|
||||
pstr, err := jsonParams(act.Code, abi.MethodNum(method), params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(pstr)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package cli
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@@ -82,6 +83,7 @@ var clientCmd = &cli.Command{
|
||||
WithCategory("util", clientCarGenCmd),
|
||||
WithCategory("util", clientInfoCmd),
|
||||
WithCategory("util", clientListTransfers),
|
||||
WithCategory("util", clientRestartTransfer),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1326,6 +1328,66 @@ var clientInfoCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var clientRestartTransfer = &cli.Command{
|
||||
Name: "restart-transfer",
|
||||
Usage: "Force restart a stalled data transfer",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "peerid",
|
||||
Usage: "narrow to transfer with specific peer",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "initiator",
|
||||
Usage: "specify only transfers where peer is/is not initiator",
|
||||
Value: true,
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if !cctx.Args().Present() {
|
||||
return cli.ShowCommandHelp(cctx, cctx.Command.Name)
|
||||
}
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
transferUint, err := strconv.ParseUint(cctx.Args().First(), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading transfer ID: %w", err)
|
||||
}
|
||||
transferID := datatransfer.TransferID(transferUint)
|
||||
initiator := cctx.Bool("initiator")
|
||||
var other peer.ID
|
||||
if pidstr := cctx.String("peerid"); pidstr != "" {
|
||||
p, err := peer.Decode(pidstr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
other = p
|
||||
} else {
|
||||
channels, err := api.ClientListDataTransfers(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
found := false
|
||||
for _, channel := range channels {
|
||||
if channel.IsInitiator == initiator && channel.TransferID == transferID {
|
||||
other = channel.OtherPeer
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return errors.New("unable to find matching data transfer")
|
||||
}
|
||||
}
|
||||
|
||||
return api.ClientRestartDataTransfer(ctx, transferID, other, initiator)
|
||||
},
|
||||
}
|
||||
|
||||
var clientListTransfers = &cli.Command{
|
||||
Name: "list-transfers",
|
||||
Usage: "List ongoing data transfers for deals",
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
+123
-5
@@ -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"
|
||||
|
||||
@@ -41,6 +45,7 @@ var multisigCmd = &cli.Command{
|
||||
msigCreateCmd,
|
||||
msigInspectCmd,
|
||||
msigProposeCmd,
|
||||
msigRemoveProposeCmd,
|
||||
msigApproveCmd,
|
||||
msigAddProposeCmd,
|
||||
msigAddApproveCmd,
|
||||
@@ -174,6 +179,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 +213,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 +270,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 +281,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 +438,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 +524,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
|
||||
}
|
||||
@@ -504,6 +544,84 @@ var msigApproveCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var msigRemoveProposeCmd = &cli.Command{
|
||||
Name: "propose-remove",
|
||||
Usage: "Propose to remove a signer",
|
||||
ArgsUsage: "[multisigAddress signer]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "decrease-threshold",
|
||||
Usage: "whether the number of required signers should be decreased",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "from",
|
||||
Usage: "account to send the propose message from",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if cctx.Args().Len() != 2 {
|
||||
return ShowHelp(cctx, fmt.Errorf("must pass multisig address and signer address"))
|
||||
}
|
||||
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
msig, err := address.NewFromString(cctx.Args().Get(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addr, err := address.NewFromString(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var from address.Address
|
||||
if cctx.IsSet("from") {
|
||||
f, err := address.NewFromString(cctx.String("from"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
from = f
|
||||
} else {
|
||||
defaddr, err := api.WalletDefaultAddress(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
from = defaddr
|
||||
}
|
||||
|
||||
msgCid, err := api.MsigRemoveSigner(ctx, msig, from, addr, cctx.Bool("decrease-threshold"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("sent remove proposal in message: ", msgCid)
|
||||
|
||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if wait.Receipt.ExitCode != 0 {
|
||||
return fmt.Errorf("add proposal returned exit %d", wait.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
var ret multisig.ProposeReturn
|
||||
err = ret.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("decoding proposal return: %w", err)
|
||||
}
|
||||
fmt.Printf("TxnID: %d", ret.TxnID)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var msigAddProposeCmd = &cli.Command{
|
||||
Name: "add-propose",
|
||||
Usage: "Propose to add a signer",
|
||||
@@ -1129,7 +1247,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
|
||||
}
|
||||
|
||||
+1
-2
@@ -29,7 +29,6 @@ import (
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/events"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
builder "github.com/filecoin-project/lotus/node/test"
|
||||
)
|
||||
|
||||
@@ -415,7 +414,7 @@ func startTwoNodesOneMiner(ctx context.Context, t *testing.T, blocktime time.Dur
|
||||
bm.MineBlocks()
|
||||
|
||||
// Send some funds to register the receiver
|
||||
receiverAddr, err := paymentReceiver.WalletNew(ctx, wallet.ActSigType("secp256k1"))
|
||||
receiverAddr, err := paymentReceiver.WalletNew(ctx, types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
+27
-10
@@ -1688,7 +1688,14 @@ func parseParamsForMethod(act cid.Cid, method uint64, args []string) ([]byte, er
|
||||
|
||||
var stateCircSupplyCmd = &cli.Command{
|
||||
Name: "circulating-supply",
|
||||
Usage: "Get the current circulating supply of filecoin",
|
||||
Usage: "Get the exact current circulating supply of Filecoin",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "vm-supply",
|
||||
Usage: "calculates the approximation of the circulating supply used internally by the VM (instead of the exact amount)",
|
||||
Value: false,
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
@@ -1703,16 +1710,26 @@ var stateCircSupplyCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
circ, err := api.StateCirculatingSupply(ctx, ts.Key())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if cctx.IsSet("vm-supply") {
|
||||
circ, err := api.StateVMCirculatingSupplyInternal(ctx, ts.Key())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Circulating supply: ", types.FIL(circ.FilCirculating))
|
||||
fmt.Println("Mined: ", types.FIL(circ.FilMined))
|
||||
fmt.Println("Vested: ", types.FIL(circ.FilVested))
|
||||
fmt.Println("Burnt: ", types.FIL(circ.FilBurnt))
|
||||
fmt.Println("Locked: ", types.FIL(circ.FilLocked))
|
||||
fmt.Println("Circulating supply: ", types.FIL(circ.FilCirculating))
|
||||
fmt.Println("Mined: ", types.FIL(circ.FilMined))
|
||||
fmt.Println("Vested: ", types.FIL(circ.FilVested))
|
||||
fmt.Println("Burnt: ", types.FIL(circ.FilBurnt))
|
||||
fmt.Println("Locked: ", types.FIL(circ.FilLocked))
|
||||
} else {
|
||||
circ, err := api.StateCirculatingSupply(ctx, ts.Key())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Exact circulating supply: ", types.FIL(circ))
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
|
||||
+21
-5
@@ -84,6 +84,12 @@ var syncStatusCmd = &cli.Command{
|
||||
var syncWaitCmd = &cli.Command{
|
||||
Name: "wait",
|
||||
Usage: "Wait for sync to be complete",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "watch",
|
||||
Usage: "don't exit after node is synced",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
napi, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
@@ -92,7 +98,7 @@ var syncWaitCmd = &cli.Command{
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
return SyncWait(ctx, napi)
|
||||
return SyncWait(ctx, napi, cctx.Bool("watch"))
|
||||
},
|
||||
}
|
||||
|
||||
@@ -122,8 +128,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 +145,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")
|
||||
}
|
||||
@@ -224,7 +240,7 @@ var syncCheckpointCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
func SyncWait(ctx context.Context, napi api.FullNode) error {
|
||||
func SyncWait(ctx context.Context, napi api.FullNode, watch bool) error {
|
||||
tick := time.Second / 4
|
||||
|
||||
lastLines := 0
|
||||
@@ -301,7 +317,7 @@ func SyncWait(ctx context.Context, napi api.FullNode) error {
|
||||
|
||||
_ = target // todo: maybe print? (creates a bunch of line wrapping issues with most tipsets)
|
||||
|
||||
if time.Now().Unix()-int64(head.MinTimestamp()) < int64(build.BlockDelaySecs) {
|
||||
if !watch && time.Now().Unix()-int64(head.MinTimestamp()) < int64(build.BlockDelaySecs) {
|
||||
fmt.Println("\nDone!")
|
||||
return nil
|
||||
}
|
||||
|
||||
+3
-4
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
types "github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
"github.com/filecoin-project/lotus/lib/tablewriter"
|
||||
)
|
||||
|
||||
@@ -55,7 +54,7 @@ var walletNew = &cli.Command{
|
||||
t = "secp256k1"
|
||||
}
|
||||
|
||||
nk, err := api.WalletNew(ctx, wallet.ActSigType(t))
|
||||
nk, err := api.WalletNew(ctx, types.KeyType(t))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -329,9 +328,9 @@ var walletImport = &cli.Command{
|
||||
ki.PrivateKey = gk.PrivateKey
|
||||
switch gk.SigType {
|
||||
case 1:
|
||||
ki.Type = wallet.KTSecp256k1
|
||||
ki.Type = types.KTSecp256k1
|
||||
case 2:
|
||||
ki.Type = wallet.KTBLS
|
||||
ki.Type = types.KTBLS
|
||||
default:
|
||||
return fmt.Errorf("unrecognized key type: %d", gk.SigType)
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
@@ -61,7 +59,7 @@ var runCmd = &cli.Command{
|
||||
func sendSmallFundsTxs(ctx context.Context, api api.FullNode, from address.Address, rate int) error {
|
||||
var sendSet []address.Address
|
||||
for i := 0; i < 20; i++ {
|
||||
naddr, err := api.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
||||
naddr, err := api.WalletNew(ctx, types.KTSecp256k1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ limit 1
|
||||
}
|
||||
|
||||
func (s *Syncer) storeCirculatingSupply(ctx context.Context, tipset *types.TipSet) error {
|
||||
supply, err := s.node.StateCirculatingSupply(ctx, tipset.Key())
|
||||
supply, err := s.node.StateVMCirculatingSupplyInternal(ctx, tipset.Key())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"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"
|
||||
)
|
||||
@@ -53,7 +52,7 @@ func TestEndToEnd(t *testing.T) {
|
||||
fmt.Println(balance)
|
||||
|
||||
// Create a wallet on the lite node
|
||||
liteWalletAddr, err := lite.WalletNew(ctx, wallet.ActSigType("secp256k1"))
|
||||
liteWalletAddr, err := lite.WalletNew(ctx, types.KTSecp256k1)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Send some funds from the full node to the lite node
|
||||
@@ -77,7 +76,7 @@ func TestEndToEnd(t *testing.T) {
|
||||
// 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"))
|
||||
addr, err := lite.WalletNew(ctx, types.KTSecp256k1)
|
||||
require.NoError(t, err)
|
||||
|
||||
walletAddrs = append(walletAddrs, addr)
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
@@ -30,12 +30,12 @@ func main() {
|
||||
return err
|
||||
}
|
||||
|
||||
var kt crypto.SigType
|
||||
var kt types.KeyType
|
||||
switch cctx.String("type") {
|
||||
case "bls":
|
||||
kt = crypto.SigTypeBLS
|
||||
kt = types.KTBLS
|
||||
case "secp256k1":
|
||||
kt = crypto.SigTypeSecp256k1
|
||||
kt = types.KTSecp256k1
|
||||
default:
|
||||
return fmt.Errorf("unrecognized key type: %q", cctx.String("type"))
|
||||
}
|
||||
|
||||
@@ -884,6 +884,8 @@ func (r *refunder) processTipsetStorageMarketActor(ctx context.Context, tipset *
|
||||
}
|
||||
|
||||
refundValue = types.BigMul(types.NewInt(uint64(recp.GasUsed)), tipset.Blocks()[0].ParentBaseFee)
|
||||
default:
|
||||
return false, messageMethod, types.NewInt(0), nil
|
||||
}
|
||||
|
||||
return true, messageMethod, refundValue, nil
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/lotus/extern/sector-storage/zerocomm"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
|
||||
@@ -93,7 +92,7 @@ func PreSeal(maddr address.Address, spt abi.RegisteredSealProof, offset abi.Sect
|
||||
return nil, nil, err
|
||||
}
|
||||
} else {
|
||||
minerAddr, err = wallet.GenerateKey(crypto.SigTypeBLS)
|
||||
minerAddr, err = wallet.GenerateKey(types.KTBLS)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@@ -372,7 +372,7 @@ var chainPledgeCmd = &cli.Command{
|
||||
pledgeCollateral = c
|
||||
}
|
||||
|
||||
circ, err := sm.GetCirculatingSupplyDetailed(ctx, abi.ChainEpoch(epoch), state)
|
||||
circ, err := sm.GetVMCirculatingSupplyDetailed(ctx, abi.ChainEpoch(epoch), state)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+10
-10
@@ -32,10 +32,10 @@ import (
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
)
|
||||
|
||||
var validTypes = []string{wallet.KTBLS, wallet.KTSecp256k1, lp2p.KTLibp2pHost}
|
||||
var validTypes = []types.KeyType{types.KTBLS, types.KTSecp256k1, lp2p.KTLibp2pHost}
|
||||
|
||||
type keyInfoOutput struct {
|
||||
Type string
|
||||
Type types.KeyType
|
||||
Address string
|
||||
PublicKey string
|
||||
}
|
||||
@@ -86,7 +86,7 @@ var keyinfoVerifyCmd = &cli.Command{
|
||||
return xerrors.Errorf("decoding key: '%s': %w", fileName, err)
|
||||
}
|
||||
|
||||
if string(name) != keyInfo.Type {
|
||||
if types.KeyType(name) != keyInfo.Type {
|
||||
return fmt.Errorf("%s of type %s is incorrect", fileName, keyInfo.Type)
|
||||
}
|
||||
case modules.KTJwtHmacSecret:
|
||||
@@ -98,7 +98,7 @@ var keyinfoVerifyCmd = &cli.Command{
|
||||
if string(name) != modules.JWTSecretName {
|
||||
return fmt.Errorf("%s of type %s is incorrect", fileName, keyInfo.Type)
|
||||
}
|
||||
case wallet.KTSecp256k1, wallet.KTBLS:
|
||||
case types.KTSecp256k1, types.KTBLS:
|
||||
keystore := wallet.NewMemKeyStore()
|
||||
w, err := wallet.NewWallet(keystore)
|
||||
if err != nil {
|
||||
@@ -214,7 +214,7 @@ var keyinfoImportCmd = &cli.Command{
|
||||
fmt.Printf("%s\n", peerid.String())
|
||||
|
||||
break
|
||||
case wallet.KTSecp256k1, wallet.KTBLS:
|
||||
case types.KTSecp256k1, types.KTBLS:
|
||||
w, err := wallet.NewWallet(keystore)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -317,7 +317,7 @@ var keyinfoInfoCmd = &cli.Command{
|
||||
kio.PublicKey = base64.StdEncoding.EncodeToString(pkBytes)
|
||||
|
||||
break
|
||||
case wallet.KTSecp256k1, wallet.KTBLS:
|
||||
case types.KTSecp256k1, types.KTBLS:
|
||||
kio.Type = keyInfo.Type
|
||||
|
||||
key, err := wallet.NewKey(keyInfo)
|
||||
@@ -366,7 +366,7 @@ var keyinfoNewCmd = &cli.Command{
|
||||
return fmt.Errorf("please specify a type to generate")
|
||||
}
|
||||
|
||||
keyType := cctx.Args().First()
|
||||
keyType := types.KeyType(cctx.Args().First())
|
||||
flagOutput := cctx.String("output")
|
||||
|
||||
if i := SliceIndex(len(validTypes), func(i int) bool {
|
||||
@@ -404,8 +404,8 @@ var keyinfoNewCmd = &cli.Command{
|
||||
keyInfo = ki
|
||||
|
||||
break
|
||||
case wallet.KTSecp256k1, wallet.KTBLS:
|
||||
key, err := wallet.GenerateKey(wallet.ActSigType(keyType))
|
||||
case types.KTSecp256k1, types.KTBLS:
|
||||
key, err := wallet.GenerateKey(keyType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -418,7 +418,7 @@ var keyinfoNewCmd = &cli.Command{
|
||||
|
||||
filename := flagOutput
|
||||
filename = strings.ReplaceAll(filename, "<addr>", keyAddr)
|
||||
filename = strings.ReplaceAll(filename, "<type>", keyType)
|
||||
filename = strings.ReplaceAll(filename, "<type>", string(keyType))
|
||||
|
||||
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/urfave/cli/v2"
|
||||
ledgerfil "github.com/whyrusleeping/ledger-filecoin-go"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
)
|
||||
|
||||
var ledgerCmd = &cli.Command{
|
||||
Name: "ledger",
|
||||
Usage: "Ledger interactions",
|
||||
Flags: []cli.Flag{},
|
||||
Subcommands: []*cli.Command{
|
||||
ledgerListAddressesCmd,
|
||||
ledgerKeyInfoCmd,
|
||||
ledgerSignTestCmd,
|
||||
},
|
||||
}
|
||||
|
||||
const hdHard = 0x80000000
|
||||
|
||||
var ledgerListAddressesCmd = &cli.Command{
|
||||
Name: "list",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "print-balances",
|
||||
Usage: "print balances",
|
||||
Aliases: []string{"b"},
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
var api api.FullNode
|
||||
if cctx.Bool("print-balances") {
|
||||
a, closer, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
api = a
|
||||
|
||||
defer closer()
|
||||
}
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
fl, err := ledgerfil.FindLedgerFilecoinApp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
end := 20
|
||||
for i := 0; i < end; i++ {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := []uint32{hdHard | 44, hdHard | 461, hdHard, 0, uint32(i)}
|
||||
pubk, err := fl.GetPublicKeySECP256K1(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addr, err := address.NewSecp256k1Address(pubk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cctx.Bool("print-balances") && api != nil { // api check makes linter happier
|
||||
b, err := api.WalletBalance(ctx, addr)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting balance: %w", err)
|
||||
}
|
||||
if !b.IsZero() {
|
||||
end = i + 21 // BIP32 spec, stop after 20 empty addresses
|
||||
}
|
||||
|
||||
fmt.Printf("%s %s %s\n", addr, printHDPath(p), types.FIL(b))
|
||||
} else {
|
||||
fmt.Printf("%s %s\n", addr, printHDPath(p))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func parseHDPath(s string) ([]uint32, error) {
|
||||
parts := strings.Split(s, "/")
|
||||
if parts[0] != "m" {
|
||||
return nil, fmt.Errorf("expected HD path to start with 'm'")
|
||||
}
|
||||
|
||||
var out []uint32
|
||||
for _, p := range parts[1:] {
|
||||
var hard bool
|
||||
if strings.HasSuffix(p, "'") {
|
||||
p = p[:len(p)-1]
|
||||
hard = true
|
||||
}
|
||||
|
||||
v, err := strconv.ParseUint(p, 10, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if v >= hdHard {
|
||||
return nil, fmt.Errorf("path element %s too large", p)
|
||||
}
|
||||
|
||||
if hard {
|
||||
v += hdHard
|
||||
}
|
||||
out = append(out, uint32(v))
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func printHDPath(pth []uint32) string {
|
||||
s := "m"
|
||||
for _, p := range pth {
|
||||
s += "/"
|
||||
|
||||
hard := p&hdHard != 0
|
||||
p &^= hdHard // remove hdHard bit
|
||||
|
||||
s += fmt.Sprint(p)
|
||||
if hard {
|
||||
s += "'"
|
||||
}
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
var ledgerKeyInfoCmd = &cli.Command{
|
||||
Name: "key-info",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
Aliases: []string{"v"},
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if !cctx.Args().Present() {
|
||||
return cli.ShowCommandHelp(cctx, cctx.Command.Name)
|
||||
}
|
||||
|
||||
fl, err := ledgerfil.FindLedgerFilecoinApp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p, err := parseHDPath(cctx.Args().First())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pubk, _, addr, err := fl.GetAddressPubKeySECP256K1(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cctx.Bool("verbose") {
|
||||
fmt.Println(addr)
|
||||
fmt.Println(pubk)
|
||||
}
|
||||
|
||||
a, err := address.NewFromString(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var pd ledgerwallet.LedgerKeyInfo
|
||||
pd.Address = a
|
||||
pd.Path = p
|
||||
|
||||
b, err := json.Marshal(pd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var ki types.KeyInfo
|
||||
ki.Type = types.KTSecp256k1Ledger
|
||||
ki.PrivateKey = b
|
||||
|
||||
out, err := json.Marshal(ki)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(string(out))
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var ledgerSignTestCmd = &cli.Command{
|
||||
Name: "sign",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if !cctx.Args().Present() {
|
||||
return cli.ShowCommandHelp(cctx, cctx.Command.Name)
|
||||
}
|
||||
|
||||
fl, err := ledgerfil.FindLedgerFilecoinApp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p, err := parseHDPath(cctx.Args().First())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addr, err := address.NewFromString("f1xc3hws5n6y5m3m44gzb3gyjzhups6wzmhe663ji")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m := &types.Message{
|
||||
To: addr,
|
||||
From: addr,
|
||||
}
|
||||
|
||||
b, err := m.ToStorageBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sig, err := fl.SignSECP256K1(p, b.RawData())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(sig.SignatureBytes())
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -41,6 +41,7 @@ func main() {
|
||||
syncCmd,
|
||||
stateTreePruneCmd,
|
||||
datastoreCmd,
|
||||
ledgerCmd,
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
|
||||
@@ -5,6 +5,11 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/filecoin-project/lotus/api/apibstore"
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
|
||||
@@ -34,6 +39,7 @@ var actorCmd = &cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
actorSetAddrsCmd,
|
||||
actorWithdrawCmd,
|
||||
actorRepayDebtCmd,
|
||||
actorSetPeeridCmd,
|
||||
actorSetOwnerCmd,
|
||||
actorControl,
|
||||
@@ -254,6 +260,105 @@ var actorWithdrawCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var actorRepayDebtCmd = &cli.Command{
|
||||
Name: "repay-debt",
|
||||
Usage: "pay down a miner's debt",
|
||||
ArgsUsage: "[amount (FIL)]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "from",
|
||||
Usage: "optionally specify the account to send funds from",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
|
||||
api, acloser, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer acloser()
|
||||
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
maddr, err := nodeApi.ActorAddress(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var amount abi.TokenAmount
|
||||
if cctx.Args().Present() {
|
||||
f, err := types.ParseFIL(cctx.Args().First())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parsing 'amount' argument: %w", err)
|
||||
}
|
||||
|
||||
amount = abi.TokenAmount(f)
|
||||
} else {
|
||||
mact, err := api.StateGetActor(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
store := adt.WrapStore(ctx, cbor.NewCborStore(apibstore.NewAPIBlockstore(api)))
|
||||
|
||||
mst, err := miner.Load(store, mact)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
amount, err = mst.FeeDebt()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fromAddr := mi.Worker
|
||||
if from := cctx.String("from"); from != "" {
|
||||
addr, err := address.NewFromString(from)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fromAddr = addr
|
||||
}
|
||||
|
||||
fromId, err := api.StateLookupID(ctx, fromAddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !mi.IsController(fromId) {
|
||||
return xerrors.Errorf("sender isn't a controller of miner: %s", fromId)
|
||||
}
|
||||
|
||||
smsg, err := api.MpoolPushMessage(ctx, &types.Message{
|
||||
To: maddr,
|
||||
From: fromId,
|
||||
Value: amount,
|
||||
Method: builtin2.MethodsMiner.RepayDebt,
|
||||
Params: nil,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Sent repay debt message %s\n", smsg.Cid())
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var actorControl = &cli.Command{
|
||||
Name: "control",
|
||||
Usage: "Manage control addresses",
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
cborutil "github.com/filecoin-project/go-cbor-util"
|
||||
paramfetch "github.com/filecoin-project/go-paramfetch"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
crypto2 "github.com/filecoin-project/go-state-types/crypto"
|
||||
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"
|
||||
@@ -156,7 +155,7 @@ var initCmd = &cli.Command{
|
||||
log.Info("Checking full node sync status")
|
||||
|
||||
if !cctx.Bool("genesis-miner") && !cctx.Bool("nosync") {
|
||||
if err := lcli.SyncWait(ctx, api); err != nil {
|
||||
if err := lcli.SyncWait(ctx, api, false); err != nil {
|
||||
return xerrors.Errorf("sync wait: %w", err)
|
||||
}
|
||||
}
|
||||
@@ -624,7 +623,7 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID,
|
||||
if cctx.String("worker") != "" {
|
||||
worker, err = address.NewFromString(cctx.String("worker"))
|
||||
} else if cctx.Bool("create-worker-key") { // TODO: Do we need to force this if owner is Secpk?
|
||||
worker, err = api.WalletNew(ctx, crypto2.SigTypeBLS)
|
||||
worker, err = api.WalletNew(ctx, types.KTBLS)
|
||||
}
|
||||
// TODO: Transfer some initial funds to worker
|
||||
if err != nil {
|
||||
|
||||
@@ -72,7 +72,7 @@ var initRestoreCmd = &cli.Command{
|
||||
}
|
||||
|
||||
if !cctx.Bool("nosync") {
|
||||
if err := lcli.SyncWait(ctx, api); err != nil {
|
||||
if err := lcli.SyncWait(ctx, api, false); err != nil {
|
||||
return xerrors.Errorf("sync wait: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ var runCmd = &cli.Command{
|
||||
log.Info("Checking full node sync status")
|
||||
|
||||
if !cctx.Bool("nosync") {
|
||||
if err := lcli.SyncWait(ctx, nodeApi); err != nil {
|
||||
if err := lcli.SyncWait(ctx, nodeApi, false); err != nil {
|
||||
return xerrors.Errorf("sync wait: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,8 @@ var sealingWorkersCmd = &cli.Command{
|
||||
cpuBars := int(stat.CpuUse * barCols / stat.Info.Resources.CPUs)
|
||||
cpuBar := strings.Repeat("|", cpuBars) + strings.Repeat(" ", int(barCols)-cpuBars)
|
||||
|
||||
fmt.Printf("\tCPU: [%s] %d core(s) in use\n", color.GreenString(cpuBar), stat.CpuUse)
|
||||
fmt.Printf("\tCPU: [%s] %d/%d core(s) in use\n",
|
||||
color.GreenString(cpuBar), stat.CpuUse, stat.Info.Resources.CPUs)
|
||||
|
||||
ramBarsRes := int(stat.Info.Resources.MemReserved * barCols / stat.Info.Resources.MemPhysical)
|
||||
ramBarsUsed := int(stat.MemUsedMin * barCols / stat.Info.Resources.MemPhysical)
|
||||
|
||||
@@ -19,13 +19,8 @@ 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)
|
||||
func (c *LoggedWallet) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) {
|
||||
log.Infow("WalletNew", "type", typ)
|
||||
|
||||
return c.under.WalletNew(ctx, typ)
|
||||
}
|
||||
|
||||
@@ -11,8 +11,11 @@ import (
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/filecoin-project/go-jsonrpc"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/lotus/lib/lotuslog"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
@@ -60,6 +63,10 @@ var runCmd = &cli.Command{
|
||||
Usage: "host address and port the wallet api will listen on",
|
||||
Value: "0.0.0.0:1777",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "ledger",
|
||||
Usage: "use a ledger device instead of an on-disk wallet",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
log.Info("Starting lotus wallet")
|
||||
@@ -94,11 +101,24 @@ var runCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
w, err := wallet.NewWallet(ks)
|
||||
lw, err := wallet.NewWallet(ks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var w api.WalletAPI = lw
|
||||
if cctx.Bool("ledger") {
|
||||
ds, err := lr.Datastore("/metadata")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w = wallet.MultiWallet{
|
||||
Local: lw,
|
||||
Ledger: ledgerwallet.NewWallet(ds),
|
||||
}
|
||||
}
|
||||
|
||||
address := cctx.String("listen")
|
||||
mux := mux.NewRouter()
|
||||
|
||||
|
||||
+5
-1
@@ -436,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
|
||||
@@ -455,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
@@ -135,7 +135,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
|
||||
}
|
||||
|
||||
// get the circulating supply before the message was executed.
|
||||
circSupplyDetail, err := fapi.StateCirculatingSupply(ctx, incTs.Key())
|
||||
circSupplyDetail, err := fapi.StateVMCirculatingSupplyInternal(ctx, incTs.Key())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed while fetching circulating supply: %w", err)
|
||||
}
|
||||
|
||||
+12
-3
@@ -87,7 +87,7 @@ type proxyingBlockstore struct {
|
||||
ctx context.Context
|
||||
api api.FullNode
|
||||
|
||||
lk sync.RWMutex
|
||||
lk sync.Mutex
|
||||
tracing bool
|
||||
traced map[cid.Cid]struct{}
|
||||
|
||||
@@ -113,11 +113,11 @@ func (pb *proxyingBlockstore) FinishTracing() map[cid.Cid]struct{} {
|
||||
}
|
||||
|
||||
func (pb *proxyingBlockstore) Get(cid cid.Cid) (blocks.Block, error) {
|
||||
pb.lk.RLock()
|
||||
pb.lk.Lock()
|
||||
if pb.tracing {
|
||||
pb.traced[cid] = struct{}{}
|
||||
}
|
||||
pb.lk.RUnlock()
|
||||
pb.lk.Unlock()
|
||||
|
||||
if block, err := pb.Blockstore.Get(cid); err == nil {
|
||||
return block, err
|
||||
@@ -140,3 +140,12 @@ func (pb *proxyingBlockstore) Get(cid cid.Cid) (blocks.Block, error) {
|
||||
|
||||
return block, nil
|
||||
}
|
||||
|
||||
func (pb *proxyingBlockstore) Put(block blocks.Block) error {
|
||||
pb.lk.Lock()
|
||||
if pb.tracing {
|
||||
pb.traced[block.Cid()] = struct{}{}
|
||||
}
|
||||
pb.lk.Unlock()
|
||||
return pb.Blockstore.Put(block)
|
||||
}
|
||||
|
||||
+222
-36
@@ -46,6 +46,7 @@
|
||||
* [ClientMinerQueryOffer](#ClientMinerQueryOffer)
|
||||
* [ClientQueryAsk](#ClientQueryAsk)
|
||||
* [ClientRemoveImport](#ClientRemoveImport)
|
||||
* [ClientRestartDataTransfer](#ClientRestartDataTransfer)
|
||||
* [ClientRetrieve](#ClientRetrieve)
|
||||
* [ClientRetrieveTryRestartInsufficientFunds](#ClientRetrieveTryRestartInsufficientFunds)
|
||||
* [ClientRetrieveWithEvents](#ClientRetrieveWithEvents)
|
||||
@@ -83,12 +84,14 @@
|
||||
* [MsigAddCancel](#MsigAddCancel)
|
||||
* [MsigAddPropose](#MsigAddPropose)
|
||||
* [MsigApprove](#MsigApprove)
|
||||
* [MsigApproveTxnHash](#MsigApproveTxnHash)
|
||||
* [MsigCancel](#MsigCancel)
|
||||
* [MsigCreate](#MsigCreate)
|
||||
* [MsigGetAvailableBalance](#MsigGetAvailableBalance)
|
||||
* [MsigGetVested](#MsigGetVested)
|
||||
* [MsigGetVestingSchedule](#MsigGetVestingSchedule)
|
||||
* [MsigPropose](#MsigPropose)
|
||||
* [MsigRemoveSigner](#MsigRemoveSigner)
|
||||
* [MsigSwapApprove](#MsigSwapApprove)
|
||||
* [MsigSwapCancel](#MsigSwapCancel)
|
||||
* [MsigSwapPropose](#MsigSwapPropose)
|
||||
@@ -163,6 +166,7 @@
|
||||
* [StateSectorGetInfo](#StateSectorGetInfo)
|
||||
* [StateSectorPartition](#StateSectorPartition)
|
||||
* [StateSectorPreCommitInfo](#StateSectorPreCommitInfo)
|
||||
* [StateVMCirculatingSupplyInternal](#StateVMCirculatingSupplyInternal)
|
||||
* [StateVerifiedClientStatus](#StateVerifiedClientStatus)
|
||||
* [StateVerifiedRegistryRootKey](#StateVerifiedRegistryRootKey)
|
||||
* [StateVerifierStatus](#StateVerifierStatus)
|
||||
@@ -175,6 +179,7 @@
|
||||
* [SyncMarkBad](#SyncMarkBad)
|
||||
* [SyncState](#SyncState)
|
||||
* [SyncSubmitBlock](#SyncSubmitBlock)
|
||||
* [SyncUnmarkAllBad](#SyncUnmarkAllBad)
|
||||
* [SyncUnmarkBad](#SyncUnmarkBad)
|
||||
* [SyncValidateTipset](#SyncValidateTipset)
|
||||
* [Wallet](#Wallet)
|
||||
@@ -223,7 +228,7 @@ Response:
|
||||
```json
|
||||
{
|
||||
"Version": "string value",
|
||||
"APIVersion": 4096,
|
||||
"APIVersion": 4352,
|
||||
"BlockDelay": 42
|
||||
}
|
||||
```
|
||||
@@ -459,7 +464,10 @@ Response:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1157,6 +1165,23 @@ Inputs:
|
||||
|
||||
Response: `{}`
|
||||
|
||||
### ClientRestartDataTransfer
|
||||
ClientRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer
|
||||
|
||||
|
||||
Perms: write
|
||||
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
3,
|
||||
"12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||
true
|
||||
]
|
||||
```
|
||||
|
||||
Response: `{}`
|
||||
|
||||
### ClientRetrieve
|
||||
ClientRetrieve initiates the retrieval of a file, as specified in the order.
|
||||
|
||||
@@ -1330,7 +1355,10 @@ Inputs:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
9,
|
||||
[
|
||||
@@ -1366,7 +1394,10 @@ Inputs:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
[
|
||||
{
|
||||
@@ -1426,7 +1457,10 @@ Inputs:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"MaxFee": "0"
|
||||
@@ -1454,7 +1488,10 @@ Response:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1738,11 +1775,17 @@ Inputs:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
"Signature": {
|
||||
"Type": 2,
|
||||
"Data": "Ynl0ZSBhcnJheQ=="
|
||||
},
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1779,7 +1822,10 @@ Inputs:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"MaxFee": "0"
|
||||
@@ -1800,11 +1846,17 @@ Response:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
"Signature": {
|
||||
"Type": 2,
|
||||
"Data": "Ynl0ZSBhcnJheQ=="
|
||||
},
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1829,11 +1881,17 @@ Inputs:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
"Signature": {
|
||||
"Type": 2,
|
||||
"Data": "Ynl0ZSBhcnJheQ=="
|
||||
},
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1913,11 +1971,17 @@ Response:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
"Signature": {
|
||||
"Type": 2,
|
||||
"Data": "Ynl0ZSBhcnJheQ=="
|
||||
},
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2007,7 +2071,33 @@ Response:
|
||||
```
|
||||
|
||||
### MsigApprove
|
||||
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>
|
||||
|
||||
|
||||
Perms: sign
|
||||
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
"f01234",
|
||||
42,
|
||||
"f01234"
|
||||
]
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
```
|
||||
|
||||
### MsigApproveTxnHash
|
||||
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>
|
||||
|
||||
@@ -2037,7 +2127,7 @@ Response:
|
||||
|
||||
### MsigCancel
|
||||
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>
|
||||
|
||||
|
||||
@@ -2202,6 +2292,33 @@ Response:
|
||||
}
|
||||
```
|
||||
|
||||
### MsigRemoveSigner
|
||||
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.
|
||||
|
||||
|
||||
Perms: sign
|
||||
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
"f01234",
|
||||
"f01234",
|
||||
"f01234",
|
||||
true
|
||||
]
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
```
|
||||
|
||||
### MsigSwapApprove
|
||||
MsigSwapApprove approves a previously proposed SwapSigner
|
||||
It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
|
||||
@@ -2941,7 +3058,10 @@ Inputs:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
[
|
||||
{
|
||||
@@ -2957,6 +3077,9 @@ Inputs:
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"MsgCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Msg": {
|
||||
"Version": 42,
|
||||
"To": "f01234",
|
||||
@@ -2967,7 +3090,10 @@ Response:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
"MsgRct": {
|
||||
"ExitCode": 0,
|
||||
@@ -2985,7 +3111,10 @@ Response:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
"MsgRct": {
|
||||
"ExitCode": 0,
|
||||
@@ -3038,7 +3167,8 @@ Response:
|
||||
```
|
||||
|
||||
### StateCirculatingSupply
|
||||
StateCirculatingSupply returns the circulating supply of Filecoin at the given tipset
|
||||
StateCirculatingSupply returns the exact circulating supply of Filecoin at the given tipset.
|
||||
This is not used anywhere in the protocol itself, and is only for external consumption.
|
||||
|
||||
|
||||
Perms: read
|
||||
@@ -3057,16 +3187,7 @@ Inputs:
|
||||
]
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"FilVested": "0",
|
||||
"FilMined": "0",
|
||||
"FilBurnt": "0",
|
||||
"FilLocked": "0",
|
||||
"FilCirculating": "0"
|
||||
}
|
||||
```
|
||||
Response: `"0"`
|
||||
|
||||
### StateCompute
|
||||
StateCompute is a flexible command that applies the given messages on the given tipset.
|
||||
@@ -3240,7 +3361,10 @@ Inputs:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
[
|
||||
{
|
||||
@@ -3919,7 +4043,7 @@ Inputs:
|
||||
]
|
||||
```
|
||||
|
||||
Response: `4`
|
||||
Response: `5`
|
||||
|
||||
### StateReadState
|
||||
StateReadState returns the indicated actor's state.
|
||||
@@ -3976,6 +4100,9 @@ Inputs:
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"MsgCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Msg": {
|
||||
"Version": 42,
|
||||
"To": "f01234",
|
||||
@@ -3986,7 +4113,10 @@ Response:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
"MsgRct": {
|
||||
"ExitCode": 0,
|
||||
@@ -4004,7 +4134,10 @@ Response:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
"MsgRct": {
|
||||
"ExitCode": 0,
|
||||
@@ -4209,6 +4342,38 @@ Response:
|
||||
}
|
||||
```
|
||||
|
||||
### StateVMCirculatingSupplyInternal
|
||||
StateVMCirculatingSupplyInternal returns an approximation of the circulating supply of Filecoin at the given tipset.
|
||||
This is the value reported by the runtime interface to actors code.
|
||||
|
||||
|
||||
Perms: read
|
||||
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
[
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
{
|
||||
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
|
||||
}
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"FilVested": "0",
|
||||
"FilMined": "0",
|
||||
"FilBurnt": "0",
|
||||
"FilLocked": "0",
|
||||
"FilCirculating": "0"
|
||||
}
|
||||
```
|
||||
|
||||
### StateVerifiedClientStatus
|
||||
StateVerifiedClientStatus returns the data cap for the given address.
|
||||
Returns nil if there is no entry in the data cap table for the
|
||||
@@ -4546,6 +4711,16 @@ Inputs:
|
||||
|
||||
Response: `{}`
|
||||
|
||||
### SyncUnmarkAllBad
|
||||
SyncUnmarkAllBad purges bad block cache, making it possible to sync to chains previously marked as bad
|
||||
|
||||
|
||||
Perms: admin
|
||||
|
||||
Inputs: `null`
|
||||
|
||||
Response: `{}`
|
||||
|
||||
### SyncUnmarkBad
|
||||
SyncUnmarkBad unmarks a blocks as bad, making it possible to be validated and synced again.
|
||||
|
||||
@@ -4644,7 +4819,7 @@ Inputs:
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"Type": "string value",
|
||||
"Type": "bls",
|
||||
"PrivateKey": "Ynl0ZSBhcnJheQ=="
|
||||
}
|
||||
```
|
||||
@@ -4674,7 +4849,7 @@ Inputs:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"Type": "string value",
|
||||
"Type": "bls",
|
||||
"PrivateKey": "Ynl0ZSBhcnJheQ=="
|
||||
}
|
||||
]
|
||||
@@ -4694,6 +4869,8 @@ Response: `null`
|
||||
|
||||
### WalletNew
|
||||
WalletNew creates a new address in the wallet with the given sigType.
|
||||
Available key types: bls, secp256k1, secp256k1-ledger
|
||||
Support for numerical types: 1 - secp256k1, 2 - BLS is deprecated
|
||||
|
||||
|
||||
Perms: write
|
||||
@@ -4701,7 +4878,7 @@ Perms: write
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
2
|
||||
"bls"
|
||||
]
|
||||
```
|
||||
|
||||
@@ -4764,7 +4941,10 @@ Inputs:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -4782,11 +4962,17 @@ Response:
|
||||
"GasFeeCap": "0",
|
||||
"GasPremium": "0",
|
||||
"Method": 1,
|
||||
"Params": "Ynl0ZSBhcnJheQ=="
|
||||
"Params": "Ynl0ZSBhcnJheQ==",
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
},
|
||||
"Signature": {
|
||||
"Type": 2,
|
||||
"Data": "Ynl0ZSBhcnJheQ=="
|
||||
},
|
||||
"CID": {
|
||||
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Vendored
+1
-1
Submodule extern/oni updated: dbee44e4f9...10ed9ef576
Vendored
+5
-4
@@ -230,8 +230,8 @@ func (mgr *SectorMgr) SealCommit1(ctx context.Context, sid abi.SectorID, ticket
|
||||
}
|
||||
|
||||
func (mgr *SectorMgr) SealCommit2(ctx context.Context, sid abi.SectorID, phase1Out storage.Commit1Out) (proof storage.Proof, err error) {
|
||||
var out [32]byte
|
||||
for i := range out {
|
||||
var out [1920]byte
|
||||
for i := range out[:len(phase1Out)] {
|
||||
out[i] = phase1Out[i] ^ byte(sid.Number&0xff)
|
||||
}
|
||||
|
||||
@@ -407,11 +407,12 @@ func (mgr *SectorMgr) CheckProvable(ctx context.Context, spt abi.RegisteredSealP
|
||||
}
|
||||
|
||||
func (m mockVerif) VerifySeal(svi proof.SealVerifyInfo) (bool, error) {
|
||||
if len(svi.Proof) != 32 { // Real ones are longer, but this should be fine
|
||||
if len(svi.Proof) != 1920 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
for i, b := range svi.Proof {
|
||||
// only the first 32 bytes, the rest are 0.
|
||||
for i, b := range svi.Proof[:32] {
|
||||
if b != svi.UnsealedCID.Bytes()[i]+svi.SealedCID.Bytes()[31-i]-svi.InteractiveRandomness[i]*svi.Randomness[i] {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -20,26 +20,26 @@ require (
|
||||
github.com/drand/kyber v1.1.2
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/elastic/go-sysinfo v1.3.0
|
||||
github.com/fatih/color v1.8.0
|
||||
github.com/fatih/color v1.9.0
|
||||
github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200716204036-cddc56607e1d
|
||||
github.com/filecoin-project/go-address v0.0.4
|
||||
github.com/filecoin-project/go-amt-ipld/v2 v2.1.1-0.20201006184820-924ee87a1349 // indirect
|
||||
github.com/filecoin-project/go-bitfield v0.2.1
|
||||
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2
|
||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
|
||||
github.com/filecoin-project/go-data-transfer v0.6.7
|
||||
github.com/filecoin-project/go-data-transfer v0.9.0
|
||||
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-fil-markets v0.9.1
|
||||
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.3
|
||||
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
|
||||
@@ -66,7 +66,7 @@ require (
|
||||
github.com/ipfs/go-ds-pebble v0.0.2-0.20200921225637-ce220f8ac459
|
||||
github.com/ipfs/go-filestore v1.0.0
|
||||
github.com/ipfs/go-fs-lock v0.0.6
|
||||
github.com/ipfs/go-graphsync v0.2.1
|
||||
github.com/ipfs/go-graphsync v0.3.0
|
||||
github.com/ipfs/go-ipfs-blockstore v1.0.1
|
||||
github.com/ipfs/go-ipfs-chunker v0.0.5
|
||||
github.com/ipfs/go-ipfs-ds-help v1.0.0
|
||||
@@ -104,6 +104,7 @@ require (
|
||||
github.com/libp2p/go-libp2p-tls v0.1.3
|
||||
github.com/libp2p/go-libp2p-yamux v0.2.8
|
||||
github.com/libp2p/go-maddr-filter v0.1.0
|
||||
github.com/mattn/go-colorable v0.1.6 // indirect
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/multiformats/go-base32 v0.0.3
|
||||
@@ -120,6 +121,7 @@ require (
|
||||
github.com/urfave/cli/v2 v2.2.0
|
||||
github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163
|
||||
github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4
|
||||
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
|
||||
github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d
|
||||
github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542
|
||||
|
||||
@@ -221,6 +221,8 @@ github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:Jp
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.8.0 h1:5bzFgL+oy7JITMTxUPJ00n7VxmYd/PdMp5mHFX40/RY=
|
||||
github.com/fatih/color v1.8.0/go.mod h1:3l45GVGkyrnYNl9HoIjnp2NnNWvh6hLAqD8yTfGjnw8=
|
||||
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E=
|
||||
github.com/filecoin-project/go-address v0.0.3 h1:eVfbdjEbpbzIrbiSa+PiGUY+oDK9HnUn+M1R/ggoHf8=
|
||||
github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8=
|
||||
@@ -238,14 +240,14 @@ github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:a
|
||||
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg=
|
||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus=
|
||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ=
|
||||
github.com/filecoin-project/go-data-transfer v0.6.7 h1:Kacr5qz2YWtd3sensU6aXFtES7joeapVDeXApeUD35I=
|
||||
github.com/filecoin-project/go-data-transfer v0.6.7/go.mod h1:C++k1U6+jMQODOaen5OPDo9XQbth9Yq3ie94vNjBJbk=
|
||||
github.com/filecoin-project/go-data-transfer v0.9.0 h1:nTT8j7Hu3TM0wRWrGy83/ctawG7sleJGdFWtIsUsKgY=
|
||||
github.com/filecoin-project/go-data-transfer v0.9.0/go.mod h1:i2CqUy7TMQGKukj9BgqIxiP8nDHDXU2VLd771KVaCaQ=
|
||||
github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ=
|
||||
github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s=
|
||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s=
|
||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ=
|
||||
github.com/filecoin-project/go-fil-markets v0.7.1 h1:e0NlpSnaeGyDUhCOzevjcxkSA54kt9BzlXpLRgduUFI=
|
||||
github.com/filecoin-project/go-fil-markets v0.7.1/go.mod h1:5Pt4DXQqUoUrp9QzlSdlYTpItXxwAtqKrxRWQ6hAOqk=
|
||||
github.com/filecoin-project/go-fil-markets v0.9.1 h1:MgO+UkpreD6x8DV2Zkw2xlBogixfpw9/wf4+nBii7bU=
|
||||
github.com/filecoin-project/go-fil-markets v0.9.1/go.mod h1:h+bJ/IUnYjnW5HMKyt9JQSnhslqetkpuzwwugc3K8vM=
|
||||
github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM=
|
||||
github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM=
|
||||
github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24=
|
||||
@@ -262,10 +264,10 @@ github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261 h
|
||||
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261/go.mod h1:fZzmf4tftbwf9S37XRifoJlz7nCjRdIrMGLR07dKLCc=
|
||||
github.com/filecoin-project/go-state-types v0.0.0-20200903145444-247639ffa6ad/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I=
|
||||
github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I=
|
||||
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-statemachine v0.0.0-20200714194326-a77c3ae20989/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
|
||||
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-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw=
|
||||
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
|
||||
github.com/filecoin-project/go-statestore v0.1.0 h1:t56reH59843TwXHkMcwyuayStBIiWBRilQjQ+5IiwdQ=
|
||||
@@ -273,11 +275,11 @@ github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZO
|
||||
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b h1:fkRZSPrYpk42PV3/lIXiL0LHetxde7vyYYvSsttQtfg=
|
||||
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/go.mod h1:Q0GQOBtKf1oE10eSXSlhN45kDBdGvEcVOqMiffqX+N8=
|
||||
github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07U6cPKol6fd3w9KjMPZ6Z4=
|
||||
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.3 h1:Niy6xncgi8bI8aBCt1McdZfATBfG4Uxytt8KW4s3bAc=
|
||||
github.com/filecoin-project/specs-actors/v2 v2.0.3/go.mod h1:v2NZVYinNIKA9acEMBm5wWXxqv5+frFEbekBFemYghY=
|
||||
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=
|
||||
@@ -536,8 +538,8 @@ github.com/ipfs/go-filestore v1.0.0/go.mod h1:/XOCuNtIe2f1YPbiXdYvD0BKLA0JR1MgPi
|
||||
github.com/ipfs/go-fs-lock v0.0.6 h1:sn3TWwNVQqSeNjlWy6zQ1uUGAZrV3hPOyEA6y1/N2a0=
|
||||
github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM=
|
||||
github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE=
|
||||
github.com/ipfs/go-graphsync v0.2.1 h1:MdehhqBSuTI2LARfKLkpYnt0mUrqHs/mtuDnESXHBfU=
|
||||
github.com/ipfs/go-graphsync v0.2.1/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10=
|
||||
github.com/ipfs/go-graphsync v0.3.0 h1:I6Y20kSuCWkUvPoUWo4V3am704/9QjgDVVkf0zIV8+8=
|
||||
github.com/ipfs/go-graphsync v0.3.0/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10=
|
||||
github.com/ipfs/go-hamt-ipld v0.1.1 h1:0IQdvwnAAUKmDE+PMJa5y1QiwOPHpI9+eAbQEEEYthk=
|
||||
github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk=
|
||||
github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08=
|
||||
@@ -1045,11 +1047,16 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
@@ -1422,6 +1429,8 @@ github.com/whyrusleeping/go-smux-multiplex v3.0.16+incompatible/go.mod h1:34LEDb
|
||||
github.com/whyrusleeping/go-smux-multistream v2.0.2+incompatible/go.mod h1:dRWHHvc4HDQSHh9gbKEBbUZ+f2Q8iZTPG3UOGYODxSQ=
|
||||
github.com/whyrusleeping/go-smux-yamux v2.0.8+incompatible/go.mod h1:6qHUzBXUbB9MXmw3AUdB52L8sEb/hScCqOdW2kj/wuI=
|
||||
github.com/whyrusleeping/go-smux-yamux v2.0.9+incompatible/go.mod h1:6qHUzBXUbB9MXmw3AUdB52L8sEb/hScCqOdW2kj/wuI=
|
||||
github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 h1:NwiwjQDB3CzQ5XH0rdMh1oQqzJH7O2PSLWxif/w3zsY=
|
||||
github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4/go.mod h1:K+EVq8d5QcQ2At5VECsA+SNZvWefyBXh8TnIsxo1OvQ=
|
||||
github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA=
|
||||
github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
|
||||
github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
|
||||
@@ -1443,6 +1452,10 @@ github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZD
|
||||
github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8=
|
||||
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
|
||||
github.com/zondax/ledger-go v0.12.1 h1:hYRcyznPRJp+5mzF2sazTLP2nGvGjYDD2VzhHhFomLU=
|
||||
github.com/zondax/ledger-go v0.12.1/go.mod h1:KatxXrVDzgWwbssUWsF5+cOJHXPvzQ09YSlzGNuhOEo=
|
||||
go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs=
|
||||
go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw=
|
||||
go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ=
|
||||
@@ -1515,6 +1528,7 @@ golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
@@ -1658,11 +1672,13 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
||||
@@ -18,19 +18,18 @@ import (
|
||||
"context"
|
||||
|
||||
ds "github.com/ipfs/go-datastore"
|
||||
dssync "github.com/ipfs/go-datastore/sync"
|
||||
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
)
|
||||
|
||||
// NewTemporary returns a temporary blockstore.
|
||||
func NewTemporary() blockstore.Blockstore {
|
||||
return NewBlockstore(ds.NewMapDatastore())
|
||||
func NewTemporary() MemStore {
|
||||
return make(MemStore)
|
||||
}
|
||||
|
||||
// NewTemporarySync returns a thread-safe temporary blockstore.
|
||||
func NewTemporarySync() blockstore.Blockstore {
|
||||
return NewBlockstore(dssync.MutexWrap(ds.NewMapDatastore()))
|
||||
func NewTemporarySync() *SyncStore {
|
||||
return &SyncStore{bs: make(MemStore)}
|
||||
}
|
||||
|
||||
// WrapIDStore wraps the underlying blockstore in an "identity" blockstore.
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
)
|
||||
|
||||
type MemStore map[cid.Cid]blocks.Block
|
||||
|
||||
func (m MemStore) DeleteBlock(k cid.Cid) error {
|
||||
delete(m, k)
|
||||
return nil
|
||||
}
|
||||
func (m MemStore) Has(k cid.Cid) (bool, error) {
|
||||
_, ok := m[k]
|
||||
return ok, nil
|
||||
}
|
||||
func (m MemStore) Get(k cid.Cid) (blocks.Block, error) {
|
||||
b, ok := m[k]
|
||||
if !ok {
|
||||
return nil, blockstore.ErrNotFound
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// GetSize returns the CIDs mapped BlockSize
|
||||
func (m MemStore) GetSize(k cid.Cid) (int, error) {
|
||||
b, ok := m[k]
|
||||
if !ok {
|
||||
return 0, blockstore.ErrNotFound
|
||||
}
|
||||
return len(b.RawData()), nil
|
||||
}
|
||||
|
||||
// Put puts a given block to the underlying datastore
|
||||
func (m MemStore) Put(b blocks.Block) error {
|
||||
// Convert to a basic block for safety, but try to reuse the existing
|
||||
// block if it's already a basic block.
|
||||
k := b.Cid()
|
||||
if _, ok := b.(*blocks.BasicBlock); !ok {
|
||||
// If we already have the block, abort.
|
||||
if _, ok := m[k]; ok {
|
||||
return nil
|
||||
}
|
||||
// the error is only for debugging.
|
||||
b, _ = blocks.NewBlockWithCid(b.RawData(), b.Cid())
|
||||
}
|
||||
m[b.Cid()] = b
|
||||
return nil
|
||||
}
|
||||
|
||||
// PutMany puts a slice of blocks at the same time using batching
|
||||
// capabilities of the underlying datastore whenever possible.
|
||||
func (m MemStore) PutMany(bs []blocks.Block) error {
|
||||
for _, b := range bs {
|
||||
_ = m.Put(b) // can't fail
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AllKeysChan returns a channel from which
|
||||
// the CIDs in the Blockstore can be read. It should respect
|
||||
// the given context, closing the channel if it becomes Done.
|
||||
func (m MemStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
ch := make(chan cid.Cid, len(m))
|
||||
for k := range m {
|
||||
ch <- k
|
||||
}
|
||||
close(ch)
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
// HashOnRead specifies if every read block should be
|
||||
// rehashed to make sure it matches its CID.
|
||||
func (m MemStore) HashOnRead(enabled bool) {
|
||||
// no-op
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package blockstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
type SyncStore struct {
|
||||
mu sync.RWMutex
|
||||
bs MemStore // specifically use a memStore to save indirection overhead.
|
||||
}
|
||||
|
||||
func (m *SyncStore) DeleteBlock(k cid.Cid) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
return m.bs.DeleteBlock(k)
|
||||
}
|
||||
func (m *SyncStore) Has(k cid.Cid) (bool, error) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.bs.Has(k)
|
||||
}
|
||||
func (m *SyncStore) Get(k cid.Cid) (blocks.Block, error) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.bs.Get(k)
|
||||
}
|
||||
|
||||
// GetSize returns the CIDs mapped BlockSize
|
||||
func (m *SyncStore) GetSize(k cid.Cid) (int, error) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.bs.GetSize(k)
|
||||
}
|
||||
|
||||
// Put puts a given block to the underlying datastore
|
||||
func (m *SyncStore) Put(b blocks.Block) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
return m.bs.Put(b)
|
||||
}
|
||||
|
||||
// PutMany puts a slice of blocks at the same time using batching
|
||||
// capabilities of the underlying datastore whenever possible.
|
||||
func (m *SyncStore) PutMany(bs []blocks.Block) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
return m.bs.PutMany(bs)
|
||||
}
|
||||
|
||||
// AllKeysChan returns a channel from which
|
||||
// the CIDs in the Blockstore can be read. It should respect
|
||||
// the given context, closing the channel if it becomes Done.
|
||||
func (m *SyncStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
// this blockstore implementation doesn't do any async work.
|
||||
return m.bs.AllKeysChan(ctx)
|
||||
}
|
||||
|
||||
// HashOnRead specifies if every read block should be
|
||||
// rehashed to make sure it matches its CID.
|
||||
func (m *SyncStore) HashOnRead(enabled bool) {
|
||||
// noop
|
||||
}
|
||||
@@ -19,10 +19,12 @@ type BufferedBS struct {
|
||||
}
|
||||
|
||||
func NewBufferedBstore(base bstore.Blockstore) *BufferedBS {
|
||||
buf := bstore.NewTemporary()
|
||||
var buf bstore.Blockstore
|
||||
if os.Getenv("LOTUS_DISABLE_VM_BUF") == "iknowitsabadidea" {
|
||||
log.Warn("VM BLOCKSTORE BUFFERING IS DISABLED")
|
||||
buf = base
|
||||
} else {
|
||||
buf = bstore.NewTemporary()
|
||||
}
|
||||
|
||||
return &BufferedBS{
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
package timedbs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
"go.uber.org/multierr"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/lib/blockstore"
|
||||
)
|
||||
|
||||
// TimedCacheBS is a blockstore that keeps blocks for at least the specified
|
||||
// caching interval before discarding them. Garbage collection must be started
|
||||
// and stopped by calling Start/Stop.
|
||||
//
|
||||
// Under the covers, it's implemented with an active and an inactive blockstore
|
||||
// that are rotated every cache time interval. This means all blocks will be
|
||||
// stored at most 2x the cache interval.
|
||||
type TimedCacheBS struct {
|
||||
mu sync.RWMutex
|
||||
active, inactive blockstore.MemStore
|
||||
|
||||
interval time.Duration
|
||||
closeCh chan struct{}
|
||||
}
|
||||
|
||||
func NewTimedCacheBS(cacheTime time.Duration) *TimedCacheBS {
|
||||
return &TimedCacheBS{
|
||||
active: blockstore.NewTemporary(),
|
||||
inactive: blockstore.NewTemporary(),
|
||||
interval: cacheTime,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TimedCacheBS) Start(ctx context.Context) error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.closeCh != nil {
|
||||
return fmt.Errorf("already started")
|
||||
}
|
||||
t.closeCh = make(chan struct{})
|
||||
go func() {
|
||||
ticker := build.Clock.Ticker(t.interval)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
t.rotate()
|
||||
case <-t.closeCh:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TimedCacheBS) Stop(ctx context.Context) error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.closeCh == nil {
|
||||
return fmt.Errorf("not started started")
|
||||
}
|
||||
select {
|
||||
case <-t.closeCh:
|
||||
// already closed
|
||||
default:
|
||||
close(t.closeCh)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TimedCacheBS) rotate() {
|
||||
newBs := blockstore.NewTemporary()
|
||||
|
||||
t.mu.Lock()
|
||||
t.inactive, t.active = t.active, newBs
|
||||
t.mu.Unlock()
|
||||
}
|
||||
|
||||
func (t *TimedCacheBS) Put(b blocks.Block) error {
|
||||
// Don't check the inactive set here. We want to keep this block for at
|
||||
// least one interval.
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
return t.active.Put(b)
|
||||
}
|
||||
|
||||
func (t *TimedCacheBS) PutMany(bs []blocks.Block) error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
return t.active.PutMany(bs)
|
||||
}
|
||||
|
||||
func (t *TimedCacheBS) Get(k cid.Cid) (blocks.Block, error) {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
b, err := t.active.Get(k)
|
||||
if err == blockstore.ErrNotFound {
|
||||
b, err = t.inactive.Get(k)
|
||||
}
|
||||
return b, err
|
||||
}
|
||||
|
||||
func (t *TimedCacheBS) GetSize(k cid.Cid) (int, error) {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
size, err := t.active.GetSize(k)
|
||||
if err == blockstore.ErrNotFound {
|
||||
size, err = t.inactive.GetSize(k)
|
||||
}
|
||||
return size, err
|
||||
}
|
||||
|
||||
func (t *TimedCacheBS) Has(k cid.Cid) (bool, error) {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
if has, err := t.active.Has(k); err != nil {
|
||||
return false, err
|
||||
} else if has {
|
||||
return true, nil
|
||||
}
|
||||
return t.inactive.Has(k)
|
||||
}
|
||||
|
||||
func (t *TimedCacheBS) HashOnRead(_ bool) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
func (t *TimedCacheBS) DeleteBlock(k cid.Cid) error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
return multierr.Combine(t.active.DeleteBlock(k), t.inactive.DeleteBlock(k))
|
||||
}
|
||||
|
||||
func (t *TimedCacheBS) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
|
||||
ch := make(chan cid.Cid, len(t.active)+len(t.inactive))
|
||||
for c := range t.active {
|
||||
ch <- c
|
||||
}
|
||||
for c := range t.inactive {
|
||||
if _, ok := t.active[c]; ok {
|
||||
continue
|
||||
}
|
||||
ch <- c
|
||||
}
|
||||
close(ch)
|
||||
return ch, nil
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package timedbs_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/lotus/lib/timedbs"
|
||||
)
|
||||
|
||||
func TestTimedBSSimple(t *testing.T) {
|
||||
tc := timedbs.NewTimedCacheBS(10 * time.Millisecond)
|
||||
_ = tc.Start(context.Background())
|
||||
defer func() {
|
||||
_ = tc.Stop(context.Background())
|
||||
}()
|
||||
|
||||
b1 := blocks.NewBlock([]byte("foo"))
|
||||
require.NoError(t, tc.Put(b1))
|
||||
|
||||
b2 := blocks.NewBlock([]byte("bar"))
|
||||
require.NoError(t, tc.Put(b2))
|
||||
|
||||
b3 := blocks.NewBlock([]byte("baz"))
|
||||
|
||||
b1out, err := tc.Get(b1.Cid())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, b1.RawData(), b1out.RawData())
|
||||
|
||||
has, err := tc.Has(b1.Cid())
|
||||
require.NoError(t, err)
|
||||
require.True(t, has)
|
||||
|
||||
time.Sleep(15 * time.Millisecond)
|
||||
|
||||
// We should still have everything.
|
||||
has, err = tc.Has(b1.Cid())
|
||||
require.NoError(t, err)
|
||||
require.True(t, has)
|
||||
|
||||
has, err = tc.Has(b2.Cid())
|
||||
require.NoError(t, err)
|
||||
require.True(t, has)
|
||||
|
||||
// extend b2, add b3.
|
||||
require.NoError(t, tc.Put(b2))
|
||||
require.NoError(t, tc.Put(b3))
|
||||
|
||||
// all keys once.
|
||||
allKeys, err := tc.AllKeysChan(context.Background())
|
||||
var ks []cid.Cid
|
||||
for k := range allKeys {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.ElementsMatch(t, ks, []cid.Cid{b1.Cid(), b2.Cid(), b3.Cid()})
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
// should still have b2, and b3, but not b1
|
||||
|
||||
has, err = tc.Has(b1.Cid())
|
||||
require.NoError(t, err)
|
||||
require.False(t, has)
|
||||
|
||||
has, err = tc.Has(b2.Cid())
|
||||
require.NoError(t, err)
|
||||
require.True(t, has)
|
||||
|
||||
has, err = tc.Has(b3.Cid())
|
||||
require.NoError(t, err)
|
||||
require.True(t, has)
|
||||
}
|
||||
+11
-2
@@ -44,6 +44,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/metrics"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger"
|
||||
"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"
|
||||
@@ -251,8 +252,8 @@ func Online() Option {
|
||||
Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule),
|
||||
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(api.WalletAPI), From(new(wallet.MultiWallet))),
|
||||
Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner),
|
||||
|
||||
Override(new(dtypes.ChainGCLocker), blockstore.NewGCLocker),
|
||||
@@ -459,8 +460,16 @@ 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)),
|
||||
Override(new(*remotewallet.RemoteWallet), remotewallet.SetupRemoteWallet(cfg.Wallet.RemoteBackend)),
|
||||
),
|
||||
If(cfg.Wallet.EnableLedger,
|
||||
Override(new(*ledgerwallet.LedgerWallet), ledgerwallet.NewWallet),
|
||||
),
|
||||
If(cfg.Wallet.DisableLocal,
|
||||
Unset(new(*wallet.LocalWallet)),
|
||||
Override(new(wallet.Default), wallet.NilDefault),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
+7
-5
@@ -110,6 +110,8 @@ type Client struct {
|
||||
|
||||
type Wallet struct {
|
||||
RemoteBackend string
|
||||
EnableLedger bool
|
||||
DisableLocal bool
|
||||
}
|
||||
|
||||
func defCommon() Common {
|
||||
@@ -180,11 +182,11 @@ func DefaultStorageMiner() *StorageMiner {
|
||||
},
|
||||
|
||||
Fees: MinerFeeConfig{
|
||||
MaxPreCommitGasFee: types.FIL(types.BigDiv(types.FromFil(1), types.NewInt(20))), // 0.05
|
||||
MaxCommitGasFee: types.FIL(types.BigDiv(types.FromFil(1), types.NewInt(20))),
|
||||
MaxWindowPoStGasFee: types.FIL(types.FromFil(50)),
|
||||
MaxPublishDealsFee: types.FIL(types.BigDiv(types.FromFil(1), types.NewInt(33))), // 0.03ish
|
||||
MaxMarketBalanceAddFee: types.FIL(types.BigDiv(types.FromFil(1), types.NewInt(100))), // 0.01
|
||||
MaxPreCommitGasFee: types.MustParseFIL("0.025"),
|
||||
MaxCommitGasFee: types.MustParseFIL("0.05"),
|
||||
MaxWindowPoStGasFee: types.MustParseFIL("5"),
|
||||
MaxPublishDealsFee: types.MustParseFIL("0.05"),
|
||||
MaxMarketBalanceAddFee: types.MustParseFIL("0.007"),
|
||||
},
|
||||
}
|
||||
cfg.Common.API.ListenAddress = "/ip4/127.0.0.1/tcp/2345/http"
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-state-types/dline"
|
||||
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
@@ -33,6 +32,7 @@ import (
|
||||
"go.uber.org/fx"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
"github.com/filecoin-project/go-fil-markets/discovery"
|
||||
"github.com/filecoin-project/go-fil-markets/pieceio"
|
||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||
@@ -850,6 +850,14 @@ func (a *API) ClientDataTransferUpdates(ctx context.Context) (<-chan api.DataTra
|
||||
return channels, nil
|
||||
}
|
||||
|
||||
func (a *API) ClientRestartDataTransfer(ctx context.Context, transferID datatransfer.TransferID, otherPeer peer.ID, isInitiator bool) error {
|
||||
selfPeer := a.Host.ID()
|
||||
if isInitiator {
|
||||
return a.DataTransfer.RestartDataTransferChannel(ctx, datatransfer.ChannelID{Initiator: selfPeer, Responder: otherPeer, ID: transferID})
|
||||
}
|
||||
return a.DataTransfer.RestartDataTransferChannel(ctx, datatransfer.ChannelID{Initiator: otherPeer, Responder: selfPeer, ID: transferID})
|
||||
}
|
||||
|
||||
func newDealInfo(v storagemarket.ClientDeal) api.DealInfo {
|
||||
return api.DealInfo{
|
||||
ProposalCid: v.ProposalCid,
|
||||
|
||||
@@ -277,7 +277,7 @@ func (m *GasModule) GasEstimateMessageGas(ctx context.Context, msg *types.Messag
|
||||
}
|
||||
|
||||
if msg.GasPremium == types.EmptyInt || types.BigCmp(msg.GasPremium, types.NewInt(0)) == 0 {
|
||||
gasPremium, err := m.GasEstimateGasPremium(ctx, 2, msg.From, msg.GasLimit, types.TipSetKey{})
|
||||
gasPremium, err := m.GasEstimateGasPremium(ctx, 10, msg.From, msg.GasLimit, types.TipSetKey{})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("estimating gas price: %w", err)
|
||||
}
|
||||
|
||||
@@ -94,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) {
|
||||
@@ -121,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) {
|
||||
@@ -133,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")
|
||||
}
|
||||
@@ -215,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
|
||||
}
|
||||
|
||||
+18
-4
@@ -362,6 +362,7 @@ func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.
|
||||
}
|
||||
|
||||
return &api.InvocResult{
|
||||
MsgCid: mc,
|
||||
Msg: m,
|
||||
MsgRct: &r.MessageReceipt,
|
||||
ExecutionTrace: r.ExecutionTrace,
|
||||
@@ -1049,7 +1050,7 @@ func (a *StateAPI) StateMinerInitialPledgeCollateral(ctx context.Context, maddr
|
||||
return types.EmptyInt, xerrors.Errorf("loading reward actor state: %w", err)
|
||||
}
|
||||
|
||||
circSupply, err := a.StateCirculatingSupply(ctx, ts.Key())
|
||||
circSupply, err := a.StateVMCirculatingSupplyInternal(ctx, ts.Key())
|
||||
if err != nil {
|
||||
return big.Zero(), xerrors.Errorf("getting circulating supply: %w", err)
|
||||
}
|
||||
@@ -1203,7 +1204,7 @@ func (a *StateAPI) StateDealProviderCollateralBounds(ctx context.Context, size a
|
||||
return api.DealCollateralBounds{}, xerrors.Errorf("failed to load reward actor state: %w", err)
|
||||
}
|
||||
|
||||
circ, err := a.StateCirculatingSupply(ctx, ts.Key())
|
||||
circ, err := a.StateVMCirculatingSupplyInternal(ctx, ts.Key())
|
||||
if err != nil {
|
||||
return api.DealCollateralBounds{}, xerrors.Errorf("getting total circulating supply: %w", err)
|
||||
}
|
||||
@@ -1231,7 +1232,20 @@ func (a *StateAPI) StateDealProviderCollateralBounds(ctx context.Context, size a
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
|
||||
func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (abi.TokenAmount, error) {
|
||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
||||
if err != nil {
|
||||
return types.EmptyInt, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||
}
|
||||
|
||||
sTree, err := a.stateForTs(ctx, ts)
|
||||
if err != nil {
|
||||
return types.EmptyInt, err
|
||||
}
|
||||
return a.StateManager.GetCirculatingSupply(ctx, ts.Height(), sTree)
|
||||
}
|
||||
|
||||
func (a *StateAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
|
||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
||||
if err != nil {
|
||||
return api.CirculatingSupply{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||
@@ -1241,7 +1255,7 @@ func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetK
|
||||
if err != nil {
|
||||
return api.CirculatingSupply{}, err
|
||||
}
|
||||
return a.StateManager.GetCirculatingSupplyDetailed(ctx, ts.Height(), sTree)
|
||||
return a.StateManager.GetVMCirculatingSupplyDetailed(ctx, ts.Height(), sTree)
|
||||
}
|
||||
|
||||
func (a *StateAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user