Update calibration network
This commit is contained in:
commit
a3686ce88e
@ -1,5 +1,9 @@
|
|||||||
comment: off
|
comment: off
|
||||||
ignore:
|
ignore:
|
||||||
- "cbor_gen.go"
|
- "**/cbor_gen.go"
|
||||||
|
- "api/test/**/*"
|
||||||
|
- "api/test/*"
|
||||||
|
- "gen/**/*"
|
||||||
|
- "gen/*"
|
||||||
github_checks:
|
github_checks:
|
||||||
annotations: false
|
annotations: false
|
||||||
|
91
CHANGELOG.md
91
CHANGELOG.md
@ -1,5 +1,96 @@
|
|||||||
# Lotus changelog
|
# Lotus changelog
|
||||||
|
|
||||||
|
# 1.0.0 / 2020-10-19
|
||||||
|
|
||||||
|
It's 1.0.0! This is an optional release of Lotus that introduces some UX improvements to the 0.10 series.
|
||||||
|
|
||||||
|
This very small release is largely cosmetic, and intended to flag the code that the Filecoin mainnet was launched with.
|
||||||
|
|
||||||
|
## API changes
|
||||||
|
|
||||||
|
- `StateMsgGasCost` has been removed. The equivalent information can be gained by calling `StateReplay`.
|
||||||
|
- A `GasCost` field has been added to the `InvocResult` type, meaning detailed gas costs will be returned when calling `StateReplay`, `StateCompute`, and `StateCall`.
|
||||||
|
- The behaviour of `StateReplay` in response to an empty tipset key has been changed. Instead of simply using the heaviest tipset (which is almost guaranteed to be an unsuccessful replay), we search now search the chain for the tipset that included the message, and replay the message in that tipset (we fail if no such tipset is found).
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- Increase code coverage! (https://github.com/filecoin-project/lotus/pull/4410)
|
||||||
|
- Mpool: Don't block node startup loading messages (https://github.com/filecoin-project/lotus/pull/4411)
|
||||||
|
- Improve the UX of multisig approves (https://github.com/filecoin-project/lotus/pull/4398)
|
||||||
|
- Use build.BlockDelaySecs for deal start buffer (https://github.com/filecoin-project/lotus/pull/4415)
|
||||||
|
- Conformance: support multiple protocol versions (https://github.com/filecoin-project/lotus/pull/4393)
|
||||||
|
- Ensure msig inspect cli works with lotus-lite (https://github.com/filecoin-project/lotus/pull/4421)
|
||||||
|
- Add command to (slowly) prune lotus chain datastore (https://github.com/filecoin-project/lotus/pull/3876)
|
||||||
|
- Add WalletVerify to lotus-gateway (https://github.com/filecoin-project/lotus/pull/4373)
|
||||||
|
- Improve StateMsg APIs (https://github.com/filecoin-project/lotus/pull/4429)
|
||||||
|
- Add endpoints needed by spacegap (https://github.com/filecoin-project/lotus/pull/4426)
|
||||||
|
- Make audit balances capable of printing robust addresses (https://github.com/filecoin-project/lotus/pull/4423)
|
||||||
|
- Custom filters for retrieval deals (https://github.com/filecoin-project/lotus/pull/4424)
|
||||||
|
- Fix message list api (https://github.com/filecoin-project/lotus/pull/4422)
|
||||||
|
- Replace bootstrap peers (https://github.com/filecoin-project/lotus/pull/4447)
|
||||||
|
- Don't overwrite previously-configured maxPieceSize for a persisted ask (https://github.com/filecoin-project/lotus/pull/4480)
|
||||||
|
- State: optimize state snapshot address cache (https://github.com/filecoin-project/lotus/pull/4481)
|
||||||
|
|
||||||
|
# 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
|
# 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.
|
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.
|
||||||
|
12
SECURITY.md
12
SECURITY.md
@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
For *critical* bugs, please send an email to security@filecoin.org.
|
For *critical* bugs, please consult our Security Policy and Responsible Disclosure Program information at https://github.com/filecoin-project/community/blob/master/SECURITY.md
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
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.
|
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'.
|
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.
|
For non-critical bugs, please simply file a GitHub [issue](https://github.com/filecoin-project/lotus/issues/new?template=bug_report.md).
|
||||||
|
|
||||||
| Version | Supported |
|
|
||||||
| ------- | ------------------ |
|
|
||||||
| Testnet | :white_check_mark: |
|
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||||
"github.com/filecoin-project/go-state-types/network"
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
@ -229,7 +230,9 @@ type FullNode interface {
|
|||||||
// MethodGroup: Wallet
|
// MethodGroup: Wallet
|
||||||
|
|
||||||
// WalletNew creates a new address in the wallet with the given sigType.
|
// 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 indicates whether the given address is in the wallet.
|
||||||
WalletHas(context.Context, address.Address) (bool, error)
|
WalletHas(context.Context, address.Address) (bool, error)
|
||||||
// WalletList lists all the addresses in the wallet.
|
// WalletList lists all the addresses in the wallet.
|
||||||
@ -296,6 +299,8 @@ type FullNode interface {
|
|||||||
// ClientListTransfers returns the status of all ongoing transfers of data
|
// ClientListTransfers returns the status of all ongoing transfers of data
|
||||||
ClientListDataTransfers(ctx context.Context) ([]DataTransferChannel, error)
|
ClientListDataTransfers(ctx context.Context) ([]DataTransferChannel, error)
|
||||||
ClientDataTransferUpdates(ctx context.Context) (<-chan 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
|
// ClientRetrieveTryRestartInsufficientFunds attempts to restart stalled retrievals on a given payment channel
|
||||||
// which are stuck due to insufficient funds
|
// which are stuck due to insufficient funds
|
||||||
ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error
|
ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error
|
||||||
@ -310,19 +315,20 @@ type FullNode interface {
|
|||||||
|
|
||||||
// MethodGroup: State
|
// MethodGroup: State
|
||||||
// The State methods are used to query, inspect, and interact with chain state.
|
// The State methods are used to query, inspect, and interact with chain state.
|
||||||
// All methods take a TipSetKey as a parameter. The state looked up is the state at that tipset.
|
// Most methods take a TipSetKey as a parameter. The state looked up is the state at that tipset.
|
||||||
// A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used.
|
// A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used.
|
||||||
|
|
||||||
// StateCall runs the given message and returns its result without any persisted changes.
|
// StateCall runs the given message and returns its result without any persisted changes.
|
||||||
StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error)
|
StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error)
|
||||||
// StateReplay returns the result of executing the indicated message, assuming it was executed in the indicated tipset.
|
// StateReplay replays a given message, assuming it was included in a block in the specified tipset.
|
||||||
|
// If no tipset key is provided, the appropriate tipset is looked up.
|
||||||
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error)
|
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error)
|
||||||
// StateGetActor returns the indicated actor's nonce and balance.
|
// StateGetActor returns the indicated actor's nonce and balance.
|
||||||
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
|
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
|
||||||
// StateReadState returns the indicated actor's state.
|
// StateReadState returns the indicated actor's state.
|
||||||
StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*ActorState, error)
|
StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*ActorState, error)
|
||||||
// StateListMessages looks back and returns all messages with a matching to or from address, stopping at the given height.
|
// StateListMessages looks back and returns all messages with a matching to or from address, stopping at the given height.
|
||||||
StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error)
|
StateListMessages(ctx context.Context, match *MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error)
|
||||||
|
|
||||||
// StateNetworkName returns the name of the network the node is synced to
|
// StateNetworkName returns the name of the network the node is synced to
|
||||||
StateNetworkName(context.Context) (dtypes.NetworkName, error)
|
StateNetworkName(context.Context) (dtypes.NetworkName, error)
|
||||||
@ -365,8 +371,6 @@ type FullNode interface {
|
|||||||
StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*miner.SectorLocation, error)
|
StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*miner.SectorLocation, error)
|
||||||
// StateSearchMsg searches for a message in the chain, and returns its receipt and the tipset where it was executed
|
// StateSearchMsg searches for a message in the chain, and returns its receipt and the tipset where it was executed
|
||||||
StateSearchMsg(context.Context, cid.Cid) (*MsgLookup, error)
|
StateSearchMsg(context.Context, cid.Cid) (*MsgLookup, error)
|
||||||
// StateMsgGasCost searches for a message in the chain, and returns details of the messages gas costs, including the penalty and miner tip
|
|
||||||
StateMsgGasCost(context.Context, cid.Cid, types.TipSetKey) (*MsgGasCost, error)
|
|
||||||
// StateWaitMsg looks back in the chain for a message. If not found, it blocks until the
|
// StateWaitMsg looks back in the chain for a message. If not found, it blocks until the
|
||||||
// message arrives on chain, and gets to the indicated confidence depth.
|
// message arrives on chain, and gets to the indicated confidence depth.
|
||||||
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error)
|
StateWaitMsg(ctx context.Context, cid cid.Cid, confidence uint64) (*MsgLookup, error)
|
||||||
@ -414,8 +418,12 @@ type FullNode interface {
|
|||||||
// can issue. It takes the deal size and verified status as parameters.
|
// can issue. It takes the deal size and verified status as parameters.
|
||||||
StateDealProviderCollateralBounds(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (DealCollateralBounds, error)
|
StateDealProviderCollateralBounds(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (DealCollateralBounds, error)
|
||||||
|
|
||||||
// StateCirculatingSupply returns the circulating supply of Filecoin at the given tipset
|
// StateCirculatingSupply returns the exact circulating supply of Filecoin at the given tipset.
|
||||||
StateCirculatingSupply(context.Context, types.TipSetKey) (CirculatingSupply, error)
|
// 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 returns the network version at the given tipset
|
||||||
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
|
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
|
||||||
|
|
||||||
@ -728,8 +736,10 @@ type RetrievalOrder struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type InvocResult struct {
|
type InvocResult struct {
|
||||||
|
MsgCid cid.Cid
|
||||||
Msg *types.Message
|
Msg *types.Message
|
||||||
MsgRct *types.MessageReceipt
|
MsgRct *types.MessageReceipt
|
||||||
|
GasCost MsgGasCost
|
||||||
ExecutionTrace types.ExecutionTrace
|
ExecutionTrace types.ExecutionTrace
|
||||||
Error string
|
Error string
|
||||||
Duration time.Duration
|
Duration time.Duration
|
||||||
@ -908,3 +918,8 @@ type MsigVesting struct {
|
|||||||
StartEpoch abi.ChainEpoch
|
StartEpoch abi.ChainEpoch
|
||||||
UnlockDuration abi.ChainEpoch
|
UnlockDuration abi.ChainEpoch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MessageMatch struct {
|
||||||
|
To address.Address
|
||||||
|
From address.Address
|
||||||
|
}
|
||||||
|
@ -10,9 +10,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type GatewayAPI interface {
|
type GatewayAPI interface {
|
||||||
|
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||||
ChainHead(ctx context.Context) (*types.TipSet, error)
|
ChainHead(ctx context.Context) (*types.TipSet, error)
|
||||||
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
|
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||||
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||||
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||||
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||||
|
@ -35,7 +35,7 @@ type MsgMeta struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type WalletAPI interface {
|
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)
|
WalletHas(context.Context, address.Address) (bool, error)
|
||||||
WalletList(context.Context) ([]address.Address, error)
|
WalletList(context.Context) ([]address.Address, error)
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-bitfield"
|
"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/piecestore"
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||||
@ -133,7 +134,7 @@ type FullNodeStruct struct {
|
|||||||
MinerGetBaseInfo func(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"`
|
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"`
|
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"`
|
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
|
||||||
WalletList func(context.Context) ([]address.Address, error) `perm:"write"`
|
WalletList func(context.Context) ([]address.Address, error) `perm:"write"`
|
||||||
WalletBalance func(context.Context, address.Address) (types.BigInt, error) `perm:"read"`
|
WalletBalance func(context.Context, address.Address) (types.BigInt, error) `perm:"read"`
|
||||||
@ -165,6 +166,7 @@ type FullNodeStruct struct {
|
|||||||
ClientDealSize func(ctx context.Context, root cid.Cid) (api.DataSize, error) `perm:"read"`
|
ClientDealSize func(ctx context.Context, root cid.Cid) (api.DataSize, error) `perm:"read"`
|
||||||
ClientListDataTransfers func(ctx context.Context) ([]api.DataTransferChannel, error) `perm:"write"`
|
ClientListDataTransfers func(ctx context.Context) ([]api.DataTransferChannel, error) `perm:"write"`
|
||||||
ClientDataTransferUpdates func(ctx context.Context) (<-chan 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"`
|
ClientRetrieveTryRestartInsufficientFunds func(ctx context.Context, paymentChannel address.Address) error `perm:"write"`
|
||||||
|
|
||||||
StateNetworkName func(context.Context) (dtypes.NetworkName, error) `perm:"read"`
|
StateNetworkName func(context.Context) (dtypes.NetworkName, error) `perm:"read"`
|
||||||
@ -189,7 +191,6 @@ type FullNodeStruct struct {
|
|||||||
StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"`
|
StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"`
|
||||||
StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"`
|
StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"`
|
||||||
StateReadState func(context.Context, address.Address, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
|
StateReadState func(context.Context, address.Address, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
|
||||||
StateMsgGasCost func(context.Context, cid.Cid, types.TipSetKey) (*api.MsgGasCost, error) `perm:"read"`
|
|
||||||
StateWaitMsg func(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) `perm:"read"`
|
StateWaitMsg func(ctx context.Context, cid cid.Cid, confidence uint64) (*api.MsgLookup, error) `perm:"read"`
|
||||||
StateWaitMsgLimited func(context.Context, cid.Cid, uint64, abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"`
|
StateWaitMsgLimited func(context.Context, cid.Cid, uint64, abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"`
|
||||||
StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"`
|
StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"`
|
||||||
@ -204,13 +205,14 @@ type FullNodeStruct struct {
|
|||||||
StateChangedActors func(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) `perm:"read"`
|
StateChangedActors func(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) `perm:"read"`
|
||||||
StateGetReceipt func(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"`
|
StateGetReceipt func(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"`
|
||||||
StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"`
|
StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"`
|
||||||
StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"`
|
StateListMessages func(ctx context.Context, match *api.MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"`
|
||||||
StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"`
|
StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"`
|
||||||
StateVerifierStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"`
|
StateVerifierStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"`
|
||||||
StateVerifiedClientStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"`
|
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"`
|
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"`
|
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"`
|
StateNetworkVersion func(context.Context, types.TipSetKey) (stnetwork.Version, error) `perm:"read"`
|
||||||
|
|
||||||
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||||
@ -368,9 +370,11 @@ type WorkerStruct struct {
|
|||||||
type GatewayStruct struct {
|
type GatewayStruct struct {
|
||||||
Internal struct {
|
Internal struct {
|
||||||
// TODO: does the gateway need perms?
|
// TODO: does the gateway need perms?
|
||||||
|
ChainHasObj func(context.Context, cid.Cid) (bool, error)
|
||||||
ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
ChainHead func(ctx context.Context) (*types.TipSet, error)
|
ChainHead func(ctx context.Context) (*types.TipSet, error)
|
||||||
|
ChainReadObj func(context.Context, cid.Cid) ([]byte, error)
|
||||||
GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||||
MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||||
MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||||
@ -384,7 +388,7 @@ type GatewayStruct struct {
|
|||||||
|
|
||||||
type WalletStruct struct {
|
type WalletStruct struct {
|
||||||
Internal 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"`
|
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
|
||||||
WalletList func(context.Context) ([]address.Address, 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"`
|
WalletSign func(context.Context, address.Address, []byte, api.MsgMeta) (*crypto.Signature, error) `perm:"sign"`
|
||||||
@ -551,6 +555,10 @@ func (c *FullNodeStruct) ClientDataTransferUpdates(ctx context.Context) (<-chan
|
|||||||
return c.Internal.ClientDataTransferUpdates(ctx)
|
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 {
|
func (c *FullNodeStruct) ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error {
|
||||||
return c.Internal.ClientRetrieveTryRestartInsufficientFunds(ctx, paymentChannel)
|
return c.Internal.ClientRetrieveTryRestartInsufficientFunds(ctx, paymentChannel)
|
||||||
}
|
}
|
||||||
@ -631,7 +639,7 @@ func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.Chain
|
|||||||
return c.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
|
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)
|
return c.Internal.WalletNew(ctx, typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -883,10 +891,6 @@ func (c *FullNodeStruct) StateReadState(ctx context.Context, addr address.Addres
|
|||||||
return c.Internal.StateReadState(ctx, addr, tsk)
|
return c.Internal.StateReadState(ctx, addr, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FullNodeStruct) StateMsgGasCost(ctx context.Context, msgc cid.Cid, tsk types.TipSetKey) (*api.MsgGasCost, error) {
|
|
||||||
return c.Internal.StateMsgGasCost(ctx, msgc, tsk)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid, confidence uint64) (*api.MsgLookup, error) {
|
func (c *FullNodeStruct) StateWaitMsg(ctx context.Context, msgc cid.Cid, confidence uint64) (*api.MsgLookup, error) {
|
||||||
return c.Internal.StateWaitMsg(ctx, msgc, confidence)
|
return c.Internal.StateWaitMsg(ctx, msgc, confidence)
|
||||||
}
|
}
|
||||||
@ -939,7 +943,7 @@ func (c *FullNodeStruct) StateGetReceipt(ctx context.Context, msg cid.Cid, tsk t
|
|||||||
return c.Internal.StateGetReceipt(ctx, msg, tsk)
|
return c.Internal.StateGetReceipt(ctx, msg, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) {
|
func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *api.MessageMatch, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) {
|
||||||
return c.Internal.StateListMessages(ctx, match, tsk, toht)
|
return c.Internal.StateListMessages(ctx, match, tsk, toht)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -963,10 +967,14 @@ func (c *FullNodeStruct) StateDealProviderCollateralBounds(ctx context.Context,
|
|||||||
return c.Internal.StateDealProviderCollateralBounds(ctx, size, verified, tsk)
|
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)
|
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) {
|
func (c *FullNodeStruct) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) {
|
||||||
return c.Internal.StateNetworkVersion(ctx, tsk)
|
return c.Internal.StateNetworkVersion(ctx, tsk)
|
||||||
}
|
}
|
||||||
@ -1421,6 +1429,10 @@ func (w *WorkerStruct) Closing(ctx context.Context) (<-chan struct{}, error) {
|
|||||||
return w.Internal.Closing(ctx)
|
return w.Internal.Closing(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) {
|
||||||
|
return g.Internal.ChainHasObj(ctx, c)
|
||||||
|
}
|
||||||
|
|
||||||
func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
func (g GatewayStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||||
return g.Internal.ChainHead(ctx)
|
return g.Internal.ChainHead(ctx)
|
||||||
}
|
}
|
||||||
@ -1433,6 +1445,10 @@ func (g GatewayStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEp
|
|||||||
return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
|
return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
|
||||||
|
return g.Internal.ChainReadObj(ctx, c)
|
||||||
|
}
|
||||||
|
|
||||||
func (g GatewayStruct) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
func (g GatewayStruct) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
||||||
return g.Internal.GasEstimateMessageGas(ctx, msg, spec, tsk)
|
return g.Internal.GasEstimateMessageGas(ctx, msg, spec, tsk)
|
||||||
}
|
}
|
||||||
@ -1465,7 +1481,7 @@ func (g GatewayStruct) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence
|
|||||||
return g.Internal.StateWaitMsg(ctx, msg, 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)
|
return c.Internal.WalletNew(ctx, typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@ func init() {
|
|||||||
addExample(abi.RegisteredPoStProof_StackedDrgWindow32GiBV1)
|
addExample(abi.RegisteredPoStProof_StackedDrgWindow32GiBV1)
|
||||||
addExample(abi.ChainEpoch(10101))
|
addExample(abi.ChainEpoch(10101))
|
||||||
addExample(crypto.SigTypeBLS)
|
addExample(crypto.SigTypeBLS)
|
||||||
|
addExample(types.KTBLS)
|
||||||
addExample(int64(9))
|
addExample(int64(9))
|
||||||
addExample(12.3)
|
addExample(12.3)
|
||||||
addExample(123)
|
addExample(123)
|
||||||
|
@ -26,7 +26,6 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/events"
|
"github.com/filecoin-project/lotus/chain/events"
|
||||||
"github.com/filecoin-project/lotus/chain/events/state"
|
"github.com/filecoin-project/lotus/chain/events/state"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
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()
|
bm.MineBlocks()
|
||||||
|
|
||||||
// send some funds to register the receiver
|
// 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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
114
api/test/tape.go
Normal file
114
api/test/tape.go
Normal file
@ -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")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,8 +3,10 @@ package test
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
|
||||||
"github.com/multiformats/go-multiaddr"
|
"github.com/multiformats/go-multiaddr"
|
||||||
|
|
||||||
@ -12,6 +14,8 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"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/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/miner"
|
"github.com/filecoin-project/lotus/miner"
|
||||||
@ -74,6 +78,7 @@ func TestApis(t *testing.T, b APIBuilder) {
|
|||||||
t.Run("testConnectTwo", ts.testConnectTwo)
|
t.Run("testConnectTwo", ts.testConnectTwo)
|
||||||
t.Run("testMining", ts.testMining)
|
t.Run("testMining", ts.testMining)
|
||||||
t.Run("testMiningReal", ts.testMiningReal)
|
t.Run("testMiningReal", ts.testMiningReal)
|
||||||
|
t.Run("testSearchMsg", ts.testSearchMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultFullOpts(nFull int) []FullNodeOpts {
|
func DefaultFullOpts(nFull int) []FullNodeOpts {
|
||||||
@ -96,7 +101,8 @@ var FullNodeWithUpgradeAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
|
|||||||
return FullNodeOpts{
|
return FullNodeOpts{
|
||||||
Opts: func(nodes []TestNode) node.Option {
|
Opts: func(nodes []TestNode) node.Option {
|
||||||
return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
||||||
Network: build.ActorUpgradeNetworkVersion,
|
// Skip directly to tape height so precommits work.
|
||||||
|
Network: network.Version5,
|
||||||
Height: upgradeHeight,
|
Height: upgradeHeight,
|
||||||
Migration: stmgr.UpgradeActorsV2,
|
Migration: stmgr.UpgradeActorsV2,
|
||||||
}})
|
}})
|
||||||
@ -118,6 +124,49 @@ func (ts *testSuite) testVersion(t *testing.T) {
|
|||||||
require.Equal(t, v.Version, build.BuildVersion)
|
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) {
|
func (ts *testSuite) testID(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
|
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
|
||||||
|
@ -35,6 +35,7 @@ var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{
|
|||||||
"https://api.drand.sh",
|
"https://api.drand.sh",
|
||||||
"https://api2.drand.sh",
|
"https://api2.drand.sh",
|
||||||
"https://api3.drand.sh",
|
"https://api3.drand.sh",
|
||||||
|
"https://drand.cloudflare.com",
|
||||||
},
|
},
|
||||||
Relays: []string{
|
Relays: []string{
|
||||||
"/dnsaddr/api.drand.sh/",
|
"/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"}`,
|
ChainInfoJSON: `{"public_key":"8cda589f88914aa728fd183f383980b35789ce81b274e5daee1f338b77d02566ef4d3fb0098af1f844f10f9c803c1827","period":25,"genesis_time":1595348225,"hash":"e73b7dc3c4f6a236378220c0dd6aa110eb16eed26c11259606e07ee122838d4f","groupHash":"567d4785122a5a3e75a9bc9911d7ea807dd85ff76b78dc4ff06b075712898607"}`,
|
||||||
},
|
},
|
||||||
DrandIncentinet: {
|
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"}`,
|
ChainInfoJSON: `{"public_key":"8cad0c72c606ab27d36ee06de1d5b2db1faf92e447025ca37575ab3a8aac2eaae83192f846fc9e158bc738423753d000","period":30,"genesis_time":1595873820,"hash":"80c8b872c714f4c00fdd3daa465d5514049f457f01f85a4caf68cdcd394ba039","groupHash":"d9406aaed487f7af71851b4399448e311f2328923d454e971536c05398ce2d9b"}`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,8 @@ const UpgradeTapeHeight = -4
|
|||||||
var UpgradeActorsV2Height = abi.ChainEpoch(10)
|
var UpgradeActorsV2Height = abi.ChainEpoch(10)
|
||||||
var UpgradeLiftoffHeight = abi.ChainEpoch(-5)
|
var UpgradeLiftoffHeight = abi.ChainEpoch(-5)
|
||||||
|
|
||||||
|
const UpgradeKumquatHeight = -6
|
||||||
|
|
||||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||||
0: DrandMainnet,
|
0: DrandMainnet,
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,10 @@ const UpgradeTapeHeight = 45
|
|||||||
// This signals our tentative epoch for mainnet launch. Can make it later, but not earlier.
|
// This signals our tentative epoch for mainnet launch. Can make it later, but not earlier.
|
||||||
// Miners, clients, developers, custodians all need time to prepare.
|
// 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.
|
// We still have upgrades and state changes to do, but can happen after signaling timing here.
|
||||||
const UpgradeLiftoffHeight = 148888
|
const UpgradeLiftoffHeight = 22400
|
||||||
|
|
||||||
|
// TODO: Confirm epoch
|
||||||
|
const UpgradeKumquatHeight = 22450
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 30))
|
policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 30))
|
@ -25,7 +25,7 @@ const UnixfsLinksPerLevel = 1024
|
|||||||
// Consensus / Network
|
// Consensus / Network
|
||||||
|
|
||||||
const AllowableClockDriftSecs = uint64(1)
|
const AllowableClockDriftSecs = uint64(1)
|
||||||
const NewestNetworkVersion = network.Version5
|
const NewestNetworkVersion = network.Version6
|
||||||
const ActorUpgradeNetworkVersion = network.Version4
|
const ActorUpgradeNetworkVersion = network.Version4
|
||||||
|
|
||||||
// Epochs
|
// Epochs
|
||||||
|
@ -86,6 +86,7 @@ var (
|
|||||||
UpgradeTapeHeight abi.ChainEpoch = -4
|
UpgradeTapeHeight abi.ChainEpoch = -4
|
||||||
UpgradeActorsV2Height abi.ChainEpoch = 10
|
UpgradeActorsV2Height abi.ChainEpoch = 10
|
||||||
UpgradeLiftoffHeight abi.ChainEpoch = -5
|
UpgradeLiftoffHeight abi.ChainEpoch = -5
|
||||||
|
UpgradeKumquatHeight abi.ChainEpoch = -6
|
||||||
|
|
||||||
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||||
0: DrandMainnet,
|
0: DrandMainnet,
|
||||||
|
@ -29,7 +29,7 @@ func buildType() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BuildVersion is the local build version, set by build system
|
// BuildVersion is the local build version, set by build system
|
||||||
const BuildVersion = "0.9.1"
|
const BuildVersion = "1.0.0"
|
||||||
|
|
||||||
func UserVersion() string {
|
func UserVersion() string {
|
||||||
return BuildVersion + buildType() + CurrentCommit
|
return BuildVersion + buildType() + CurrentCommit
|
||||||
@ -83,7 +83,7 @@ func VersionForType(nodeType NodeType) (Version, error) {
|
|||||||
|
|
||||||
// semver versions of the rpc api exposed
|
// semver versions of the rpc api exposed
|
||||||
var (
|
var (
|
||||||
FullAPIVersion = newVer(0, 16, 0)
|
FullAPIVersion = newVer(0, 17, 0)
|
||||||
MinerAPIVersion = newVer(0, 15, 0)
|
MinerAPIVersion = newVer(0, 15, 0)
|
||||||
WorkerAPIVersion = newVer(0, 15, 0)
|
WorkerAPIVersion = newVer(0, 15, 0)
|
||||||
)
|
)
|
||||||
|
@ -2,25 +2,28 @@ package builtin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/filecoin-project/go-address"
|
"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"
|
"github.com/ipfs/go-cid"
|
||||||
"golang.org/x/xerrors"
|
"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/abi"
|
||||||
"github.com/filecoin-project/go-state-types/cbor"
|
"github.com/filecoin-project/go-state-types/cbor"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"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"
|
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||||
proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof"
|
proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof"
|
||||||
smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing"
|
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 SystemActorAddr = builtin0.SystemActorAddr
|
||||||
var BurntFundsActorAddr = builtin0.BurntFundsActorAddr
|
var BurntFundsActorAddr = builtin0.BurntFundsActorAddr
|
||||||
|
var CronActorAddr = builtin0.CronActorAddr
|
||||||
|
var SaftAddress = makeAddress("t0122")
|
||||||
var ReserveAddress = makeAddress("t090")
|
var ReserveAddress = makeAddress("t090")
|
||||||
var RootVerifierAddress = makeAddress("t080")
|
var RootVerifierAddress = makeAddress("t080")
|
||||||
|
|
||||||
|
@ -7,9 +7,9 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/exitcode"
|
"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)
|
changed, err := pre.DeadlinesChanged(cur)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -18,11 +18,7 @@ func DiffDeadlines(pre, cur State) (*DeadlinesDiff, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
numDl, err := pre.NumDeadlines()
|
dlDiff := make(DeadlinesDiff)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
dlDiff := make(DeadlinesDiff, numDl)
|
|
||||||
if err := pre.ForEachDeadline(func(idx uint64, preDl Deadline) error {
|
if err := pre.ForEachDeadline(func(idx uint64, preDl Deadline) error {
|
||||||
curDl, err := cur.LoadDeadline(idx)
|
curDl, err := cur.LoadDeadline(idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -39,12 +35,12 @@ func DiffDeadlines(pre, cur State) (*DeadlinesDiff, error) {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &dlDiff, nil
|
return dlDiff, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeadlineDiff map[uint64]*PartitionDiff
|
type DeadlineDiff map[uint64]*PartitionDiff
|
||||||
|
|
||||||
func DiffDeadline(pre, cur Deadline) (*DeadlineDiff, error) {
|
func DiffDeadline(pre, cur Deadline) (DeadlineDiff, error) {
|
||||||
changed, err := pre.PartitionsChanged(cur)
|
changed, err := pre.PartitionsChanged(cur)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -104,7 +100,7 @@ func DiffDeadline(pre, cur Deadline) (*DeadlineDiff, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &partDiff, nil
|
return partDiff, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type PartitionDiff struct {
|
type PartitionDiff struct {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package miner
|
package miner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/filecoin-project/go-state-types/big"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
@ -148,6 +149,20 @@ type MinerInfo struct {
|
|||||||
ConsensusFaultElapsed abi.ChainEpoch
|
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 {
|
type SectorExpiration struct {
|
||||||
OnTime abi.ChainEpoch
|
OnTime abi.ChainEpoch
|
||||||
|
|
||||||
@ -182,3 +197,7 @@ type LockedFunds struct {
|
|||||||
InitialPledgeRequirement abi.TokenAmount
|
InitialPledgeRequirement abi.TokenAmount
|
||||||
PreCommitDeposits 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
|
store adt.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *state0) AvailableBalance(bal abi.TokenAmount) (abi.TokenAmount, error) {
|
func (s *state0) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmount, err error) {
|
||||||
return s.GetAvailableBalance(bal), nil
|
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) {
|
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 true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.State.Deadlines.Equals(other0.Deadlines), nil
|
return !s.State.Deadlines.Equals(other0.Deadlines), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *state0) Info() (MinerInfo, error) {
|
func (s *state0) Info() (MinerInfo, error) {
|
||||||
@ -362,7 +370,7 @@ func (d *deadline0) PartitionsChanged(other Deadline) (bool, error) {
|
|||||||
return true, nil
|
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) {
|
func (d *deadline0) PostSubmissions() (bitfield.BitField, error) {
|
||||||
|
@ -45,8 +45,16 @@ type partition2 struct {
|
|||||||
store adt.Store
|
store adt.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *state2) AvailableBalance(bal abi.TokenAmount) (abi.TokenAmount, error) {
|
func (s *state2) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmount, err error) {
|
||||||
return s.GetAvailableBalance(bal)
|
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) {
|
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 true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.State.Deadlines.Equals(other2.Deadlines), nil
|
return !s.State.Deadlines.Equals(other2.Deadlines), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *state2) Info() (MinerInfo, error) {
|
func (s *state2) Info() (MinerInfo, error) {
|
||||||
@ -361,7 +369,7 @@ func (d *deadline2) PartitionsChanged(other Deadline) (bool, error) {
|
|||||||
return true, nil
|
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) {
|
func (d *deadline2) PostSubmissions() (bitfield.BitField, error) {
|
||||||
|
@ -45,6 +45,7 @@ type MessageBuilder interface {
|
|||||||
|
|
||||||
// this type is the same between v0 and v2
|
// this type is the same between v0 and v2
|
||||||
type ProposalHashData = multisig2.ProposalHashData
|
type ProposalHashData = multisig2.ProposalHashData
|
||||||
|
type ProposeReturn = multisig2.ProposeReturn
|
||||||
|
|
||||||
func txnParams(id uint64, data *ProposalHashData) ([]byte, error) {
|
func txnParams(id uint64, data *ProposalHashData) ([]byte, error) {
|
||||||
params := multisig2.TxnIDParams{ID: multisig2.TxnID(id)}
|
params := multisig2.TxnIDParams{ID: multisig2.TxnID(id)}
|
||||||
|
@ -18,7 +18,7 @@ func VersionForNetwork(version network.Version) Version {
|
|||||||
switch version {
|
switch version {
|
||||||
case network.Version0, network.Version1, network.Version2, network.Version3:
|
case network.Version0, network.Version1, network.Version2, network.Version3:
|
||||||
return Version0
|
return Version0
|
||||||
case network.Version4, network.Version5:
|
case network.Version4, network.Version5, network.Version6:
|
||||||
return Version2
|
return Version2
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unsupported network version %d", version))
|
panic(fmt.Sprintf("unsupported network version %d", version))
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestPrintGroupInfo(t *testing.T) {
|
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)
|
c, err := hclient.New(server, nil, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
cg := c.(interface {
|
cg := c.(interface {
|
||||||
|
@ -155,14 +155,14 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
|
|||||||
return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err)
|
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 {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to generate banker key: %w", err)
|
return nil, xerrors.Errorf("failed to generate banker key: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
receievers := make([]address.Address, msgsPerBlock)
|
receievers := make([]address.Address, msgsPerBlock)
|
||||||
for r := range receievers {
|
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 {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to generate receiver key: %w", err)
|
return nil, xerrors.Errorf("failed to generate receiver key: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -405,7 +405,7 @@ func circSupply(ctx context.Context, vmi *vm.VM, maddr address.Address) abi.Toke
|
|||||||
rt := unsafeVM.MakeRuntime(ctx, &types.Message{
|
rt := unsafeVM.MakeRuntime(ctx, &types.Message{
|
||||||
GasLimit: 1_000_000_000,
|
GasLimit: 1_000_000_000,
|
||||||
From: maddr,
|
From: maddr,
|
||||||
}, maddr, 0, 0, 0)
|
})
|
||||||
|
|
||||||
return rt.TotalFilCircSupply()
|
return rt.TotalFilCircSupply()
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,8 @@ var MaxUntrustedActorPendingMessages = 10
|
|||||||
|
|
||||||
var MaxNonceGap = uint64(4)
|
var MaxNonceGap = uint64(4)
|
||||||
|
|
||||||
|
var DefaultMaxFee = abi.TokenAmount(types.MustParseFIL("0.007"))
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrMessageTooBig = errors.New("message too big")
|
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) {
|
func CapGasFee(msg *types.Message, maxFee abi.TokenAmount) {
|
||||||
if maxFee.Equals(big.Zero()) {
|
if maxFee.Equals(big.Zero()) {
|
||||||
maxFee = types.NewInt(build.FilecoinPrecision / 10)
|
maxFee = DefaultMaxFee
|
||||||
}
|
}
|
||||||
|
|
||||||
gl := types.NewInt(uint64(msg.GasLimit))
|
gl := types.NewInt(uint64(msg.GasLimit))
|
||||||
@ -368,11 +370,23 @@ func New(api Provider, ds dtypes.MetadataDS, netName dtypes.NetworkName, j journ
|
|||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
if err := mp.loadLocal(); err != nil {
|
mp.curTsLk.Lock()
|
||||||
log.Errorf("loading local messages: %+v", err)
|
mp.lk.Lock()
|
||||||
}
|
|
||||||
|
|
||||||
go mp.runLoop()
|
go func() {
|
||||||
|
err := mp.loadLocal()
|
||||||
|
|
||||||
|
mp.lk.Unlock()
|
||||||
|
mp.curTsLk.Unlock()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("loading local messages: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("mpool ready")
|
||||||
|
|
||||||
|
mp.runLoop()
|
||||||
|
}()
|
||||||
|
|
||||||
return mp, nil
|
return mp, nil
|
||||||
}
|
}
|
||||||
@ -665,11 +679,12 @@ func (mp *MessagePool) addLoaded(m *types.SignedMessage) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mp.curTsLk.Lock()
|
|
||||||
defer mp.curTsLk.Unlock()
|
|
||||||
|
|
||||||
curTs := mp.curTs
|
curTs := mp.curTs
|
||||||
|
|
||||||
|
if curTs == nil {
|
||||||
|
return xerrors.Errorf("current tipset not loaded")
|
||||||
|
}
|
||||||
|
|
||||||
snonce, err := mp.getStateNonce(m.Message.From, curTs)
|
snonce, err := mp.getStateNonce(m.Message.From, curTs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("failed to look up actor state nonce: %s: %w", err, ErrSoftValidationFailure)
|
return xerrors.Errorf("failed to look up actor state nonce: %s: %w", err, ErrSoftValidationFailure)
|
||||||
@ -679,9 +694,6 @@ func (mp *MessagePool) addLoaded(m *types.SignedMessage) error {
|
|||||||
return xerrors.Errorf("minimum expected nonce is %d: %w", snonce, ErrNonceTooLow)
|
return xerrors.Errorf("minimum expected nonce is %d: %w", snonce, ErrNonceTooLow)
|
||||||
}
|
}
|
||||||
|
|
||||||
mp.lk.Lock()
|
|
||||||
defer mp.lk.Unlock()
|
|
||||||
|
|
||||||
_, err = mp.verifyMsgBeforeAdd(m, curTs, true)
|
_, err = mp.verifyMsgBeforeAdd(m, curTs, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"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/messagepool/gasguess"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/types/mock"
|
"github.com/filecoin-project/lotus/chain/types/mock"
|
||||||
@ -232,7 +231,7 @@ func TestMessagePool(t *testing.T) {
|
|||||||
|
|
||||||
a := tma.nextBlock()
|
a := tma.nextBlock()
|
||||||
|
|
||||||
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
sender, err := w.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -273,7 +272,7 @@ func TestMessagePoolMessagesInEachBlock(t *testing.T) {
|
|||||||
|
|
||||||
a := tma.nextBlock()
|
a := tma.nextBlock()
|
||||||
|
|
||||||
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
sender, err := w.WalletNew(context.Background(), types.KTBLS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -323,7 +322,7 @@ func TestRevertMessages(t *testing.T) {
|
|||||||
a := tma.nextBlock()
|
a := tma.nextBlock()
|
||||||
b := tma.nextBlock()
|
b := tma.nextBlock()
|
||||||
|
|
||||||
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
sender, err := w.WalletNew(context.Background(), types.KTBLS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -386,7 +385,7 @@ func TestPruningSimple(t *testing.T) {
|
|||||||
a := tma.nextBlock()
|
a := tma.nextBlock()
|
||||||
tma.applyBlock(t, a)
|
tma.applyBlock(t, a)
|
||||||
|
|
||||||
sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
sender, err := w.WalletNew(context.Background(), types.KTBLS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -433,7 +432,7 @@ func TestLoadLocal(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -443,7 +442,7 @@ func TestLoadLocal(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -505,7 +504,7 @@ func TestClearAll(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -515,7 +514,7 @@ func TestClearAll(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -559,7 +558,7 @@ func TestClearNonLocal(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -569,7 +568,7 @@ func TestClearNonLocal(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -620,7 +619,7 @@ func TestUpdates(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -630,7 +629,7 @@ func TestUpdates(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/crypto"
|
|
||||||
"github.com/filecoin-project/lotus/chain/messagepool/gasguess"
|
"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/lotus/chain/wallet"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
"github.com/ipfs/go-datastore"
|
"github.com/ipfs/go-datastore"
|
||||||
@ -33,7 +33,7 @@ func TestRepubMessages(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ func TestRepubMessages(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ import (
|
|||||||
logging "github.com/ipfs/go-log"
|
logging "github.com/ipfs/go-log"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"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/build"
|
||||||
"github.com/filecoin-project/lotus/chain/messagepool/gasguess"
|
"github.com/filecoin-project/lotus/chain/messagepool/gasguess"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
@ -77,7 +76,7 @@ func TestMessageChains(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -87,7 +86,7 @@ func TestMessageChains(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -315,7 +314,7 @@ func TestMessageChainSkipping(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -325,7 +324,7 @@ func TestMessageChainSkipping(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -391,7 +390,7 @@ func TestBasicMessageSelection(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -401,7 +400,7 @@ func TestBasicMessageSelection(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -535,7 +534,7 @@ func TestMessageSelectionTrimming(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -545,7 +544,7 @@ func TestMessageSelectionTrimming(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -598,7 +597,7 @@ func TestPriorityMessageSelection(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -608,7 +607,7 @@ func TestPriorityMessageSelection(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -677,7 +676,7 @@ func TestPriorityMessageSelection2(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -687,7 +686,7 @@ func TestPriorityMessageSelection2(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -746,7 +745,7 @@ func TestPriorityMessageSelection3(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -756,7 +755,7 @@ func TestPriorityMessageSelection3(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -843,7 +842,7 @@ func TestOptimalMessageSelection1(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -853,7 +852,7 @@ func TestOptimalMessageSelection1(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -910,7 +909,7 @@ func TestOptimalMessageSelection2(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -920,7 +919,7 @@ func TestOptimalMessageSelection2(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -994,7 +993,7 @@ func TestOptimalMessageSelection3(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a, err := w.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -1074,7 +1073,7 @@ func testCompetitiveMessageSelection(t *testing.T, rng *rand.Rand, getPremium fu
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a, err := w.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -1344,7 +1343,7 @@ readLoop:
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1)
|
a, err := w.WalletNew(context.Background(), types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
"github.com/filecoin-project/lotus/chain/wallet"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/crypto"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
ds_sync "github.com/ipfs/go-datastore/sync"
|
ds_sync "github.com/ipfs/go-datastore/sync"
|
||||||
@ -47,13 +46,13 @@ func TestMessageSignerSignMessage(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
w, _ := wallet.NewWallet(wallet.NewMemKeyStore())
|
w, _ := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||||
from1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
from1, err := w.WalletNew(ctx, types.KTSecp256k1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
from2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
from2, err := w.WalletNew(ctx, types.KTSecp256k1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
to1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
to1, err := w.WalletNew(ctx, types.KTSecp256k1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
to2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
to2, err := w.WalletNew(ctx, types.KTSecp256k1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
type msgSpec struct {
|
type msgSpec struct {
|
||||||
|
@ -26,16 +26,18 @@ var log = logging.Logger("statetree")
|
|||||||
|
|
||||||
// StateTree stores actors state by their ID.
|
// StateTree stores actors state by their ID.
|
||||||
type StateTree struct {
|
type StateTree struct {
|
||||||
root adt.Map
|
root adt.Map
|
||||||
version types.StateTreeVersion
|
version types.StateTreeVersion
|
||||||
info cid.Cid
|
info cid.Cid
|
||||||
Store cbor.IpldStore
|
Store cbor.IpldStore
|
||||||
|
lookupIDFun func(address.Address) (address.Address, error)
|
||||||
|
|
||||||
snaps *stateSnaps
|
snaps *stateSnaps
|
||||||
}
|
}
|
||||||
|
|
||||||
type stateSnaps struct {
|
type stateSnaps struct {
|
||||||
layers []*stateSnapLayer
|
layers []*stateSnapLayer
|
||||||
|
lastMaybeNonEmptyResolveCache int
|
||||||
}
|
}
|
||||||
|
|
||||||
type stateSnapLayer struct {
|
type stateSnapLayer struct {
|
||||||
@ -67,7 +69,12 @@ func (ss *stateSnaps) addLayer() {
|
|||||||
|
|
||||||
func (ss *stateSnaps) dropLayer() {
|
func (ss *stateSnaps) dropLayer() {
|
||||||
ss.layers[len(ss.layers)-1] = nil // allow it to be GCed
|
ss.layers[len(ss.layers)-1] = nil // allow it to be GCed
|
||||||
|
|
||||||
ss.layers = ss.layers[:len(ss.layers)-1]
|
ss.layers = ss.layers[:len(ss.layers)-1]
|
||||||
|
|
||||||
|
if ss.lastMaybeNonEmptyResolveCache == len(ss.layers) {
|
||||||
|
ss.lastMaybeNonEmptyResolveCache = len(ss.layers) - 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *stateSnaps) mergeLastLayer() {
|
func (ss *stateSnaps) mergeLastLayer() {
|
||||||
@ -86,7 +93,13 @@ func (ss *stateSnaps) mergeLastLayer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ss *stateSnaps) resolveAddress(addr address.Address) (address.Address, bool) {
|
func (ss *stateSnaps) resolveAddress(addr address.Address) (address.Address, bool) {
|
||||||
for i := len(ss.layers) - 1; i >= 0; i-- {
|
for i := ss.lastMaybeNonEmptyResolveCache; i >= 0; i-- {
|
||||||
|
if len(ss.layers[i].resolveCache) == 0 {
|
||||||
|
if ss.lastMaybeNonEmptyResolveCache == i {
|
||||||
|
ss.lastMaybeNonEmptyResolveCache = i - 1
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
resa, ok := ss.layers[i].resolveCache[addr]
|
resa, ok := ss.layers[i].resolveCache[addr]
|
||||||
if ok {
|
if ok {
|
||||||
return resa, true
|
return resa, true
|
||||||
@ -97,6 +110,7 @@ func (ss *stateSnaps) resolveAddress(addr address.Address) (address.Address, boo
|
|||||||
|
|
||||||
func (ss *stateSnaps) cacheResolveAddress(addr, resa address.Address) {
|
func (ss *stateSnaps) cacheResolveAddress(addr, resa address.Address) {
|
||||||
ss.layers[len(ss.layers)-1].resolveCache[addr] = resa
|
ss.layers[len(ss.layers)-1].resolveCache[addr] = resa
|
||||||
|
ss.lastMaybeNonEmptyResolveCache = len(ss.layers) - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *stateSnaps) getActor(addr address.Address) (*types.Actor, error) {
|
func (ss *stateSnaps) getActor(addr address.Address) (*types.Actor, error) {
|
||||||
@ -160,13 +174,15 @@ func NewStateTree(cst cbor.IpldStore, ver types.StateTreeVersion) (*StateTree, e
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &StateTree{
|
s := &StateTree{
|
||||||
root: root,
|
root: root,
|
||||||
info: info,
|
info: info,
|
||||||
version: ver,
|
version: ver,
|
||||||
Store: cst,
|
Store: cst,
|
||||||
snaps: newStateSnaps(),
|
snaps: newStateSnaps(),
|
||||||
}, nil
|
}
|
||||||
|
s.lookupIDFun = s.lookupIDinternal
|
||||||
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
|
func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
|
||||||
@ -190,13 +206,15 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &StateTree{
|
s := &StateTree{
|
||||||
root: nd,
|
root: nd,
|
||||||
info: root.Info,
|
info: root.Info,
|
||||||
version: root.Version,
|
version: root.Version,
|
||||||
Store: cst,
|
Store: cst,
|
||||||
snaps: newStateSnaps(),
|
snaps: newStateSnaps(),
|
||||||
}, nil
|
}
|
||||||
|
s.lookupIDFun = s.lookupIDinternal
|
||||||
|
return s, nil
|
||||||
default:
|
default:
|
||||||
return nil, xerrors.Errorf("unsupported state tree version: %d", root.Version)
|
return nil, xerrors.Errorf("unsupported state tree version: %d", root.Version)
|
||||||
}
|
}
|
||||||
@ -213,17 +231,7 @@ func (st *StateTree) SetActor(addr address.Address, act *types.Actor) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupID gets the ID address of this actor's `addr` stored in the `InitActor`.
|
func (st *StateTree) lookupIDinternal(addr address.Address) (address.Address, error) {
|
||||||
func (st *StateTree) LookupID(addr address.Address) (address.Address, error) {
|
|
||||||
if addr.Protocol() == address.ID {
|
|
||||||
return addr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
resa, ok := st.snaps.resolveAddress(addr)
|
|
||||||
if ok {
|
|
||||||
return resa, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
act, err := st.GetActor(init_.Address)
|
act, err := st.GetActor(init_.Address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return address.Undef, xerrors.Errorf("getting init actor: %w", err)
|
return address.Undef, xerrors.Errorf("getting init actor: %w", err)
|
||||||
@ -241,6 +249,23 @@ func (st *StateTree) LookupID(addr address.Address) (address.Address, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return address.Undef, xerrors.Errorf("resolve address %s: %w", addr, err)
|
return address.Undef, xerrors.Errorf("resolve address %s: %w", addr, err)
|
||||||
}
|
}
|
||||||
|
return a, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupID gets the ID address of this actor's `addr` stored in the `InitActor`.
|
||||||
|
func (st *StateTree) LookupID(addr address.Address) (address.Address, error) {
|
||||||
|
if addr.Protocol() == address.ID {
|
||||||
|
return addr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
resa, ok := st.snaps.resolveAddress(addr)
|
||||||
|
if ok {
|
||||||
|
return resa, nil
|
||||||
|
}
|
||||||
|
a, err := st.lookupIDFun(addr)
|
||||||
|
if err != nil {
|
||||||
|
return a, err
|
||||||
|
}
|
||||||
|
|
||||||
st.snaps.cacheResolveAddress(addr, a)
|
st.snaps.cacheResolveAddress(addr, a)
|
||||||
|
|
||||||
|
@ -73,6 +73,103 @@ func BenchmarkStateTreeSetFlush(b *testing.B) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResolveCache(t *testing.T) {
|
||||||
|
cst := cbor.NewMemCborStore()
|
||||||
|
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
nonId := address.NewForTestGetter()()
|
||||||
|
id, _ := address.NewIDAddress(1000)
|
||||||
|
|
||||||
|
st.lookupIDFun = func(a address.Address) (address.Address, error) {
|
||||||
|
if a == nonId {
|
||||||
|
return id, nil
|
||||||
|
}
|
||||||
|
return address.Undef, types.ErrActorNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
err = st.SetActor(nonId, &types.Actor{Nonce: 1})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
err = st.Snapshot(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
act, err := st.GetActor(nonId)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if act.Nonce != 1 {
|
||||||
|
t.Fatalf("expected nonce 1, got %d", act.Nonce)
|
||||||
|
}
|
||||||
|
err = st.SetActor(nonId, &types.Actor{Nonce: 2})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
act, err = st.GetActor(nonId)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if act.Nonce != 2 {
|
||||||
|
t.Fatalf("expected nonce 2, got %d", act.Nonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := st.Revert(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
st.ClearSnapshot()
|
||||||
|
}
|
||||||
|
|
||||||
|
act, err := st.GetActor(nonId)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if act.Nonce != 1 {
|
||||||
|
t.Fatalf("expected nonce 1, got %d", act.Nonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
err = st.Snapshot(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
act, err := st.GetActor(nonId)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if act.Nonce != 1 {
|
||||||
|
t.Fatalf("expected nonce 1, got %d", act.Nonce)
|
||||||
|
}
|
||||||
|
err = st.SetActor(nonId, &types.Actor{Nonce: 2})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
act, err = st.GetActor(nonId)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if act.Nonce != 2 {
|
||||||
|
t.Fatalf("expected nonce 2, got %d", act.Nonce)
|
||||||
|
}
|
||||||
|
st.ClearSnapshot()
|
||||||
|
}
|
||||||
|
|
||||||
|
act, err = st.GetActor(nonId)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if act.Nonce != 2 {
|
||||||
|
t.Fatalf("expected nonce 2, got %d", act.Nonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkStateTree10kGetActor(b *testing.B) {
|
func BenchmarkStateTree10kGetActor(b *testing.B) {
|
||||||
cst := cbor.NewMemCborStore()
|
cst := cbor.NewMemCborStore()
|
||||||
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
|
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
|
||||||
|
@ -61,7 +61,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
|
|||||||
Rand: store.NewChainRand(sm.cs, ts.Cids()),
|
Rand: store.NewChainRand(sm.cs, ts.Cids()),
|
||||||
Bstore: sm.cs.Blockstore(),
|
Bstore: sm.cs.Blockstore(),
|
||||||
Syscalls: sm.cs.VMSys(),
|
Syscalls: sm.cs.VMSys(),
|
||||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
CircSupplyCalc: sm.GetVMCirculatingSupply,
|
||||||
NtwkVersion: sm.GetNtwkVersion,
|
NtwkVersion: sm.GetNtwkVersion,
|
||||||
BaseFee: types.NewInt(0),
|
BaseFee: types.NewInt(0),
|
||||||
}
|
}
|
||||||
@ -113,6 +113,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &api.InvocResult{
|
return &api.InvocResult{
|
||||||
|
MsgCid: msg.Cid(),
|
||||||
Msg: msg,
|
Msg: msg,
|
||||||
MsgRct: &ret.MessageReceipt,
|
MsgRct: &ret.MessageReceipt,
|
||||||
ExecutionTrace: ret.ExecutionTrace,
|
ExecutionTrace: ret.ExecutionTrace,
|
||||||
@ -174,7 +175,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
|
|||||||
Rand: r,
|
Rand: r,
|
||||||
Bstore: sm.cs.Blockstore(),
|
Bstore: sm.cs.Blockstore(),
|
||||||
Syscalls: sm.cs.VMSys(),
|
Syscalls: sm.cs.VMSys(),
|
||||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
CircSupplyCalc: sm.GetVMCirculatingSupply,
|
||||||
NtwkVersion: sm.GetNtwkVersion,
|
NtwkVersion: sm.GetNtwkVersion,
|
||||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||||
}
|
}
|
||||||
@ -228,8 +229,10 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &api.InvocResult{
|
return &api.InvocResult{
|
||||||
|
MsgCid: msg.Cid(),
|
||||||
Msg: msg,
|
Msg: msg,
|
||||||
MsgRct: &ret.MessageReceipt,
|
MsgRct: &ret.MessageReceipt,
|
||||||
|
GasCost: MakeMsgGasCost(msg, ret),
|
||||||
ExecutionTrace: ret.ExecutionTrace,
|
ExecutionTrace: ret.ExecutionTrace,
|
||||||
Error: errs,
|
Error: errs,
|
||||||
Duration: ret.Duration,
|
Duration: ret.Duration,
|
||||||
|
@ -86,6 +86,10 @@ func DefaultUpgradeSchedule() UpgradeSchedule {
|
|||||||
Height: build.UpgradeLiftoffHeight,
|
Height: build.UpgradeLiftoffHeight,
|
||||||
Network: network.Version5,
|
Network: network.Version5,
|
||||||
Migration: UpgradeLiftoff,
|
Migration: UpgradeLiftoff,
|
||||||
|
}, {
|
||||||
|
Height: build.UpgradeKumquatHeight,
|
||||||
|
Network: network.Version6,
|
||||||
|
Migration: nil,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
if build.UpgradeActorsV2Height == math.MaxInt64 { // disable actors upgrade
|
if build.UpgradeActorsV2Height == math.MaxInt64 { // disable actors upgrade
|
||||||
@ -168,7 +172,7 @@ func (sm *StateManager) hasExpensiveFork(ctx context.Context, height abi.ChainEp
|
|||||||
return ok
|
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)
|
fromAct, err := tree.GetActor(from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("failed to get 'from' actor for transfer: %w", err)
|
return xerrors.Errorf("failed to get 'from' actor for transfer: %w", err)
|
||||||
@ -201,7 +205,6 @@ func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address,
|
|||||||
From: from,
|
From: from,
|
||||||
To: to,
|
To: to,
|
||||||
Value: amt,
|
Value: amt,
|
||||||
Nonce: math.MaxUint64,
|
|
||||||
}
|
}
|
||||||
fakeRct := &types.MessageReceipt{
|
fakeRct := &types.MessageReceipt{
|
||||||
ExitCode: 0,
|
ExitCode: 0,
|
||||||
@ -209,22 +212,14 @@ func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address,
|
|||||||
GasUsed: 0,
|
GasUsed: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cb(fakeMsg.Cid(), fakeMsg, &vm.ApplyRet{
|
cb(types.ExecutionTrace{
|
||||||
MessageReceipt: *fakeRct,
|
Msg: fakeMsg,
|
||||||
ActorErr: nil,
|
MsgRct: fakeRct,
|
||||||
ExecutionTrace: types.ExecutionTrace{
|
Error: "",
|
||||||
Msg: fakeMsg,
|
Duration: 0,
|
||||||
MsgRct: fakeRct,
|
GasCharges: nil,
|
||||||
Error: "",
|
Subcalls: nil,
|
||||||
Duration: 0,
|
})
|
||||||
GasCharges: nil,
|
|
||||||
Subcalls: nil,
|
|
||||||
},
|
|
||||||
Duration: 0,
|
|
||||||
GasCosts: vm.ZeroGasOutputs(),
|
|
||||||
}); err != nil {
|
|
||||||
return xerrors.Errorf("recording transfer: %w", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -265,11 +260,6 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
|||||||
return cid.Undef, xerrors.Errorf("loading state tree failed: %w", err)
|
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)
|
tree, err := sm.StateTree(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
|
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
|
||||||
@ -282,6 +272,10 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
|||||||
}
|
}
|
||||||
|
|
||||||
var transfers []transfer
|
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
|
// Take all excess funds away, put them into the reserve account
|
||||||
err = tree.ForEach(func(addr address.Address, act *types.Actor) error {
|
err = tree.ForEach(func(addr address.Address, act *types.Actor) error {
|
||||||
@ -295,7 +289,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
|||||||
if !sysAcc {
|
if !sysAcc {
|
||||||
transfers = append(transfers, transfer{
|
transfers = append(transfers, transfer{
|
||||||
From: addr,
|
From: addr,
|
||||||
To: ReserveAddress,
|
To: builtin.ReserveAddress,
|
||||||
Amt: act.Balance,
|
Amt: act.Balance,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -317,11 +311,13 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
|||||||
available = st.GetAvailableBalance(act.Balance)
|
available = st.GetAvailableBalance(act.Balance)
|
||||||
}
|
}
|
||||||
|
|
||||||
transfers = append(transfers, transfer{
|
if !available.IsZero() {
|
||||||
From: addr,
|
transfers = append(transfers, transfer{
|
||||||
To: ReserveAddress,
|
From: addr,
|
||||||
Amt: available,
|
To: builtin.ReserveAddress,
|
||||||
})
|
Amt: available,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -331,7 +327,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
|||||||
|
|
||||||
// Execute transfers from previous step
|
// Execute transfers from previous step
|
||||||
for _, t := range transfers {
|
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)
|
return cid.Undef, xerrors.Errorf("transfer %s %s->%s failed: %w", t.Amt, t.From, t.To, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -370,7 +366,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
|||||||
nbalance := big.Min(prevBalance, AccountCap)
|
nbalance := big.Min(prevBalance, AccountCap)
|
||||||
if nbalance.Sign() != 0 {
|
if nbalance.Sign() != 0 {
|
||||||
transfersBack = append(transfersBack, transfer{
|
transfersBack = append(transfersBack, transfer{
|
||||||
From: ReserveAddress,
|
From: builtin.ReserveAddress,
|
||||||
To: addr,
|
To: addr,
|
||||||
Amt: nbalance,
|
Amt: nbalance,
|
||||||
})
|
})
|
||||||
@ -397,7 +393,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
|||||||
|
|
||||||
mfunds := minerFundsAlloc(power, totalPower)
|
mfunds := minerFundsAlloc(power, totalPower)
|
||||||
transfersBack = append(transfersBack, transfer{
|
transfersBack = append(transfersBack, transfer{
|
||||||
From: ReserveAddress,
|
From: builtin.ReserveAddress,
|
||||||
To: minfo.Worker,
|
To: minfo.Worker,
|
||||||
Amt: mfunds,
|
Amt: mfunds,
|
||||||
})
|
})
|
||||||
@ -417,7 +413,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
|||||||
|
|
||||||
if lbsectors.Length() > 0 {
|
if lbsectors.Length() > 0 {
|
||||||
transfersBack = append(transfersBack, transfer{
|
transfersBack = append(transfersBack, transfer{
|
||||||
From: ReserveAddress,
|
From: builtin.ReserveAddress,
|
||||||
To: minfo.Worker,
|
To: minfo.Worker,
|
||||||
Amt: BaseMinerBalance,
|
Amt: BaseMinerBalance,
|
||||||
})
|
})
|
||||||
@ -434,7 +430,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, t := range transfersBack {
|
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)
|
return cid.Undef, xerrors.Errorf("transfer %s %s->%s failed: %w", t.Amt, t.From, t.To, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -444,7 +440,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("failed to load burnt funds actor: %w", err)
|
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)
|
return cid.Undef, xerrors.Errorf("failed to unburn funds: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,7 +456,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
|||||||
}
|
}
|
||||||
|
|
||||||
difference := types.BigSub(DesiredReimbursementBalance, reimb.Balance)
|
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)
|
return cid.Undef, xerrors.Errorf("failed to top up reimbursement account: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,6 +475,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)
|
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: nil,
|
||||||
|
}); err != nil {
|
||||||
|
return cid.Undef, xerrors.Errorf("recording transfers: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return tree.Flush(ctx)
|
return tree.Flush(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,12 +548,12 @@ func UpgradeIgnition(ctx context.Context, sm *StateManager, cb ExecCallback, roo
|
|||||||
return cid.Undef, xerrors.Errorf("resetting genesis msig start epochs: %w", err)
|
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 {
|
if err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("splitting first msig: %w", err)
|
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 {
|
if err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("splitting second msig: %w", err)
|
return cid.Undef, xerrors.Errorf("splitting second msig: %w", err)
|
||||||
}
|
}
|
||||||
@ -545,12 +574,7 @@ func UpgradeRefuel(ctx context.Context, sm *StateManager, cb ExecCallback, root
|
|||||||
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
|
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, err := address.NewFromString("t0122")
|
err = resetMultisigVesting(ctx, store, tree, builtin.SaftAddress, 0, 0, big.Zero())
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, xerrors.Errorf("getting address: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = resetMultisigVesting(ctx, store, tree, addr, 0, 0, big.Zero())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err)
|
return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err)
|
||||||
}
|
}
|
||||||
@ -655,7 +679,7 @@ func setNetworkName(ctx context.Context, store adt.Store, tree *state.StateTree,
|
|||||||
return nil
|
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 {
|
if portions < 1 {
|
||||||
return xerrors.Errorf("cannot split into 0 portions")
|
return xerrors.Errorf("cannot split into 0 portions")
|
||||||
}
|
}
|
||||||
@ -724,6 +748,11 @@ func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Add
|
|||||||
}
|
}
|
||||||
|
|
||||||
i := uint64(0)
|
i := uint64(0)
|
||||||
|
subcalls := make([]types.ExecutionTrace, 0, portions)
|
||||||
|
transferCb := func(trace types.ExecutionTrace) {
|
||||||
|
subcalls = append(subcalls, trace)
|
||||||
|
}
|
||||||
|
|
||||||
for i < portions {
|
for i < portions {
|
||||||
keyAddr, err := makeKeyAddr(addr, i)
|
keyAddr, err := makeKeyAddr(addr, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -740,13 +769,46 @@ func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Add
|
|||||||
return xerrors.Errorf("setting new msig actor state: %w", err)
|
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)
|
return xerrors.Errorf("transferring split msig balance: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
i++
|
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: nil,
|
||||||
|
}); err != nil {
|
||||||
|
return xerrors.Errorf("recording transfers: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,11 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
"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"
|
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
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 {
|
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 {
|
return func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
|
||||||
ir := &api.InvocResult{
|
ir := &api.InvocResult{
|
||||||
|
MsgCid: mcid,
|
||||||
Msg: msg,
|
Msg: msg,
|
||||||
MsgRct: &ret.MessageReceipt,
|
MsgRct: &ret.MessageReceipt,
|
||||||
ExecutionTrace: ret.ExecutionTrace,
|
ExecutionTrace: ret.ExecutionTrace,
|
||||||
@ -203,6 +209,9 @@ func traceFunc(trace *[]*api.InvocResult) func(mcid cid.Cid, msg *types.Message,
|
|||||||
if ret.ActorErr != nil {
|
if ret.ActorErr != nil {
|
||||||
ir.Error = ret.ActorErr.Error()
|
ir.Error = ret.ActorErr.Error()
|
||||||
}
|
}
|
||||||
|
if ret.GasCosts != nil {
|
||||||
|
ir.GasCost = MakeMsgGasCost(msg, ret)
|
||||||
|
}
|
||||||
*trace = append(*trace, ir)
|
*trace = append(*trace, ir)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -229,7 +238,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
|
|||||||
Rand: r,
|
Rand: r,
|
||||||
Bstore: sm.cs.Blockstore(),
|
Bstore: sm.cs.Blockstore(),
|
||||||
Syscalls: sm.cs.VMSys(),
|
Syscalls: sm.cs.VMSys(),
|
||||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
CircSupplyCalc: sm.GetVMCirculatingSupply,
|
||||||
NtwkVersion: sm.GetNtwkVersion,
|
NtwkVersion: sm.GetNtwkVersion,
|
||||||
BaseFee: baseFee,
|
BaseFee: baseFee,
|
||||||
}
|
}
|
||||||
@ -242,17 +251,12 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
|
|||||||
return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err)
|
return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
runCron := func() error {
|
runCron := func(epoch abi.ChainEpoch) error {
|
||||||
// TODO: this nonce-getting is a tiny bit ugly
|
|
||||||
ca, err := vmi.StateTree().GetActor(builtin0.SystemActorAddr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cronMsg := &types.Message{
|
cronMsg := &types.Message{
|
||||||
To: builtin0.CronActorAddr,
|
To: builtin0.CronActorAddr,
|
||||||
From: builtin0.SystemActorAddr,
|
From: builtin0.SystemActorAddr,
|
||||||
Nonce: ca.Nonce,
|
Nonce: uint64(epoch),
|
||||||
Value: types.NewInt(0),
|
Value: types.NewInt(0),
|
||||||
GasFeeCap: types.NewInt(0),
|
GasFeeCap: types.NewInt(0),
|
||||||
GasPremium: types.NewInt(0),
|
GasPremium: types.NewInt(0),
|
||||||
@ -279,7 +283,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
|
|||||||
for i := parentEpoch; i < epoch; i++ {
|
for i := parentEpoch; i < epoch; i++ {
|
||||||
if i > parentEpoch {
|
if i > parentEpoch {
|
||||||
// run cron for null rounds if any
|
// run cron for null rounds if any
|
||||||
if err := runCron(); err != nil {
|
if err := runCron(i); err != nil {
|
||||||
return cid.Undef, cid.Undef, err
|
return cid.Undef, cid.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,7 +312,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
|
|||||||
}
|
}
|
||||||
|
|
||||||
var receipts []cbg.CBORMarshaler
|
var receipts []cbg.CBORMarshaler
|
||||||
processedMsgs := map[cid.Cid]bool{}
|
processedMsgs := make(map[cid.Cid]struct{})
|
||||||
for _, b := range bms {
|
for _, b := range bms {
|
||||||
penalty := types.NewInt(0)
|
penalty := types.NewInt(0)
|
||||||
gasReward := big.Zero()
|
gasReward := big.Zero()
|
||||||
@ -332,7 +336,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
|
|||||||
return cid.Undef, cid.Undef, err
|
return cid.Undef, cid.Undef, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
processedMsgs[m.Cid()] = true
|
processedMsgs[m.Cid()] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
params, err := actors.SerializeParams(&reward.AwardBlockRewardParams{
|
params, err := actors.SerializeParams(&reward.AwardBlockRewardParams{
|
||||||
@ -345,15 +349,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)
|
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{
|
rwMsg := &types.Message{
|
||||||
From: builtin0.SystemActorAddr,
|
From: builtin0.SystemActorAddr,
|
||||||
To: reward.Address,
|
To: reward.Address,
|
||||||
Nonce: sysAct.Nonce,
|
Nonce: uint64(epoch),
|
||||||
Value: types.NewInt(0),
|
Value: types.NewInt(0),
|
||||||
GasFeeCap: types.NewInt(0),
|
GasFeeCap: types.NewInt(0),
|
||||||
GasPremium: types.NewInt(0),
|
GasPremium: types.NewInt(0),
|
||||||
@ -376,7 +375,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
|
return cid.Cid{}, cid.Cid{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,12 +429,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, ts *types.TipSet
|
|||||||
parentEpoch = parent.Height
|
parentEpoch = parent.Height
|
||||||
}
|
}
|
||||||
|
|
||||||
cids := make([]cid.Cid, len(blks))
|
r := store.NewChainRand(sm.cs, ts.Cids())
|
||||||
for i, v := range blks {
|
|
||||||
cids[i] = v.Cid()
|
|
||||||
}
|
|
||||||
|
|
||||||
r := store.NewChainRand(sm.cs, cids)
|
|
||||||
|
|
||||||
blkmsgs, err := sm.cs.BlockMsgsForTipset(ts)
|
blkmsgs, err := sm.cs.BlockMsgsForTipset(ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -733,7 +727,7 @@ func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet
|
|||||||
}
|
}
|
||||||
|
|
||||||
if r != nil {
|
if r != nil {
|
||||||
return pts, r, foundMsg, nil
|
return cur, r, foundMsg, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1294,7 +1288,16 @@ func GetFilBurnt(ctx context.Context, st *state.StateTree) (abi.TokenAmount, err
|
|||||||
return burnt.Balance, nil
|
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()
|
sm.genesisMsigLk.Lock()
|
||||||
defer sm.genesisMsigLk.Unlock()
|
defer sm.genesisMsigLk.Unlock()
|
||||||
if sm.preIgnitionGenInfos == nil {
|
if sm.preIgnitionGenInfos == nil {
|
||||||
@ -1357,12 +1360,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) {
|
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 {
|
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 {
|
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,
|
Rand: r,
|
||||||
Bstore: sm.cs.Blockstore(),
|
Bstore: sm.cs.Blockstore(),
|
||||||
Syscalls: sm.cs.VMSys(),
|
Syscalls: sm.cs.VMSys(),
|
||||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
CircSupplyCalc: sm.GetVMCirculatingSupply,
|
||||||
NtwkVersion: sm.GetNtwkVersion,
|
NtwkVersion: sm.GetNtwkVersion,
|
||||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||||
}
|
}
|
||||||
@ -701,3 +701,16 @@ func CheckTotalFIL(ctx context.Context, sm *StateManager, ts *types.TipSet) (abi
|
|||||||
|
|
||||||
return sum, nil
|
return sum, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MakeMsgGasCost(msg *types.Message, ret *vm.ApplyRet) api.MsgGasCost {
|
||||||
|
return api.MsgGasCost{
|
||||||
|
Message: msg.Cid(),
|
||||||
|
GasUsed: big.NewInt(ret.GasUsed),
|
||||||
|
BaseFeeBurn: ret.GasCosts.BaseFeeBurn,
|
||||||
|
OverEstimationBurn: ret.GasCosts.OverEstimationBurn,
|
||||||
|
MinerPenalty: ret.GasCosts.MinerPenalty,
|
||||||
|
MinerTip: ret.GasCosts.MinerTip,
|
||||||
|
Refund: ret.GasCosts.Refund,
|
||||||
|
TotalCost: big.Sub(msg.RequiredFunds(), ret.GasCosts.Refund),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -37,6 +37,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/lib/bufbstore"
|
"github.com/filecoin-project/lotus/lib/bufbstore"
|
||||||
"github.com/filecoin-project/lotus/lib/sigs"
|
"github.com/filecoin-project/lotus/lib/sigs"
|
||||||
"github.com/filecoin-project/lotus/metrics"
|
"github.com/filecoin-project/lotus/metrics"
|
||||||
|
"github.com/filecoin-project/lotus/node/impl/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
var log = logging.Logger("sub")
|
var log = logging.Logger("sub")
|
||||||
@ -44,6 +45,13 @@ var log = logging.Logger("sub")
|
|||||||
var ErrSoftFailure = errors.New("soft validation failure")
|
var ErrSoftFailure = errors.New("soft validation failure")
|
||||||
var ErrInsufficientPower = errors.New("incoming block's miner does not have minimum power")
|
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) {
|
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
|
// Timeout after (block time + propagation delay). This is useless at
|
||||||
// this point.
|
// this point.
|
||||||
@ -168,6 +176,9 @@ func fetchCids(
|
|||||||
|
|
||||||
cidIndex := make(map[cid.Cid]int)
|
cidIndex := make(map[cid.Cid]int)
|
||||||
for i, c := range cids {
|
for i, c := range cids {
|
||||||
|
if c.Prefix() != msgCidPrefix {
|
||||||
|
return fmt.Errorf("invalid msg CID: %s", c)
|
||||||
|
}
|
||||||
cidIndex[c] = i
|
cidIndex[c] = i
|
||||||
}
|
}
|
||||||
if len(cids) != len(cidIndex) {
|
if len(cids) != len(cidIndex) {
|
||||||
|
@ -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)
|
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
|
// TODO: IMPORTANT(GARBAGE). These message puts and the msgmeta
|
||||||
// computation need to go into the 'temporary' side of the blockstore when
|
// computation need to go into the 'temporary' side of the blockstore when
|
||||||
// we implement that
|
// 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.
|
// Compute the root CID of the combined message trie.
|
||||||
smroot, err := computeMsgMeta(bs, bcids, scids)
|
smroot, err := computeMsgMeta(cst, bcids, scids)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("validating msgmeta, compute failed: %w", err)
|
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)
|
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 {
|
// Finally, flush.
|
||||||
_, err := store.PutMessage(blockstore, m)
|
return vm.Copy(context.TODO(), blockstore, syncer.store.Blockstore(), smroot)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (syncer *Syncer) LocalPeer() peer.ID {
|
func (syncer *Syncer) LocalPeer() peer.ID {
|
||||||
@ -1064,8 +1061,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cst := cbor.NewCborStore(syncer.store.Blockstore())
|
st, err := state.LoadStateTree(syncer.store.Store(ctx), stateroot)
|
||||||
st, err := state.LoadStateTree(cst, stateroot)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("failed to load base state tree: %w", err)
|
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
|
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 {
|
for i, m := range b.BlsMessages {
|
||||||
if err := checkMsg(m); err != nil {
|
if err := checkMsg(m); err != nil {
|
||||||
return xerrors.Errorf("block had invalid bls message at index %d: %w", i, err)
|
return xerrors.Errorf("block had invalid bls message at index %d: %w", i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c := cbg.CborCid(m.Cid())
|
c, err := store.PutMessage(tmpbs, m)
|
||||||
if err := bmArr.Set(uint64(i), &c); err != nil {
|
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)
|
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 {
|
for i, m := range b.SecpkMessages {
|
||||||
if err := checkMsg(m); err != nil {
|
if err := checkMsg(m); err != nil {
|
||||||
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
|
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
|
||||||
@ -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)
|
return xerrors.Errorf("secpk message %s has invalid signature: %w", m.Cid(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c := cbg.CborCid(m.Cid())
|
c, err := store.PutMessage(tmpbs, m)
|
||||||
if err := smArr.Set(uint64(i), &c); err != nil {
|
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)
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mrcid, err := cst.Put(ctx, &types.MsgMeta{
|
mrcid, err := tmpstore.Put(ctx, &types.MsgMeta{
|
||||||
BlsMessages: bmroot,
|
BlsMessages: bmroot,
|
||||||
SecpkMessages: smroot,
|
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 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 {
|
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 {
|
func (syncer *Syncer) syncMessagesAndCheckState(ctx context.Context, headers []*types.TipSet) error {
|
||||||
ss := extractSyncState(ctx)
|
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 {
|
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()))
|
log.Debugw("validating tipset", "height", fts.TipSet().Height(), "size", len(fts.TipSet().Cids()))
|
||||||
|
@ -81,5 +81,14 @@ func ParseFIL(s string) (FIL, error) {
|
|||||||
return FIL{r.Num()}, nil
|
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.TextMarshaler = (*FIL)(nil)
|
||||||
var _ encoding.TextUnmarshaler = (*FIL)(nil)
|
var _ encoding.TextUnmarshaler = (*FIL)(nil)
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -9,9 +12,50 @@ var (
|
|||||||
ErrKeyExists = fmt.Errorf("key already exists")
|
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
|
// KeyInfo is used for storing keys in KeyStore
|
||||||
type KeyInfo struct {
|
type KeyInfo struct {
|
||||||
Type string
|
Type KeyType
|
||||||
PrivateKey []byte
|
PrivateKey []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
@ -106,6 +107,20 @@ func (m *Message) Cid() cid.Cid {
|
|||||||
return b.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 {
|
func (m *Message) RequiredFunds() BigInt {
|
||||||
return BigMul(m.GasFeeCap, NewInt(uint64(m.GasLimit)))
|
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
|
// since prices might vary with time, this is technically semantic validation
|
||||||
if m.GasLimit < minGas {
|
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
|
return nil
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
"github.com/filecoin-project/go-state-types/big"
|
||||||
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -70,3 +73,66 @@ func TestEqualCall(t *testing.T) {
|
|||||||
require.True(t, m1.EqualCall(m3))
|
require.True(t, m1.EqualCall(m3))
|
||||||
require.False(t, m1.EqualCall(m4))
|
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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
"github.com/filecoin-project/go-state-types/crypto"
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
@ -62,8 +63,29 @@ func (sm *SignedMessage) Serialize() ([]byte, error) {
|
|||||||
return buf.Bytes(), nil
|
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 {
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"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/actors/policy"
|
||||||
"github.com/filecoin-project/lotus/chain/gen"
|
"github.com/filecoin-project/lotus/chain/gen"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
@ -62,7 +61,7 @@ func MakeMessageSigningVectors() []vectors.MessageSigningVector {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
blsk, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
blsk, err := w.WalletNew(context.Background(), types.KTBLS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -86,7 +85,7 @@ func MakeMessageSigningVectors() []vectors.MessageSigningVector {
|
|||||||
Signature: &bmsg.Signature,
|
Signature: &bmsg.Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
secpk, err := w.WalletNew(context.Background(), crypto.SigTypeBLS)
|
secpk, err := w.WalletNew(context.Background(), types.KTBLS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,7 @@ type Runtime struct {
|
|||||||
originNonce uint64
|
originNonce uint64
|
||||||
|
|
||||||
executionTrace types.ExecutionTrace
|
executionTrace types.ExecutionTrace
|
||||||
|
depth uint64
|
||||||
numActorsCreated uint64
|
numActorsCreated uint64
|
||||||
allowInternal bool
|
allowInternal bool
|
||||||
callerValidated bool
|
callerValidated bool
|
||||||
|
@ -38,6 +38,8 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/lib/bufbstore"
|
"github.com/filecoin-project/lotus/lib/bufbstore"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const MaxCallDepth = 4096
|
||||||
|
|
||||||
var log = logging.Logger("vm")
|
var log = logging.Logger("vm")
|
||||||
var actorLog = logging.Logger("actors")
|
var actorLog = logging.Logger("actors")
|
||||||
var gasOnActorExec = newGasCharge("OnActorExec", 0, 0)
|
var gasOnActorExec = newGasCharge("OnActorExec", 0, 0)
|
||||||
@ -97,24 +99,37 @@ func (bs *gasChargingBlocks) Put(blk block.Block) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin address.Address, originNonce uint64, usedGas int64, nac uint64) *Runtime {
|
func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, parent *Runtime) *Runtime {
|
||||||
rt := &Runtime{
|
rt := &Runtime{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
vm: vm,
|
vm: vm,
|
||||||
state: vm.cstate,
|
state: vm.cstate,
|
||||||
origin: origin,
|
origin: msg.From,
|
||||||
originNonce: originNonce,
|
originNonce: msg.Nonce,
|
||||||
height: vm.blockHeight,
|
height: vm.blockHeight,
|
||||||
|
|
||||||
gasUsed: usedGas,
|
gasUsed: 0,
|
||||||
gasAvailable: msg.GasLimit,
|
gasAvailable: msg.GasLimit,
|
||||||
numActorsCreated: nac,
|
depth: 0,
|
||||||
|
numActorsCreated: 0,
|
||||||
pricelist: PricelistByEpoch(vm.blockHeight),
|
pricelist: PricelistByEpoch(vm.blockHeight),
|
||||||
allowInternal: true,
|
allowInternal: true,
|
||||||
callerValidated: false,
|
callerValidated: false,
|
||||||
executionTrace: types.ExecutionTrace{Msg: msg},
|
executionTrace: types.ExecutionTrace{Msg: msg},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if parent != nil {
|
||||||
|
rt.gasUsed = parent.gasUsed
|
||||||
|
rt.origin = parent.origin
|
||||||
|
rt.originNonce = parent.originNonce
|
||||||
|
rt.numActorsCreated = parent.numActorsCreated
|
||||||
|
rt.depth = parent.depth + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if rt.depth > MaxCallDepth && rt.NetworkVersion() >= network.Version6 {
|
||||||
|
rt.Abortf(exitcode.SysErrForbidden, "message execution exceeds call depth")
|
||||||
|
}
|
||||||
|
|
||||||
rt.cst = &cbor.BasicIpldStore{
|
rt.cst = &cbor.BasicIpldStore{
|
||||||
Blocks: &gasChargingBlocks{rt.chargeGasFunc(2), rt.pricelist, vm.cst.Blocks},
|
Blocks: &gasChargingBlocks{rt.chargeGasFunc(2), rt.pricelist, vm.cst.Blocks},
|
||||||
Atlas: vm.cst.Atlas,
|
Atlas: vm.cst.Atlas,
|
||||||
@ -148,8 +163,8 @@ type UnsafeVM struct {
|
|||||||
VM *VM
|
VM *VM
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message, origin address.Address, originNonce uint64, usedGas int64, nac uint64) *Runtime {
|
func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message) *Runtime {
|
||||||
return vm.VM.makeRuntime(ctx, msg, origin, originNonce, usedGas, nac)
|
return vm.VM.makeRuntime(ctx, msg, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
type CircSupplyCalculator func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error)
|
type CircSupplyCalculator func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error)
|
||||||
@ -214,7 +229,7 @@ type ApplyRet struct {
|
|||||||
ActorErr aerrors.ActorError
|
ActorErr aerrors.ActorError
|
||||||
ExecutionTrace types.ExecutionTrace
|
ExecutionTrace types.ExecutionTrace
|
||||||
Duration time.Duration
|
Duration time.Duration
|
||||||
GasCosts GasOutputs
|
GasCosts *GasOutputs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
|
func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
|
||||||
@ -224,18 +239,7 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
|
|||||||
|
|
||||||
st := vm.cstate
|
st := vm.cstate
|
||||||
|
|
||||||
origin := msg.From
|
rt := vm.makeRuntime(ctx, msg, parent)
|
||||||
on := msg.Nonce
|
|
||||||
var nac uint64 = 0
|
|
||||||
var gasUsed int64
|
|
||||||
if parent != nil {
|
|
||||||
gasUsed = parent.gasUsed
|
|
||||||
origin = parent.origin
|
|
||||||
on = parent.originNonce
|
|
||||||
nac = parent.numActorsCreated
|
|
||||||
}
|
|
||||||
|
|
||||||
rt := vm.makeRuntime(ctx, msg, origin, on, gasUsed, nac)
|
|
||||||
if EnableGasTracing {
|
if EnableGasTracing {
|
||||||
rt.lastGasChargeTime = start
|
rt.lastGasChargeTime = start
|
||||||
if parent != nil {
|
if parent != nil {
|
||||||
@ -361,7 +365,7 @@ func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*Ap
|
|||||||
},
|
},
|
||||||
ActorErr: actorErr,
|
ActorErr: actorErr,
|
||||||
ExecutionTrace: rt.executionTrace,
|
ExecutionTrace: rt.executionTrace,
|
||||||
GasCosts: GasOutputs{},
|
GasCosts: nil,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, actorErr
|
}, actorErr
|
||||||
}
|
}
|
||||||
@ -397,7 +401,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
|
|||||||
ExitCode: exitcode.SysErrOutOfGas,
|
ExitCode: exitcode.SysErrOutOfGas,
|
||||||
GasUsed: 0,
|
GasUsed: 0,
|
||||||
},
|
},
|
||||||
GasCosts: gasOutputs,
|
GasCosts: &gasOutputs,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -417,7 +421,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
|
|||||||
GasUsed: 0,
|
GasUsed: 0,
|
||||||
},
|
},
|
||||||
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "actor not found: %s", msg.From),
|
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "actor not found: %s", msg.From),
|
||||||
GasCosts: gasOutputs,
|
GasCosts: &gasOutputs,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -434,7 +438,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
|
|||||||
GasUsed: 0,
|
GasUsed: 0,
|
||||||
},
|
},
|
||||||
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "send from not account actor: %s", fromActor.Code),
|
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "send from not account actor: %s", fromActor.Code),
|
||||||
GasCosts: gasOutputs,
|
GasCosts: &gasOutputs,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -450,7 +454,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
|
|||||||
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
|
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
|
||||||
"actor nonce invalid: msg:%d != state:%d", msg.Nonce, fromActor.Nonce),
|
"actor nonce invalid: msg:%d != state:%d", msg.Nonce, fromActor.Nonce),
|
||||||
|
|
||||||
GasCosts: gasOutputs,
|
GasCosts: &gasOutputs,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -466,7 +470,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
|
|||||||
},
|
},
|
||||||
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
|
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
|
||||||
"actor balance less than needed: %s < %s", types.FIL(fromActor.Balance), types.FIL(gascost)),
|
"actor balance less than needed: %s < %s", types.FIL(fromActor.Balance), types.FIL(gascost)),
|
||||||
GasCosts: gasOutputs,
|
GasCosts: &gasOutputs,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -560,7 +564,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
|
|||||||
},
|
},
|
||||||
ActorErr: actorErr,
|
ActorErr: actorErr,
|
||||||
ExecutionTrace: rt.executionTrace,
|
ExecutionTrace: rt.executionTrace,
|
||||||
GasCosts: gasOutputs,
|
GasCosts: &gasOutputs,
|
||||||
Duration: time.Since(start),
|
Duration: time.Since(start),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,17 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/lib/sigs"
|
"github.com/filecoin-project/lotus/lib/sigs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GenerateKey(typ crypto.SigType) (*Key, error) {
|
func GenerateKey(typ types.KeyType) (*Key, error) {
|
||||||
pk, err := sigs.Generate(typ)
|
ctyp := ActSigType(typ)
|
||||||
|
if ctyp == crypto.SigTypeUnknown {
|
||||||
|
return nil, xerrors.Errorf("unknown sig type: %s", typ)
|
||||||
|
}
|
||||||
|
pk, err := sigs.Generate(ctyp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ki := types.KeyInfo{
|
ki := types.KeyInfo{
|
||||||
Type: kstoreSigType(typ),
|
Type: typ,
|
||||||
PrivateKey: pk,
|
PrivateKey: pk,
|
||||||
}
|
}
|
||||||
return NewKey(ki)
|
return NewKey(ki)
|
||||||
@ -41,41 +45,30 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch k.Type {
|
switch k.Type {
|
||||||
case KTSecp256k1:
|
case types.KTSecp256k1:
|
||||||
k.Address, err = address.NewSecp256k1Address(k.PublicKey)
|
k.Address, err = address.NewSecp256k1Address(k.PublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
|
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
|
||||||
}
|
}
|
||||||
case KTBLS:
|
case types.KTBLS:
|
||||||
k.Address, err = address.NewBLSAddress(k.PublicKey)
|
k.Address, err = address.NewBLSAddress(k.PublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("converting BLS to address: %w", err)
|
return nil, xerrors.Errorf("converting BLS to address: %w", err)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, xerrors.Errorf("unknown key type")
|
return nil, xerrors.Errorf("unsupported key type: %s", k.Type)
|
||||||
}
|
}
|
||||||
return k, nil
|
return k, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func kstoreSigType(typ crypto.SigType) string {
|
func ActSigType(typ types.KeyType) crypto.SigType {
|
||||||
switch typ {
|
switch typ {
|
||||||
case crypto.SigTypeBLS:
|
case types.KTBLS:
|
||||||
return KTBLS
|
|
||||||
case crypto.SigTypeSecp256k1:
|
|
||||||
return KTSecp256k1
|
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ActSigType(typ string) crypto.SigType {
|
|
||||||
switch typ {
|
|
||||||
case KTBLS:
|
|
||||||
return crypto.SigTypeBLS
|
return crypto.SigTypeBLS
|
||||||
case KTSecp256k1:
|
case types.KTSecp256k1:
|
||||||
return crypto.SigTypeSecp256k1
|
return crypto.SigTypeSecp256k1
|
||||||
default:
|
default:
|
||||||
return 0
|
return crypto.SigTypeUnknown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
242
chain/wallet/ledger/ledger.go
Normal file
242
chain/wallet/ledger/ledger.go
Normal file
@ -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())
|
||||||
|
}
|
170
chain/wallet/multi.go
Normal file
170
chain/wallet/multi.go
Normal file
@ -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
|
return &RemoteWallet{wapi}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *RemoteWallet) Get() api.WalletAPI {
|
||||||
|
if w == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
@ -26,8 +26,6 @@ const (
|
|||||||
KNamePrefix = "wallet-"
|
KNamePrefix = "wallet-"
|
||||||
KTrashPrefix = "trash-"
|
KTrashPrefix = "trash-"
|
||||||
KDefault = "default"
|
KDefault = "default"
|
||||||
KTBLS = "bls"
|
|
||||||
KTSecp256k1 = "secp256k1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type LocalWallet struct {
|
type LocalWallet struct {
|
||||||
@ -236,7 +234,7 @@ func (w *LocalWallet) SetDefault(a address.Address) error {
|
|||||||
return nil
|
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()
|
w.lk.Lock()
|
||||||
defer w.lk.Unlock()
|
defer w.lk.Unlock()
|
||||||
|
|
||||||
@ -300,6 +298,14 @@ func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) er
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *LocalWallet) Get() api.WalletAPI {
|
||||||
|
if w == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
var _ api.WalletAPI = &LocalWallet{}
|
var _ api.WalletAPI = &LocalWallet{}
|
||||||
|
|
||||||
func swapMainnetForTestnetPrefix(addr string) (string, error) {
|
func swapMainnetForTestnetPrefix(addr string) (string, error) {
|
||||||
@ -312,3 +318,16 @@ func swapMainnetForTestnetPrefix(addr string) (string, error) {
|
|||||||
aChars[0] = prefixRunes[0]
|
aChars[0] = prefixRunes[0]
|
||||||
return string(aChars), nil
|
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
|
||||||
|
67
cli/chain.go
67
cli/chain.go
@ -3,6 +3,7 @@ package cli
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -53,6 +54,7 @@ var chainCmd = &cli.Command{
|
|||||||
slashConsensusFault,
|
slashConsensusFault,
|
||||||
chainGasPriceCmd,
|
chainGasPriceCmd,
|
||||||
chainInspectUsage,
|
chainInspectUsage,
|
||||||
|
chainDecodeCmd,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1234,3 +1236,68 @@ var chainGasPriceCmd = &cli.Command{
|
|||||||
return nil
|
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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -82,6 +83,7 @@ var clientCmd = &cli.Command{
|
|||||||
WithCategory("util", clientCarGenCmd),
|
WithCategory("util", clientCarGenCmd),
|
||||||
WithCategory("util", clientInfoCmd),
|
WithCategory("util", clientInfoCmd),
|
||||||
WithCategory("util", clientListTransfers),
|
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{
|
var clientListTransfers = &cli.Command{
|
||||||
Name: "list-transfers",
|
Name: "list-transfers",
|
||||||
Usage: "List ongoing data transfers for deals",
|
Usage: "List ongoing data transfers for deals",
|
||||||
|
278
cli/multisig.go
278
cli/multisig.go
@ -5,7 +5,6 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -24,6 +23,7 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
|
cid "github.com/ipfs/go-cid"
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
@ -41,10 +41,18 @@ import (
|
|||||||
var multisigCmd = &cli.Command{
|
var multisigCmd = &cli.Command{
|
||||||
Name: "msig",
|
Name: "msig",
|
||||||
Usage: "Interact with a multisig wallet",
|
Usage: "Interact with a multisig wallet",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.IntFlag{
|
||||||
|
Name: "confidence",
|
||||||
|
Usage: "number of block confirmations to wait for",
|
||||||
|
Value: int(build.MessageConfidence),
|
||||||
|
},
|
||||||
|
},
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
msigCreateCmd,
|
msigCreateCmd,
|
||||||
msigInspectCmd,
|
msigInspectCmd,
|
||||||
msigProposeCmd,
|
msigProposeCmd,
|
||||||
|
msigRemoveProposeCmd,
|
||||||
msigApproveCmd,
|
msigApproveCmd,
|
||||||
msigAddProposeCmd,
|
msigAddProposeCmd,
|
||||||
msigAddApproveCmd,
|
msigAddApproveCmd,
|
||||||
@ -56,6 +64,7 @@ var multisigCmd = &cli.Command{
|
|||||||
msigLockApproveCmd,
|
msigLockApproveCmd,
|
||||||
msigLockCancelCmd,
|
msigLockCancelCmd,
|
||||||
msigVestedCmd,
|
msigVestedCmd,
|
||||||
|
msigProposeThresholdCmd,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,14 +154,14 @@ var msigCreateCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wait for it to get mined into a block
|
// wait for it to get mined into a block
|
||||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// check it executed successfully
|
// check it executed successfully
|
||||||
if wait.Receipt.ExitCode != 0 {
|
if wait.Receipt.ExitCode != 0 {
|
||||||
fmt.Println("actor creation failed!")
|
fmt.Fprintln(cctx.App.Writer, "actor creation failed!")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +171,7 @@ var msigCreateCmd = &cli.Command{
|
|||||||
if err := execreturn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)); err != nil {
|
if err := execreturn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println("Created new multisig: ", execreturn.IDAddress, execreturn.RobustAddress)
|
fmt.Fprintln(cctx.App.Writer, "Created new multisig: ", execreturn.IDAddress, execreturn.RobustAddress)
|
||||||
|
|
||||||
// TODO: maybe register this somewhere
|
// TODO: maybe register this somewhere
|
||||||
return nil
|
return nil
|
||||||
@ -226,25 +235,25 @@ var msigInspectCmd = &cli.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Balance: %s\n", types.FIL(act.Balance))
|
fmt.Fprintf(cctx.App.Writer, "Balance: %s\n", types.FIL(act.Balance))
|
||||||
fmt.Printf("Spendable: %s\n", types.FIL(types.BigSub(act.Balance, locked)))
|
fmt.Fprintf(cctx.App.Writer, "Spendable: %s\n", types.FIL(types.BigSub(act.Balance, locked)))
|
||||||
|
|
||||||
if cctx.Bool("vesting") {
|
if cctx.Bool("vesting") {
|
||||||
ib, err := mstate.InitialBalance()
|
ib, err := mstate.InitialBalance()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf("InitialBalance: %s\n", types.FIL(ib))
|
fmt.Fprintf(cctx.App.Writer, "InitialBalance: %s\n", types.FIL(ib))
|
||||||
se, err := mstate.StartEpoch()
|
se, err := mstate.StartEpoch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf("StartEpoch: %d\n", se)
|
fmt.Fprintf(cctx.App.Writer, "StartEpoch: %d\n", se)
|
||||||
ud, err := mstate.UnlockDuration()
|
ud, err := mstate.UnlockDuration()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf("UnlockDuration: %d\n", ud)
|
fmt.Fprintf(cctx.App.Writer, "UnlockDuration: %d\n", ud)
|
||||||
}
|
}
|
||||||
|
|
||||||
signers, err := mstate.Signers()
|
signers, err := mstate.Signers()
|
||||||
@ -255,10 +264,10 @@ var msigInspectCmd = &cli.Command{
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf("Threshold: %d / %d\n", threshold, len(signers))
|
fmt.Fprintf(cctx.App.Writer, "Threshold: %d / %d\n", threshold, len(signers))
|
||||||
fmt.Println("Signers:")
|
fmt.Fprintln(cctx.App.Writer, "Signers:")
|
||||||
for _, s := range signers {
|
for _, s := range signers {
|
||||||
fmt.Printf("\t%s\n", s)
|
fmt.Fprintf(cctx.App.Writer, "\t%s\n", s)
|
||||||
}
|
}
|
||||||
|
|
||||||
pending := make(map[int64]multisig.Transaction)
|
pending := make(map[int64]multisig.Transaction)
|
||||||
@ -270,7 +279,7 @@ var msigInspectCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
decParams := cctx.Bool("decode-params")
|
decParams := cctx.Bool("decode-params")
|
||||||
fmt.Println("Transactions: ", len(pending))
|
fmt.Fprintln(cctx.App.Writer, "Transactions: ", len(pending))
|
||||||
if len(pending) > 0 {
|
if len(pending) > 0 {
|
||||||
var txids []int64
|
var txids []int64
|
||||||
for txid := range pending {
|
for txid := range pending {
|
||||||
@ -280,7 +289,7 @@ var msigInspectCmd = &cli.Command{
|
|||||||
return txids[i] < txids[j]
|
return txids[i] < txids[j]
|
||||||
})
|
})
|
||||||
|
|
||||||
w := tabwriter.NewWriter(os.Stdout, 8, 4, 2, ' ', 0)
|
w := tabwriter.NewWriter(cctx.App.Writer, 8, 4, 2, ' ', 0)
|
||||||
fmt.Fprintf(w, "ID\tState\tApprovals\tTo\tValue\tMethod\tParams\n")
|
fmt.Fprintf(w, "ID\tState\tApprovals\tTo\tValue\tMethod\tParams\n")
|
||||||
for _, txid := range txids {
|
for _, txid := range txids {
|
||||||
tx := pending[txid]
|
tx := pending[txid]
|
||||||
@ -409,7 +418,7 @@ var msigProposeCmd = &cli.Command{
|
|||||||
|
|
||||||
fmt.Println("send proposal in message: ", msgCid)
|
fmt.Println("send proposal in message: ", msgCid)
|
||||||
|
|
||||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -445,14 +454,18 @@ var msigApproveCmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
if cctx.Args().Len() < 5 {
|
if cctx.Args().Len() < 2 {
|
||||||
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, message ID, proposer address, destination, and value"))
|
return ShowHelp(cctx, fmt.Errorf("must pass at least multisig address and message ID"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if cctx.Args().Len() > 5 && cctx.Args().Len() != 7 {
|
if cctx.Args().Len() > 5 && cctx.Args().Len() != 7 {
|
||||||
return ShowHelp(cctx, fmt.Errorf("usage: msig approve <msig addr> <message ID> <proposer address> <desination> <value> [ <method> <params> ]"))
|
return ShowHelp(cctx, fmt.Errorf("usage: msig approve <msig addr> <message ID> <proposer address> <desination> <value> [ <method> <params> ]"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cctx.Args().Len() > 2 && cctx.Args().Len() != 5 {
|
||||||
|
return ShowHelp(cctx, fmt.Errorf("usage: msig approve <msig addr> <message ID> <proposer address> <desination> <value>"))
|
||||||
|
}
|
||||||
|
|
||||||
api, closer, err := GetFullNodeAPI(cctx)
|
api, closer, err := GetFullNodeAPI(cctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -470,42 +483,121 @@ var msigApproveCmd = &cli.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
proposer, err := address.NewFromString(cctx.Args().Get(2))
|
var from address.Address
|
||||||
if err != nil {
|
if cctx.IsSet("from") {
|
||||||
return err
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
if proposer.Protocol() != address.ID {
|
var msgCid cid.Cid
|
||||||
proposer, err = api.StateLookupID(ctx, proposer, types.EmptyTSK)
|
if cctx.Args().Len() == 2 {
|
||||||
|
msgCid, err = api.MsigApprove(ctx, msig, txid, from)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
proposer, err := address.NewFromString(cctx.Args().Get(2))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if proposer.Protocol() != address.ID {
|
||||||
|
proposer, err = api.StateLookupID(ctx, proposer, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dest, err := address.NewFromString(cctx.Args().Get(3))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := types.ParseFIL(cctx.Args().Get(4))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var method uint64
|
||||||
|
var params []byte
|
||||||
|
if cctx.Args().Len() == 7 {
|
||||||
|
m, err := strconv.ParseUint(cctx.Args().Get(5), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
method = m
|
||||||
|
|
||||||
|
p, err := hex.DecodeString(cctx.Args().Get(6))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
params = p
|
||||||
|
}
|
||||||
|
|
||||||
|
msgCid, err = api.MsigApproveTxnHash(ctx, msig, txid, proposer, dest, types.BigInt(value), from, method, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dest, err := address.NewFromString(cctx.Args().Get(3))
|
fmt.Println("sent approval in message: ", msgCid)
|
||||||
|
|
||||||
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
value, err := types.ParseFIL(cctx.Args().Get(4))
|
if wait.Receipt.ExitCode != 0 {
|
||||||
|
return fmt.Errorf("approve returned exit %d", wait.Receipt.ExitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var method uint64
|
addr, err := address.NewFromString(cctx.Args().Get(1))
|
||||||
var params []byte
|
if err != nil {
|
||||||
if cctx.Args().Len() == 7 {
|
return err
|
||||||
m, err := strconv.ParseUint(cctx.Args().Get(5), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
method = m
|
|
||||||
|
|
||||||
p, err := hex.DecodeString(cctx.Args().Get(6))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
params = p
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var from address.Address
|
var from address.Address
|
||||||
@ -523,22 +615,29 @@ var msigApproveCmd = &cli.Command{
|
|||||||
from = defaddr
|
from = defaddr
|
||||||
}
|
}
|
||||||
|
|
||||||
msgCid, err := api.MsigApproveTxnHash(ctx, msig, txid, proposer, dest, types.BigInt(value), from, method, params)
|
msgCid, err := api.MsigRemoveSigner(ctx, msig, from, addr, cctx.Bool("decrease-threshold"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("sent approval in message: ", msgCid)
|
fmt.Println("sent remove proposal in message: ", msgCid)
|
||||||
|
|
||||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if wait.Receipt.ExitCode != 0 {
|
if wait.Receipt.ExitCode != 0 {
|
||||||
return fmt.Errorf("approve returned exit %d", wait.Receipt.ExitCode)
|
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
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -599,9 +698,9 @@ var msigAddProposeCmd = &cli.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("sent add proposal in message: ", msgCid)
|
fmt.Fprintln(cctx.App.Writer, "sent add proposal in message: ", msgCid)
|
||||||
|
|
||||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -683,7 +782,7 @@ var msigAddApproveCmd = &cli.Command{
|
|||||||
|
|
||||||
fmt.Println("sent add approval in message: ", msgCid)
|
fmt.Println("sent add approval in message: ", msgCid)
|
||||||
|
|
||||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -760,7 +859,7 @@ var msigAddCancelCmd = &cli.Command{
|
|||||||
|
|
||||||
fmt.Println("sent add cancellation in message: ", msgCid)
|
fmt.Println("sent add cancellation in message: ", msgCid)
|
||||||
|
|
||||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -832,7 +931,7 @@ var msigSwapProposeCmd = &cli.Command{
|
|||||||
|
|
||||||
fmt.Println("sent swap proposal in message: ", msgCid)
|
fmt.Println("sent swap proposal in message: ", msgCid)
|
||||||
|
|
||||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -914,7 +1013,7 @@ var msigSwapApproveCmd = &cli.Command{
|
|||||||
|
|
||||||
fmt.Println("sent swap approval in message: ", msgCid)
|
fmt.Println("sent swap approval in message: ", msgCid)
|
||||||
|
|
||||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -991,7 +1090,7 @@ var msigSwapCancelCmd = &cli.Command{
|
|||||||
|
|
||||||
fmt.Println("sent swap cancellation in message: ", msgCid)
|
fmt.Println("sent swap cancellation in message: ", msgCid)
|
||||||
|
|
||||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1078,7 +1177,7 @@ var msigLockProposeCmd = &cli.Command{
|
|||||||
|
|
||||||
fmt.Println("sent lock proposal in message: ", msgCid)
|
fmt.Println("sent lock proposal in message: ", msgCid)
|
||||||
|
|
||||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1175,7 +1274,7 @@ var msigLockApproveCmd = &cli.Command{
|
|||||||
|
|
||||||
fmt.Println("sent lock approval in message: ", msgCid)
|
fmt.Println("sent lock approval in message: ", msgCid)
|
||||||
|
|
||||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1267,7 +1366,7 @@ var msigLockCancelCmd = &cli.Command{
|
|||||||
|
|
||||||
fmt.Println("sent lock cancellation in message: ", msgCid)
|
fmt.Println("sent lock cancellation in message: ", msgCid)
|
||||||
|
|
||||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1341,3 +1440,78 @@ var msigVestedCmd = &cli.Command{
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var msigProposeThresholdCmd = &cli.Command{
|
||||||
|
Name: "propose-threshold",
|
||||||
|
Usage: "Propose setting a different signing threshold on the account",
|
||||||
|
ArgsUsage: "<multisigAddress newM>",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "from",
|
||||||
|
Usage: "account to send the proposal from",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
if cctx.Args().Len() != 2 {
|
||||||
|
return ShowHelp(cctx, fmt.Errorf("must pass multisig address and new threshold value"))
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
newM, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
params, actErr := actors.SerializeParams(&msig0.ChangeNumApprovalsThresholdParams{
|
||||||
|
NewThreshold: newM,
|
||||||
|
})
|
||||||
|
|
||||||
|
if actErr != nil {
|
||||||
|
return actErr
|
||||||
|
}
|
||||||
|
|
||||||
|
msgCid, err := api.MsigPropose(ctx, msig, msig, types.NewInt(0), from, uint64(builtin2.MethodsMultisig.ChangeNumApprovalsThreshold), params)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to propose change of threshold: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("sent change threshold proposal in message: ", msgCid)
|
||||||
|
|
||||||
|
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if wait.Receipt.ExitCode != 0 {
|
||||||
|
return fmt.Errorf("change threshold proposal returned exit %d", wait.Receipt.ExitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
55
cli/multisig_test.go
Normal file
55
cli/multisig_test.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/lotus/api/test"
|
||||||
|
clitest "github.com/filecoin-project/lotus/cli/test"
|
||||||
|
builder "github.com/filecoin-project/lotus/node/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestMultisig does a basic test to exercise the multisig CLI
|
||||||
|
// commands
|
||||||
|
func TestMultisig(t *testing.T) {
|
||||||
|
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
|
|
||||||
|
blocktime := 5 * time.Millisecond
|
||||||
|
ctx := context.Background()
|
||||||
|
nodes, _ := startNodes(ctx, t, blocktime)
|
||||||
|
clientNode := nodes[0]
|
||||||
|
clitest.RunMultisigTest(t, Commands, clientNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration) ([]test.TestNode, []address.Address) {
|
||||||
|
n, sn := builder.RPCMockSbBuilder(t, test.OneFull, test.OneMiner)
|
||||||
|
|
||||||
|
full := n[0]
|
||||||
|
miner := sn[0]
|
||||||
|
|
||||||
|
// Get everyone connected
|
||||||
|
addrs, err := full.NetAddrsListen(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := miner.NetConnect(ctx, addrs); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start mining blocks
|
||||||
|
bm := test.NewBlockMiner(ctx, t, miner, blocktime)
|
||||||
|
bm.MineBlocks()
|
||||||
|
|
||||||
|
// Get the creator's address
|
||||||
|
creatorAddr, err := full.WalletDefaultAddress(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create mock CLI
|
||||||
|
return n, []address.Address{creatorAddr}
|
||||||
|
}
|
@ -29,7 +29,6 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/events"
|
"github.com/filecoin-project/lotus/chain/events"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
|
||||||
builder "github.com/filecoin-project/lotus/node/test"
|
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()
|
bm.MineBlocks()
|
||||||
|
|
||||||
// Send some funds to register the receiver
|
// 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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -438,6 +437,7 @@ type mockCLI struct {
|
|||||||
out *bytes.Buffer
|
out *bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: refactor to use the methods in cli/test/mockcli.go
|
||||||
func newMockCLI(t *testing.T) *mockCLI {
|
func newMockCLI(t *testing.T) *mockCLI {
|
||||||
// Create a CLI App with an --api-url flag so that we can specify which node
|
// Create a CLI App with an --api-url flag so that we can specify which node
|
||||||
// the command should be executed against
|
// the command should be executed against
|
||||||
|
236
cli/state.go
236
cli/state.go
@ -60,7 +60,7 @@ var stateCmd = &cli.Command{
|
|||||||
stateSectorCmd,
|
stateSectorCmd,
|
||||||
stateGetActorCmd,
|
stateGetActorCmd,
|
||||||
stateLookupIDCmd,
|
stateLookupIDCmd,
|
||||||
stateReplaySetCmd,
|
stateReplayCmd,
|
||||||
stateSectorSizeCmd,
|
stateSectorSizeCmd,
|
||||||
stateReadStateCmd,
|
stateReadStateCmd,
|
||||||
stateListMessagesCmd,
|
stateListMessagesCmd,
|
||||||
@ -69,7 +69,6 @@ var stateCmd = &cli.Command{
|
|||||||
stateGetDealSetCmd,
|
stateGetDealSetCmd,
|
||||||
stateWaitMsgCmd,
|
stateWaitMsgCmd,
|
||||||
stateSearchMsgCmd,
|
stateSearchMsgCmd,
|
||||||
stateMsgCostCmd,
|
|
||||||
stateMinerInfo,
|
stateMinerInfo,
|
||||||
stateMarketCmd,
|
stateMarketCmd,
|
||||||
stateExecTraceCmd,
|
stateExecTraceCmd,
|
||||||
@ -384,20 +383,27 @@ var stateExecTraceCmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var stateReplaySetCmd = &cli.Command{
|
var stateReplayCmd = &cli.Command{
|
||||||
Name: "replay",
|
Name: "replay",
|
||||||
Usage: "Replay a particular message within a tipset",
|
Usage: "Replay a particular message",
|
||||||
ArgsUsage: "[tipsetKey messageCid]",
|
ArgsUsage: "<messageCid>",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "show-trace",
|
||||||
|
Usage: "print out full execution trace for given message",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "detailed-gas",
|
||||||
|
Usage: "print out detailed gas costs for given message",
|
||||||
|
},
|
||||||
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
if cctx.Args().Len() < 1 {
|
if cctx.Args().Len() != 1 {
|
||||||
fmt.Println("usage: [tipset] <message cid>")
|
fmt.Println("must provide cid of message to replay")
|
||||||
fmt.Println("The last cid passed will be used as the message CID")
|
|
||||||
fmt.Println("All preceding ones will be used as the tipset")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
args := cctx.Args().Slice()
|
mcid, err := cid.Decode(cctx.Args().First())
|
||||||
mcid, err := cid.Decode(args[len(args)-1])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("message cid was invalid: %s", err)
|
return fmt.Errorf("message cid was invalid: %s", err)
|
||||||
}
|
}
|
||||||
@ -410,52 +416,7 @@ var stateReplaySetCmd = &cli.Command{
|
|||||||
|
|
||||||
ctx := ReqContext(cctx)
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
var ts *types.TipSet
|
res, err := fapi.StateReplay(ctx, types.EmptyTSK, mcid)
|
||||||
{
|
|
||||||
var tscids []cid.Cid
|
|
||||||
for _, s := range args[:len(args)-1] {
|
|
||||||
c, err := cid.Decode(s)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("tipset cid was invalid: %s", err)
|
|
||||||
}
|
|
||||||
tscids = append(tscids, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(tscids) > 0 {
|
|
||||||
var headers []*types.BlockHeader
|
|
||||||
for _, c := range tscids {
|
|
||||||
h, err := fapi.ChainGetBlock(ctx, c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
headers = append(headers, h)
|
|
||||||
}
|
|
||||||
|
|
||||||
ts, err = types.NewTipSet(headers)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var r *api.MsgLookup
|
|
||||||
r, err = fapi.StateWaitMsg(ctx, mcid, build.MessageConfidence)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("finding message in chain: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
childTs, err := fapi.ChainGetTipSet(ctx, r.TipSet)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("loading tipset: %w", err)
|
|
||||||
}
|
|
||||||
ts, err = fapi.ChainGetTipSet(ctx, childTs.Parents())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := fapi.StateReplay(ctx, ts.Key(), mcid)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("replay call failed: %w", err)
|
return xerrors.Errorf("replay call failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -464,10 +425,25 @@ var stateReplaySetCmd = &cli.Command{
|
|||||||
fmt.Printf("Exit code: %d\n", res.MsgRct.ExitCode)
|
fmt.Printf("Exit code: %d\n", res.MsgRct.ExitCode)
|
||||||
fmt.Printf("Return: %x\n", res.MsgRct.Return)
|
fmt.Printf("Return: %x\n", res.MsgRct.Return)
|
||||||
fmt.Printf("Gas Used: %d\n", res.MsgRct.GasUsed)
|
fmt.Printf("Gas Used: %d\n", res.MsgRct.GasUsed)
|
||||||
|
|
||||||
|
if cctx.Bool("detailed-gas") {
|
||||||
|
fmt.Printf("Base Fee Burn: %d\n", res.GasCost.BaseFeeBurn)
|
||||||
|
fmt.Printf("Overestimaton Burn: %d\n", res.GasCost.OverEstimationBurn)
|
||||||
|
fmt.Printf("Miner Penalty: %d\n", res.GasCost.MinerPenalty)
|
||||||
|
fmt.Printf("Miner Tip: %d\n", res.GasCost.MinerTip)
|
||||||
|
fmt.Printf("Refund: %d\n", res.GasCost.Refund)
|
||||||
|
}
|
||||||
|
fmt.Printf("Total Message Cost: %d\n", res.GasCost.TotalCost)
|
||||||
|
|
||||||
if res.MsgRct.ExitCode != 0 {
|
if res.MsgRct.ExitCode != 0 {
|
||||||
fmt.Printf("Error message: %q\n", res.Error)
|
fmt.Printf("Error message: %q\n", res.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cctx.Bool("show-trace") {
|
||||||
|
fmt.Printf("%s\t%s\t%s\t%d\t%x\t%d\t%x\n", res.Msg.From, res.Msg.To, res.Msg.Value, res.Msg.Method, res.Msg.Params, res.MsgRct.ExitCode, res.MsgRct.Return)
|
||||||
|
printInternalExecutions("\t", res.ExecutionTrace.Subcalls)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -837,33 +813,66 @@ var stateListMessagesCmd = &cli.Command{
|
|||||||
froma = a
|
froma = a
|
||||||
}
|
}
|
||||||
|
|
||||||
toh := cctx.Uint64("toheight")
|
toh := abi.ChainEpoch(cctx.Uint64("toheight"))
|
||||||
|
|
||||||
ts, err := LoadTipSet(ctx, cctx, api)
|
ts, err := LoadTipSet(ctx, cctx, api)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
msgs, err := api.StateListMessages(ctx, &types.Message{To: toa, From: froma}, ts.Key(), abi.ChainEpoch(toh))
|
if ts == nil {
|
||||||
if err != nil {
|
head, err := api.ChainHead(ctx)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ts = head
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range msgs {
|
windowSize := abi.ChainEpoch(100)
|
||||||
if cctx.Bool("cids") {
|
|
||||||
fmt.Println(c.String())
|
cur := ts
|
||||||
continue
|
for cur.Height() > toh {
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
m, err := api.ChainGetMessage(ctx, c)
|
end := toh
|
||||||
|
if cur.Height()-windowSize > end {
|
||||||
|
end = cur.Height() - windowSize
|
||||||
|
}
|
||||||
|
|
||||||
|
msgs, err := api.StateListMessages(ctx, &lapi.MessageMatch{To: toa, From: froma}, cur.Key(), end)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.MarshalIndent(m, "", " ")
|
|
||||||
|
for _, c := range msgs {
|
||||||
|
if cctx.Bool("cids") {
|
||||||
|
fmt.Println(c.String())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := api.ChainGetMessage(ctx, c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b, err := json.MarshalIndent(m, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(string(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
if end <= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
next, err := api.ChainGetTipSetByHeight(ctx, end-1, cur.Key())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println(string(b))
|
|
||||||
|
cur = next
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -1424,60 +1433,6 @@ var stateSearchMsgCmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var stateMsgCostCmd = &cli.Command{
|
|
||||||
Name: "msg-cost",
|
|
||||||
Usage: "Get the detailed gas costs of a message",
|
|
||||||
ArgsUsage: "[messageCid]",
|
|
||||||
Action: func(cctx *cli.Context) error {
|
|
||||||
if !cctx.Args().Present() {
|
|
||||||
return fmt.Errorf("must specify message cid to get gas costs for")
|
|
||||||
}
|
|
||||||
|
|
||||||
api, closer, err := GetFullNodeAPI(cctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer closer()
|
|
||||||
|
|
||||||
ctx := ReqContext(cctx)
|
|
||||||
|
|
||||||
msg, err := cid.Decode(cctx.Args().First())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tsk := types.EmptyTSK
|
|
||||||
|
|
||||||
ts, err := LoadTipSet(ctx, cctx, api)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ts != nil {
|
|
||||||
tsk = ts.Key()
|
|
||||||
}
|
|
||||||
|
|
||||||
mgc, err := api.StateMsgGasCost(ctx, msg, tsk)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if mgc != nil {
|
|
||||||
fmt.Printf("Message CID: %s", mgc.Message)
|
|
||||||
fmt.Printf("\nGas Used: %d", mgc.GasUsed)
|
|
||||||
fmt.Printf("\nBase Fee Burn: %d", mgc.BaseFeeBurn)
|
|
||||||
fmt.Printf("\nOverestimation Burn: %d", mgc.OverEstimationBurn)
|
|
||||||
fmt.Printf("\nMiner Tip: %d", mgc.MinerTip)
|
|
||||||
fmt.Printf("\nRefund: %d", mgc.Refund)
|
|
||||||
fmt.Printf("\nTotal Cost: %d", mgc.TotalCost)
|
|
||||||
fmt.Printf("\nMiner Penalty: %d", mgc.MinerPenalty)
|
|
||||||
} else {
|
|
||||||
fmt.Print("message was not found on chain")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var stateCallCmd = &cli.Command{
|
var stateCallCmd = &cli.Command{
|
||||||
Name: "call",
|
Name: "call",
|
||||||
Usage: "Invoke a method on an actor locally",
|
Usage: "Invoke a method on an actor locally",
|
||||||
@ -1688,7 +1643,14 @@ func parseParamsForMethod(act cid.Cid, method uint64, args []string) ([]byte, er
|
|||||||
|
|
||||||
var stateCircSupplyCmd = &cli.Command{
|
var stateCircSupplyCmd = &cli.Command{
|
||||||
Name: "circulating-supply",
|
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 {
|
Action: func(cctx *cli.Context) error {
|
||||||
api, closer, err := GetFullNodeAPI(cctx)
|
api, closer, err := GetFullNodeAPI(cctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1703,16 +1665,26 @@ var stateCircSupplyCmd = &cli.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
circ, err := api.StateCirculatingSupply(ctx, ts.Key())
|
if cctx.IsSet("vm-supply") {
|
||||||
if err != nil {
|
circ, err := api.StateVMCirculatingSupplyInternal(ctx, ts.Key())
|
||||||
return err
|
if err != nil {
|
||||||
}
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("Circulating supply: ", types.FIL(circ.FilCirculating))
|
fmt.Println("Circulating supply: ", types.FIL(circ.FilCirculating))
|
||||||
fmt.Println("Mined: ", types.FIL(circ.FilMined))
|
fmt.Println("Mined: ", types.FIL(circ.FilMined))
|
||||||
fmt.Println("Vested: ", types.FIL(circ.FilVested))
|
fmt.Println("Vested: ", types.FIL(circ.FilVested))
|
||||||
fmt.Println("Burnt: ", types.FIL(circ.FilBurnt))
|
fmt.Println("Burnt: ", types.FIL(circ.FilBurnt))
|
||||||
fmt.Println("Locked: ", types.FIL(circ.FilLocked))
|
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
|
return nil
|
||||||
},
|
},
|
||||||
|
12
cli/sync.go
12
cli/sync.go
@ -84,6 +84,12 @@ var syncStatusCmd = &cli.Command{
|
|||||||
var syncWaitCmd = &cli.Command{
|
var syncWaitCmd = &cli.Command{
|
||||||
Name: "wait",
|
Name: "wait",
|
||||||
Usage: "Wait for sync to be complete",
|
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 {
|
Action: func(cctx *cli.Context) error {
|
||||||
napi, closer, err := GetFullNodeAPI(cctx)
|
napi, closer, err := GetFullNodeAPI(cctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -92,7 +98,7 @@ var syncWaitCmd = &cli.Command{
|
|||||||
defer closer()
|
defer closer()
|
||||||
ctx := ReqContext(cctx)
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
return SyncWait(ctx, napi)
|
return SyncWait(ctx, napi, cctx.Bool("watch"))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,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
|
tick := time.Second / 4
|
||||||
|
|
||||||
lastLines := 0
|
lastLines := 0
|
||||||
@ -311,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)
|
_ = 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!")
|
fmt.Println("\nDone!")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
124
cli/test/mockcli.go
Normal file
124
cli/test/mockcli.go
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/multiformats/go-multiaddr"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
lcli "github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mockCLI struct {
|
||||||
|
t *testing.T
|
||||||
|
cmds []*lcli.Command
|
||||||
|
cctx *lcli.Context
|
||||||
|
out *bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMockCLI(t *testing.T, cmds []*lcli.Command) *mockCLI {
|
||||||
|
// Create a CLI App with an --api-url flag so that we can specify which node
|
||||||
|
// the command should be executed against
|
||||||
|
app := &lcli.App{
|
||||||
|
Flags: []lcli.Flag{
|
||||||
|
&lcli.StringFlag{
|
||||||
|
Name: "api-url",
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Commands: cmds,
|
||||||
|
}
|
||||||
|
|
||||||
|
var out bytes.Buffer
|
||||||
|
app.Writer = &out
|
||||||
|
app.Setup()
|
||||||
|
|
||||||
|
cctx := lcli.NewContext(app, &flag.FlagSet{}, nil)
|
||||||
|
return &mockCLI{t: t, cmds: cmds, cctx: cctx, out: &out}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mockCLI) client(addr multiaddr.Multiaddr) *mockCLIClient {
|
||||||
|
return &mockCLIClient{t: c.t, cmds: c.cmds, addr: addr, cctx: c.cctx, out: c.out}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mockCLIClient runs commands against a particular node
|
||||||
|
type mockCLIClient struct {
|
||||||
|
t *testing.T
|
||||||
|
cmds []*lcli.Command
|
||||||
|
addr multiaddr.Multiaddr
|
||||||
|
cctx *lcli.Context
|
||||||
|
out *bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mockCLIClient) run(cmd []string, params []string, args []string) string {
|
||||||
|
// Add parameter --api-url=<node api listener address>
|
||||||
|
apiFlag := "--api-url=" + c.addr.String()
|
||||||
|
params = append([]string{apiFlag}, params...)
|
||||||
|
|
||||||
|
err := c.cctx.App.Run(append(append(cmd, params...), args...))
|
||||||
|
require.NoError(c.t, err)
|
||||||
|
|
||||||
|
// Get the output
|
||||||
|
str := strings.TrimSpace(c.out.String())
|
||||||
|
c.out.Reset()
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mockCLIClient) runCmd(input []string) string {
|
||||||
|
cmd := c.cmdByNameSub(input[0], input[1])
|
||||||
|
out, err := c.runCmdRaw(cmd, input[2:])
|
||||||
|
require.NoError(c.t, err)
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mockCLIClient) cmdByNameSub(name string, sub string) *lcli.Command {
|
||||||
|
for _, c := range c.cmds {
|
||||||
|
if c.Name == name {
|
||||||
|
for _, s := range c.Subcommands {
|
||||||
|
if s.Name == sub {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mockCLIClient) runCmdRaw(cmd *lcli.Command, input []string) (string, error) {
|
||||||
|
// prepend --api-url=<node api listener address>
|
||||||
|
apiFlag := "--api-url=" + c.addr.String()
|
||||||
|
input = append([]string{apiFlag}, input...)
|
||||||
|
|
||||||
|
fs := c.flagSet(cmd)
|
||||||
|
err := fs.Parse(input)
|
||||||
|
require.NoError(c.t, err)
|
||||||
|
|
||||||
|
err = cmd.Action(lcli.NewContext(c.cctx.App, fs, c.cctx))
|
||||||
|
|
||||||
|
// Get the output
|
||||||
|
str := strings.TrimSpace(c.out.String())
|
||||||
|
c.out.Reset()
|
||||||
|
return str, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mockCLIClient) flagSet(cmd *lcli.Command) *flag.FlagSet {
|
||||||
|
// Apply app level flags (so we can process --api-url flag)
|
||||||
|
fs := &flag.FlagSet{}
|
||||||
|
for _, f := range c.cctx.App.Flags {
|
||||||
|
err := f.Apply(fs)
|
||||||
|
if err != nil {
|
||||||
|
c.t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Apply command level flags
|
||||||
|
for _, f := range cmd.Flags {
|
||||||
|
err := f.Apply(fs)
|
||||||
|
if err != nil {
|
||||||
|
c.t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fs
|
||||||
|
}
|
110
cli/test/multisig.go
Normal file
110
cli/test/multisig.go
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/lotus/api/test"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
logging "github.com/ipfs/go-log/v2"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
lcli "github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QuietMiningLogs() {
|
||||||
|
logging.SetLogLevel("miner", "ERROR")
|
||||||
|
logging.SetLogLevel("chainstore", "ERROR")
|
||||||
|
logging.SetLogLevel("chain", "ERROR")
|
||||||
|
logging.SetLogLevel("sub", "ERROR")
|
||||||
|
logging.SetLogLevel("storageminer", "ERROR")
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
// Create mock CLI
|
||||||
|
mockCLI := newMockCLI(t, cmds)
|
||||||
|
clientCLI := mockCLI.client(clientNode.ListenAddr)
|
||||||
|
|
||||||
|
// Create some wallets on the node to use for testing multisig
|
||||||
|
var walletAddrs []address.Address
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
addr, err := clientNode.WalletNew(ctx, types.KTSecp256k1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
walletAddrs = append(walletAddrs, addr)
|
||||||
|
|
||||||
|
test.SendFunds(ctx, t, clientNode, addr, types.NewInt(1e15))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an msig with three of the addresses and threshold of two sigs
|
||||||
|
// msig create --required=2 --duration=50 --value=1000attofil <addr1> <addr2> <addr3>
|
||||||
|
amtAtto := types.NewInt(1000)
|
||||||
|
threshold := 2
|
||||||
|
paramDuration := "--duration=50"
|
||||||
|
paramRequired := fmt.Sprintf("--required=%d", threshold)
|
||||||
|
paramValue := fmt.Sprintf("--value=%dattofil", amtAtto)
|
||||||
|
cmd := []string{
|
||||||
|
"msig", "create",
|
||||||
|
paramRequired,
|
||||||
|
paramDuration,
|
||||||
|
paramValue,
|
||||||
|
walletAddrs[0].String(),
|
||||||
|
walletAddrs[1].String(),
|
||||||
|
walletAddrs[2].String(),
|
||||||
|
}
|
||||||
|
out := clientCLI.runCmd(cmd)
|
||||||
|
fmt.Println(out)
|
||||||
|
|
||||||
|
// Extract msig robust address from output
|
||||||
|
expCreateOutPrefix := "Created new multisig:"
|
||||||
|
require.Regexp(t, regexp.MustCompile(expCreateOutPrefix), out)
|
||||||
|
parts := strings.Split(strings.TrimSpace(strings.Replace(out, expCreateOutPrefix, "", -1)), " ")
|
||||||
|
require.Len(t, parts, 2)
|
||||||
|
msigRobustAddr := parts[1]
|
||||||
|
fmt.Println("msig robust address:", msigRobustAddr)
|
||||||
|
|
||||||
|
// Propose to add a new address to the msig
|
||||||
|
// msig add-propose --from=<addr> <msig> <addr>
|
||||||
|
paramFrom := fmt.Sprintf("--from=%s", walletAddrs[0])
|
||||||
|
cmd = []string{
|
||||||
|
"msig", "add-propose",
|
||||||
|
paramFrom,
|
||||||
|
msigRobustAddr,
|
||||||
|
walletAddrs[3].String(),
|
||||||
|
}
|
||||||
|
out = clientCLI.runCmd(cmd)
|
||||||
|
fmt.Println(out)
|
||||||
|
|
||||||
|
// msig inspect <msig>
|
||||||
|
cmd = []string{"msig", "inspect", "--vesting", "--decode-params", msigRobustAddr}
|
||||||
|
out = clientCLI.runCmd(cmd)
|
||||||
|
fmt.Println(out)
|
||||||
|
|
||||||
|
// Expect correct balance
|
||||||
|
require.Regexp(t, regexp.MustCompile("Balance: 0.000000000000001 FIL"), out)
|
||||||
|
// Expect 1 transaction
|
||||||
|
require.Regexp(t, regexp.MustCompile(`Transactions:\s*1`), out)
|
||||||
|
// Expect transaction to be "AddSigner"
|
||||||
|
require.Regexp(t, regexp.MustCompile(`AddSigner`), out)
|
||||||
|
|
||||||
|
// Approve adding the new address
|
||||||
|
// msig add-approve --from=<addr> <msig> <addr> 0 <addr> false
|
||||||
|
txnID := "0"
|
||||||
|
paramFrom = fmt.Sprintf("--from=%s", walletAddrs[1])
|
||||||
|
cmd = []string{
|
||||||
|
"msig", "add-approve",
|
||||||
|
paramFrom,
|
||||||
|
msigRobustAddr,
|
||||||
|
walletAddrs[0].String(),
|
||||||
|
txnID,
|
||||||
|
walletAddrs[3].String(),
|
||||||
|
"false",
|
||||||
|
}
|
||||||
|
out = clientCLI.runCmd(cmd)
|
||||||
|
fmt.Println(out)
|
||||||
|
}
|
@ -17,7 +17,6 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/crypto"
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
|
|
||||||
types "github.com/filecoin-project/lotus/chain/types"
|
types "github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
|
||||||
"github.com/filecoin-project/lotus/lib/tablewriter"
|
"github.com/filecoin-project/lotus/lib/tablewriter"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -55,7 +54,7 @@ var walletNew = &cli.Command{
|
|||||||
t = "secp256k1"
|
t = "secp256k1"
|
||||||
}
|
}
|
||||||
|
|
||||||
nk, err := api.WalletNew(ctx, wallet.ActSigType(t))
|
nk, err := api.WalletNew(ctx, types.KeyType(t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -329,9 +328,9 @@ var walletImport = &cli.Command{
|
|||||||
ki.PrivateKey = gk.PrivateKey
|
ki.PrivateKey = gk.PrivateKey
|
||||||
switch gk.SigType {
|
switch gk.SigType {
|
||||||
case 1:
|
case 1:
|
||||||
ki.Type = wallet.KTSecp256k1
|
ki.Type = types.KTSecp256k1
|
||||||
case 2:
|
case 2:
|
||||||
ki.Type = wallet.KTBLS
|
ki.Type = types.KTBLS
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unrecognized key type: %d", gk.SigType)
|
return fmt.Errorf("unrecognized key type: %d", gk.SigType)
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/crypto"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"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 {
|
func sendSmallFundsTxs(ctx context.Context, api api.FullNode, from address.Address, rate int) error {
|
||||||
var sendSet []address.Address
|
var sendSet []address.Address
|
||||||
for i := 0; i < 20; i++ {
|
for i := 0; i < 20; i++ {
|
||||||
naddr, err := api.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
naddr, err := api.WalletNew(ctx, types.KTSecp256k1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -316,7 +316,7 @@ limit 1
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Syncer) storeCirculatingSupply(ctx context.Context, tipset *types.TipSet) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -6,16 +6,23 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/go-bitfield"
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
|
"github.com/filecoin-project/go-state-types/dline"
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/lib/sigs"
|
||||||
|
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||||
|
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||||
"github.com/filecoin-project/lotus/node/impl/full"
|
"github.com/filecoin-project/lotus/node/impl/full"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LookbackCap = time.Hour
|
LookbackCap = time.Hour * 12
|
||||||
stateWaitLookbackLimit = abi.ChainEpoch(20)
|
stateWaitLookbackLimit = abi.ChainEpoch(20)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,9 +33,12 @@ var (
|
|||||||
// gatewayDepsAPI defines the API methods that the GatewayAPI depends on
|
// gatewayDepsAPI defines the API methods that the GatewayAPI depends on
|
||||||
// (to make it easy to mock for tests)
|
// (to make it easy to mock for tests)
|
||||||
type gatewayDepsAPI interface {
|
type gatewayDepsAPI interface {
|
||||||
|
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||||
ChainHead(ctx context.Context) (*types.TipSet, error)
|
ChainHead(ctx context.Context) (*types.TipSet, error)
|
||||||
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
|
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||||
|
ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error)
|
||||||
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||||
MpoolPushUntrusted(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
MpoolPushUntrusted(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||||
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error)
|
||||||
@ -37,10 +47,31 @@ type gatewayDepsAPI interface {
|
|||||||
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
||||||
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||||
StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error)
|
StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error)
|
||||||
|
StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error)
|
||||||
|
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error)
|
||||||
|
StateMinerFaults(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error)
|
||||||
|
StateMinerRecoveries(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error)
|
||||||
|
StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error)
|
||||||
|
StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]api.Deadline, error)
|
||||||
|
StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
|
||||||
|
StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error)
|
||||||
|
StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error)
|
||||||
|
StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (api.CirculatingSupply, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type GatewayAPI struct {
|
type GatewayAPI struct {
|
||||||
api gatewayDepsAPI
|
api gatewayDepsAPI
|
||||||
|
lookbackCap time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGatewayAPI creates a new GatewayAPI with the default lookback cap
|
||||||
|
func NewGatewayAPI(api gatewayDepsAPI) *GatewayAPI {
|
||||||
|
return newGatewayAPI(api, LookbackCap)
|
||||||
|
}
|
||||||
|
|
||||||
|
// used by the tests
|
||||||
|
func newGatewayAPI(api gatewayDepsAPI, lookbackCap time.Duration) *GatewayAPI {
|
||||||
|
return &GatewayAPI{api: api, lookbackCap: lookbackCap}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) checkTipsetKey(ctx context.Context, tsk types.TipSetKey) error {
|
func (a *GatewayAPI) checkTipsetKey(ctx context.Context, tsk types.TipSetKey) error {
|
||||||
@ -76,13 +107,17 @@ func (a *GatewayAPI) checkTipsetHeight(ts *types.TipSet, h abi.ChainEpoch) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) checkTimestamp(at time.Time) error {
|
func (a *GatewayAPI) checkTimestamp(at time.Time) error {
|
||||||
if time.Since(at) > LookbackCap {
|
if time.Since(at) > a.lookbackCap {
|
||||||
return ErrLookbackTooLong
|
return ErrLookbackTooLong
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) ChainHasObj(ctx context.Context, c cid.Cid) (bool, error) {
|
||||||
|
return a.api.ChainHasObj(ctx, c)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
func (a *GatewayAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||||
// TODO: cache and invalidate cache when timestamp is up (or have internal ChainNotify)
|
// TODO: cache and invalidate cache when timestamp is up (or have internal ChainNotify)
|
||||||
|
|
||||||
@ -94,9 +129,19 @@ func (a *GatewayAPI) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
|
func (a *GatewayAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||||
ts, err := a.api.ChainGetTipSet(ctx, tsk)
|
var ts *types.TipSet
|
||||||
if err != nil {
|
if tsk.IsEmpty() {
|
||||||
return nil, err
|
head, err := a.api.ChainHead(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ts = head
|
||||||
|
} else {
|
||||||
|
gts, err := a.api.ChainGetTipSet(ctx, tsk)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ts = gts
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the tipset key refers to a tipset that's too far in the past
|
// Check if the tipset key refers to a tipset that's too far in the past
|
||||||
@ -112,6 +157,14 @@ func (a *GatewayAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoc
|
|||||||
return a.api.ChainGetTipSetByHeight(ctx, h, tsk)
|
return a.api.ChainGetTipSetByHeight(ctx, h, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
|
||||||
|
return a.api.ChainReadObj(ctx, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) ChainGetNode(ctx context.Context, p string) (*api.IpldObject, error) {
|
||||||
|
return a.api.ChainGetNode(ctx, p)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
func (a *GatewayAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
||||||
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -172,6 +225,80 @@ func (a *GatewayAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence u
|
|||||||
return a.api.StateWaitMsgLimited(ctx, msg, confidence, stateWaitLookbackLimit)
|
return a.api.StateWaitMsgLimited(ctx, msg, confidence, stateWaitLookbackLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateReadState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*api.ActorState, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return a.api.StateReadState(ctx, actor, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateMinerPower(ctx context.Context, m address.Address, tsk types.TipSetKey) (*api.MinerPower, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return a.api.StateMinerPower(ctx, m, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateMinerFaults(ctx context.Context, m address.Address, tsk types.TipSetKey) (bitfield.BitField, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return bitfield.BitField{}, err
|
||||||
|
}
|
||||||
|
return a.api.StateMinerFaults(ctx, m, tsk)
|
||||||
|
}
|
||||||
|
func (a *GatewayAPI) StateMinerRecoveries(ctx context.Context, m address.Address, tsk types.TipSetKey) (bitfield.BitField, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return bitfield.BitField{}, err
|
||||||
|
}
|
||||||
|
return a.api.StateMinerRecoveries(ctx, m, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateMinerInfo(ctx context.Context, m address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return miner.MinerInfo{}, err
|
||||||
|
}
|
||||||
|
return a.api.StateMinerInfo(ctx, m, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateMinerDeadlines(ctx context.Context, m address.Address, tsk types.TipSetKey) ([]api.Deadline, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return a.api.StateMinerDeadlines(ctx, m, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateMinerAvailableBalance(ctx context.Context, m address.Address, tsk types.TipSetKey) (types.BigInt, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return types.BigInt{}, err
|
||||||
|
}
|
||||||
|
return a.api.StateMinerAvailableBalance(ctx, m, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateMinerProvingDeadline(ctx context.Context, m address.Address, tsk types.TipSetKey) (*dline.Info, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return a.api.StateMinerProvingDeadline(ctx, m, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (abi.TokenAmount, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return types.BigInt{}, err
|
||||||
|
}
|
||||||
|
return a.api.StateCirculatingSupply(ctx, tsk)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return api.CirculatingSupply{}, err
|
||||||
|
}
|
||||||
|
return a.api.StateVMCirculatingSupplyInternal(ctx, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) {
|
||||||
|
return sigs.Verify(sig, k, msg) == nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
var _ api.GatewayAPI = (*GatewayAPI)(nil)
|
var _ api.GatewayAPI = (*GatewayAPI)(nil)
|
||||||
var _ full.ChainModuleAPI = (*GatewayAPI)(nil)
|
var _ full.ChainModuleAPI = (*GatewayAPI)(nil)
|
||||||
var _ full.GasModuleAPI = (*GatewayAPI)(nil)
|
var _ full.GasModuleAPI = (*GatewayAPI)(nil)
|
||||||
|
@ -88,7 +88,7 @@ func TestGatewayAPIChainGetTipSetByHeight(t *testing.T) {
|
|||||||
tt := tt
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
mock := &mockGatewayDepsAPI{}
|
mock := &mockGatewayDepsAPI{}
|
||||||
a := &GatewayAPI{api: mock}
|
a := NewGatewayAPI(mock)
|
||||||
|
|
||||||
// Create tipsets from genesis up to tskh and return the highest
|
// Create tipsets from genesis up to tskh and return the highest
|
||||||
ts := mock.createTipSets(tt.args.tskh, tt.args.genesisTS)
|
ts := mock.createTipSets(tt.args.tskh, tt.args.genesisTS)
|
||||||
@ -107,6 +107,13 @@ func TestGatewayAPIChainGetTipSetByHeight(t *testing.T) {
|
|||||||
type mockGatewayDepsAPI struct {
|
type mockGatewayDepsAPI struct {
|
||||||
lk sync.RWMutex
|
lk sync.RWMutex
|
||||||
tipsets []*types.TipSet
|
tipsets []*types.TipSet
|
||||||
|
|
||||||
|
gatewayDepsAPI // satisfies all interface requirements but will panic if
|
||||||
|
// methods are called. easier than filling out with panic stubs IMO
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockGatewayDepsAPI) ChainHasObj(context.Context, cid.Cid) (bool, error) {
|
||||||
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockGatewayDepsAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
func (m *mockGatewayDepsAPI) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||||
@ -158,6 +165,10 @@ func (m *mockGatewayDepsAPI) ChainGetTipSetByHeight(ctx context.Context, h abi.C
|
|||||||
return m.tipsets[h], nil
|
return m.tipsets[h], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *mockGatewayDepsAPI) ChainReadObj(ctx context.Context, c cid.Cid) ([]byte, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
func (m *mockGatewayDepsAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
func (m *mockGatewayDepsAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
@ -189,3 +200,7 @@ func (m *mockGatewayDepsAPI) StateLookupID(ctx context.Context, addr address.Add
|
|||||||
func (m *mockGatewayDepsAPI) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error) {
|
func (m *mockGatewayDepsAPI) StateWaitMsgLimited(ctx context.Context, msg cid.Cid, confidence uint64, h abi.ChainEpoch) (*api.MsgLookup, error) {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *mockGatewayDepsAPI) StateReadState(ctx context.Context, act address.Address, ts types.TipSetKey) (*api.ActorState, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
@ -4,10 +4,14 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/cli"
|
||||||
|
clitest "github.com/filecoin-project/lotus/cli/test"
|
||||||
|
|
||||||
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
||||||
|
|
||||||
@ -22,25 +26,26 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/api/test"
|
"github.com/filecoin-project/lotus/api/test"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
|
||||||
"github.com/filecoin-project/lotus/node"
|
"github.com/filecoin-project/lotus/node"
|
||||||
builder "github.com/filecoin-project/lotus/node/test"
|
builder "github.com/filecoin-project/lotus/node/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const maxLookbackCap = time.Duration(math.MaxInt64)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
|
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
|
||||||
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
|
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
|
||||||
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
|
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestEndToEnd tests that API calls can be made on a lite node that is
|
// TestEndToEndWalletMsig tests that wallet and msig API calls can be made
|
||||||
// connected through a gateway to a full API node
|
// on a lite node that is connected through a gateway to a full API node
|
||||||
func TestEndToEnd(t *testing.T) {
|
func TestEndToEndWalletMsig(t *testing.T) {
|
||||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
|
|
||||||
blocktime := 5 * time.Millisecond
|
blocktime := 5 * time.Millisecond
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
full, lite, closer := startNodes(ctx, t, blocktime)
|
full, lite, closer := startNodes(ctx, t, blocktime, maxLookbackCap)
|
||||||
defer closer()
|
defer closer()
|
||||||
|
|
||||||
// The full node starts with a wallet
|
// The full node starts with a wallet
|
||||||
@ -53,15 +58,15 @@ func TestEndToEnd(t *testing.T) {
|
|||||||
fmt.Println(balance)
|
fmt.Println(balance)
|
||||||
|
|
||||||
// Create a wallet on the lite node
|
// 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)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Send some funds from the full node to the lite node
|
// Send some funds from the full node to the lite node
|
||||||
err = sendFunds(ctx, t, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18))
|
err = sendFunds(ctx, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Send some funds from the lite node back to the full node
|
// Send some funds from the lite node back to the full node
|
||||||
err = sendFunds(ctx, t, lite, liteWalletAddr, fullWalletAddr, types.NewInt(100))
|
err = sendFunds(ctx, lite, liteWalletAddr, fullWalletAddr, types.NewInt(100))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Sign some data with the lite node wallet address
|
// Sign some data with the lite node wallet address
|
||||||
@ -77,12 +82,12 @@ func TestEndToEnd(t *testing.T) {
|
|||||||
// Create some wallets on the lite node to use for testing multisig
|
// Create some wallets on the lite node to use for testing multisig
|
||||||
var walletAddrs []address.Address
|
var walletAddrs []address.Address
|
||||||
for i := 0; i < 4; i++ {
|
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)
|
require.NoError(t, err)
|
||||||
|
|
||||||
walletAddrs = append(walletAddrs, addr)
|
walletAddrs = append(walletAddrs, addr)
|
||||||
|
|
||||||
err = sendFunds(ctx, t, lite, liteWalletAddr, addr, types.NewInt(1e15))
|
err = sendFunds(ctx, lite, liteWalletAddr, addr, types.NewInt(1e15))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +141,33 @@ func TestEndToEnd(t *testing.T) {
|
|||||||
require.True(t, approveReturn.Applied)
|
require.True(t, approveReturn.Applied)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendFunds(ctx context.Context, t *testing.T, fromNode test.TestNode, fromAddr address.Address, toAddr address.Address, amt types.BigInt) error {
|
// TestEndToEndMsigCLI tests that msig CLI calls can be made
|
||||||
|
// on a lite node that is connected through a gateway to a full API node
|
||||||
|
func TestEndToEndMsigCLI(t *testing.T) {
|
||||||
|
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||||
|
clitest.QuietMiningLogs()
|
||||||
|
|
||||||
|
blocktime := 5 * time.Millisecond
|
||||||
|
ctx := context.Background()
|
||||||
|
full, lite, closer := startNodes(ctx, t, blocktime, maxLookbackCap)
|
||||||
|
defer closer()
|
||||||
|
|
||||||
|
// The full node starts with a wallet
|
||||||
|
fullWalletAddr, err := full.WalletDefaultAddress(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Create a wallet on the lite node
|
||||||
|
liteWalletAddr, err := lite.WalletNew(ctx, types.KTSecp256k1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Send some funds from the full node to the lite node
|
||||||
|
err = sendFunds(ctx, full, fullWalletAddr, liteWalletAddr, types.NewInt(1e18))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
clitest.RunMultisigTest(t, cli.Commands, lite)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendFunds(ctx context.Context, fromNode test.TestNode, fromAddr address.Address, toAddr address.Address, amt types.BigInt) error {
|
||||||
msg := &types.Message{
|
msg := &types.Message{
|
||||||
From: fromAddr,
|
From: fromAddr,
|
||||||
To: toAddr,
|
To: toAddr,
|
||||||
@ -159,7 +190,7 @@ func sendFunds(ctx context.Context, t *testing.T, fromNode test.TestNode, fromAd
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration) (test.TestNode, test.TestNode, jsonrpc.ClientCloser) {
|
func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration, lookbackCap time.Duration) (test.TestNode, test.TestNode, jsonrpc.ClientCloser) {
|
||||||
var closer jsonrpc.ClientCloser
|
var closer jsonrpc.ClientCloser
|
||||||
|
|
||||||
// Create one miner and two full nodes.
|
// Create one miner and two full nodes.
|
||||||
@ -176,7 +207,7 @@ func startNodes(ctx context.Context, t *testing.T, blocktime time.Duration) (tes
|
|||||||
fullNode := nodes[0]
|
fullNode := nodes[0]
|
||||||
|
|
||||||
// Create a gateway server in front of the full node
|
// Create a gateway server in front of the full node
|
||||||
_, addr, err := builder.CreateRPCServer(&GatewayAPI{api: fullNode})
|
_, addr, err := builder.CreateRPCServer(newGatewayAPI(fullNode, lookbackCap))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Create a gateway client API that connects to the gateway server
|
// Create a gateway client API that connects to the gateway server
|
||||||
|
@ -76,7 +76,7 @@ var runCmd = &cli.Command{
|
|||||||
log.Info("Setting up API endpoint at " + address)
|
log.Info("Setting up API endpoint at " + address)
|
||||||
|
|
||||||
rpcServer := jsonrpc.NewServer()
|
rpcServer := jsonrpc.NewServer()
|
||||||
rpcServer.Register("Filecoin", &GatewayAPI{api: api})
|
rpcServer.Register("Filecoin", NewGatewayAPI(api))
|
||||||
|
|
||||||
mux.Handle("/rpc/v0", rpcServer)
|
mux.Handle("/rpc/v0", rpcServer)
|
||||||
mux.PathPrefix("/").Handler(http.DefaultServeMux)
|
mux.PathPrefix("/").Handler(http.DefaultServeMux)
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"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/chain/wallet"
|
||||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||||
@ -30,12 +30,12 @@ func main() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var kt crypto.SigType
|
var kt types.KeyType
|
||||||
switch cctx.String("type") {
|
switch cctx.String("type") {
|
||||||
case "bls":
|
case "bls":
|
||||||
kt = crypto.SigTypeBLS
|
kt = types.KTBLS
|
||||||
case "secp256k1":
|
case "secp256k1":
|
||||||
kt = crypto.SigTypeSecp256k1
|
kt = types.KTSecp256k1
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unrecognized key type: %q", cctx.String("type"))
|
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)
|
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
|
return true, messageMethod, refundValue, nil
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
"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/lotus/extern/sector-storage/zerocomm"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
"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
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
minerAddr, err = wallet.GenerateKey(crypto.SigTypeBLS)
|
minerAddr, err = wallet.GenerateKey(types.KTBLS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/gen/genesis"
|
||||||
|
|
||||||
|
_init "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
||||||
|
|
||||||
"github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
|
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
|
||||||
@ -136,6 +140,9 @@ var chainBalanceStateCmd = &cli.Command{
|
|||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "miner-info",
|
Name: "miner-info",
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "robust-addresses",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
@ -187,6 +194,33 @@ var chainBalanceStateCmd = &cli.Command{
|
|||||||
|
|
||||||
minerInfo := cctx.Bool("miner-info")
|
minerInfo := cctx.Bool("miner-info")
|
||||||
|
|
||||||
|
robustMap := make(map[address.Address]address.Address)
|
||||||
|
if cctx.Bool("robust-addresses") {
|
||||||
|
iact, err := tree.GetActor(_init.Address)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to load init actor: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ist, err := _init.Load(store, iact)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to load init actor state: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ist.ForEachActor(func(id abi.ActorID, addr address.Address) error {
|
||||||
|
idAddr, err := address.NewIDAddress(uint64(id))
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to write to addr map: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
robustMap[idAddr] = addr
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to invert init address map: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var infos []accountInfo
|
var infos []accountInfo
|
||||||
err = tree.ForEach(func(addr address.Address, act *types.Actor) error {
|
err = tree.ForEach(func(addr address.Address, act *types.Actor) error {
|
||||||
|
|
||||||
@ -201,6 +235,23 @@ var chainBalanceStateCmd = &cli.Command{
|
|||||||
VestingAmount: types.FIL(big.NewInt(0)),
|
VestingAmount: types.FIL(big.NewInt(0)),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cctx.Bool("robust-addresses") {
|
||||||
|
robust, found := robustMap[addr]
|
||||||
|
if found {
|
||||||
|
ai.Address = robust
|
||||||
|
} else {
|
||||||
|
id, err := address.IDFromAddress(addr)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to get ID address: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This is not the correctest way to determine whether a robust address should exist
|
||||||
|
if id >= genesis.MinerStart {
|
||||||
|
return xerrors.Errorf("address doesn't have a robust address: %s", addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if minerInfo && builtin.IsStorageMinerActor(act.Code) {
|
if minerInfo && builtin.IsStorageMinerActor(act.Code) {
|
||||||
pow, _, _, err := stmgr.GetPowerRaw(ctx, sm, sroot, addr)
|
pow, _, _, err := stmgr.GetPowerRaw(ctx, sm, sroot, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -372,7 +423,7 @@ var chainPledgeCmd = &cli.Command{
|
|||||||
pledgeCollateral = c
|
pledgeCollateral = c
|
||||||
}
|
}
|
||||||
|
|
||||||
circ, err := sm.GetCirculatingSupplyDetailed(ctx, abi.ChainEpoch(epoch), state)
|
circ, err := sm.GetVMCirculatingSupplyDetailed(ctx, abi.ChainEpoch(epoch), state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -32,10 +32,10 @@ import (
|
|||||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
_ "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 keyInfoOutput struct {
|
||||||
Type string
|
Type types.KeyType
|
||||||
Address string
|
Address string
|
||||||
PublicKey string
|
PublicKey string
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ var keyinfoVerifyCmd = &cli.Command{
|
|||||||
return xerrors.Errorf("decoding key: '%s': %w", fileName, err)
|
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)
|
return fmt.Errorf("%s of type %s is incorrect", fileName, keyInfo.Type)
|
||||||
}
|
}
|
||||||
case modules.KTJwtHmacSecret:
|
case modules.KTJwtHmacSecret:
|
||||||
@ -98,7 +98,7 @@ var keyinfoVerifyCmd = &cli.Command{
|
|||||||
if string(name) != modules.JWTSecretName {
|
if string(name) != modules.JWTSecretName {
|
||||||
return fmt.Errorf("%s of type %s is incorrect", fileName, keyInfo.Type)
|
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()
|
keystore := wallet.NewMemKeyStore()
|
||||||
w, err := wallet.NewWallet(keystore)
|
w, err := wallet.NewWallet(keystore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -214,7 +214,7 @@ var keyinfoImportCmd = &cli.Command{
|
|||||||
fmt.Printf("%s\n", peerid.String())
|
fmt.Printf("%s\n", peerid.String())
|
||||||
|
|
||||||
break
|
break
|
||||||
case wallet.KTSecp256k1, wallet.KTBLS:
|
case types.KTSecp256k1, types.KTBLS:
|
||||||
w, err := wallet.NewWallet(keystore)
|
w, err := wallet.NewWallet(keystore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -317,7 +317,7 @@ var keyinfoInfoCmd = &cli.Command{
|
|||||||
kio.PublicKey = base64.StdEncoding.EncodeToString(pkBytes)
|
kio.PublicKey = base64.StdEncoding.EncodeToString(pkBytes)
|
||||||
|
|
||||||
break
|
break
|
||||||
case wallet.KTSecp256k1, wallet.KTBLS:
|
case types.KTSecp256k1, types.KTBLS:
|
||||||
kio.Type = keyInfo.Type
|
kio.Type = keyInfo.Type
|
||||||
|
|
||||||
key, err := wallet.NewKey(keyInfo)
|
key, err := wallet.NewKey(keyInfo)
|
||||||
@ -366,7 +366,7 @@ var keyinfoNewCmd = &cli.Command{
|
|||||||
return fmt.Errorf("please specify a type to generate")
|
return fmt.Errorf("please specify a type to generate")
|
||||||
}
|
}
|
||||||
|
|
||||||
keyType := cctx.Args().First()
|
keyType := types.KeyType(cctx.Args().First())
|
||||||
flagOutput := cctx.String("output")
|
flagOutput := cctx.String("output")
|
||||||
|
|
||||||
if i := SliceIndex(len(validTypes), func(i int) bool {
|
if i := SliceIndex(len(validTypes), func(i int) bool {
|
||||||
@ -404,8 +404,8 @@ var keyinfoNewCmd = &cli.Command{
|
|||||||
keyInfo = ki
|
keyInfo = ki
|
||||||
|
|
||||||
break
|
break
|
||||||
case wallet.KTSecp256k1, wallet.KTBLS:
|
case types.KTSecp256k1, types.KTBLS:
|
||||||
key, err := wallet.GenerateKey(wallet.ActSigType(keyType))
|
key, err := wallet.GenerateKey(keyType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -418,7 +418,7 @@ var keyinfoNewCmd = &cli.Command{
|
|||||||
|
|
||||||
filename := flagOutput
|
filename := flagOutput
|
||||||
filename = strings.ReplaceAll(filename, "<addr>", keyAddr)
|
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)
|
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
248
cmd/lotus-shed/ledger.go
Normal file
248
cmd/lotus-shed/ledger.go
Normal file
@ -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,
|
syncCmd,
|
||||||
stateTreePruneCmd,
|
stateTreePruneCmd,
|
||||||
datastoreCmd,
|
datastoreCmd,
|
||||||
|
ledgerCmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
app := &cli.App{
|
app := &cli.App{
|
||||||
|
@ -5,6 +5,11 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"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"
|
"github.com/filecoin-project/lotus/build"
|
||||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||||
|
|
||||||
@ -34,6 +39,7 @@ var actorCmd = &cli.Command{
|
|||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
actorSetAddrsCmd,
|
actorSetAddrsCmd,
|
||||||
actorWithdrawCmd,
|
actorWithdrawCmd,
|
||||||
|
actorRepayDebtCmd,
|
||||||
actorSetPeeridCmd,
|
actorSetPeeridCmd,
|
||||||
actorSetOwnerCmd,
|
actorSetOwnerCmd,
|
||||||
actorControl,
|
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{
|
var actorControl = &cli.Command{
|
||||||
Name: "control",
|
Name: "control",
|
||||||
Usage: "Manage control addresses",
|
Usage: "Manage control addresses",
|
||||||
|
@ -27,7 +27,6 @@ import (
|
|||||||
cborutil "github.com/filecoin-project/go-cbor-util"
|
cborutil "github.com/filecoin-project/go-cbor-util"
|
||||||
paramfetch "github.com/filecoin-project/go-paramfetch"
|
paramfetch "github.com/filecoin-project/go-paramfetch"
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"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"
|
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/ffiwrapper"
|
||||||
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||||
@ -156,7 +155,7 @@ var initCmd = &cli.Command{
|
|||||||
log.Info("Checking full node sync status")
|
log.Info("Checking full node sync status")
|
||||||
|
|
||||||
if !cctx.Bool("genesis-miner") && !cctx.Bool("nosync") {
|
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)
|
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") != "" {
|
if cctx.String("worker") != "" {
|
||||||
worker, err = address.NewFromString(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?
|
} 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
|
// TODO: Transfer some initial funds to worker
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -72,7 +72,7 @@ var initRestoreCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !cctx.Bool("nosync") {
|
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)
|
return xerrors.Errorf("sync wait: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ var runCmd = &cli.Command{
|
|||||||
log.Info("Checking full node sync status")
|
log.Info("Checking full node sync status")
|
||||||
|
|
||||||
if !cctx.Bool("nosync") {
|
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)
|
return xerrors.Errorf("sync wait: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,8 @@ var sealingWorkersCmd = &cli.Command{
|
|||||||
cpuBars := int(stat.CpuUse * barCols / stat.Info.Resources.CPUs)
|
cpuBars := int(stat.CpuUse * barCols / stat.Info.Resources.CPUs)
|
||||||
cpuBar := strings.Repeat("|", cpuBars) + strings.Repeat(" ", int(barCols)-cpuBars)
|
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)
|
ramBarsRes := int(stat.Info.Resources.MemReserved * barCols / stat.Info.Resources.MemPhysical)
|
||||||
ramBarsUsed := int(stat.MemUsedMin * barCols / stat.Info.Resources.MemPhysical)
|
ramBarsUsed := int(stat.MemUsedMin * barCols / stat.Info.Resources.MemPhysical)
|
||||||
|
@ -19,13 +19,8 @@ type LoggedWallet struct {
|
|||||||
under api.WalletAPI
|
under api.WalletAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *LoggedWallet) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
|
func (c *LoggedWallet) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) {
|
||||||
n, err := typ.Name()
|
log.Infow("WalletNew", "type", typ)
|
||||||
if err != nil {
|
|
||||||
return address.Address{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infow("WalletNew", "type", n)
|
|
||||||
|
|
||||||
return c.under.WalletNew(ctx, typ)
|
return c.under.WalletNew(ctx, typ)
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,11 @@ import (
|
|||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-jsonrpc"
|
"github.com/filecoin-project/go-jsonrpc"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
"github.com/filecoin-project/lotus/chain/wallet"
|
||||||
|
ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger"
|
||||||
lcli "github.com/filecoin-project/lotus/cli"
|
lcli "github.com/filecoin-project/lotus/cli"
|
||||||
"github.com/filecoin-project/lotus/lib/lotuslog"
|
"github.com/filecoin-project/lotus/lib/lotuslog"
|
||||||
"github.com/filecoin-project/lotus/node/repo"
|
"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",
|
Usage: "host address and port the wallet api will listen on",
|
||||||
Value: "0.0.0.0:1777",
|
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 {
|
Action: func(cctx *cli.Context) error {
|
||||||
log.Info("Starting lotus wallet")
|
log.Info("Starting lotus wallet")
|
||||||
@ -94,11 +101,24 @@ var runCmd = &cli.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
w, err := wallet.NewWallet(ks)
|
lw, err := wallet.NewWallet(ks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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")
|
address := cctx.String("listen")
|
||||||
mux := mux.NewRouter()
|
mux := mux.NewRouter()
|
||||||
|
|
||||||
|
38
cmd/tvx/codenames.go
Normal file
38
cmd/tvx/codenames.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProtocolCodenames is a table that summarises the protocol codenames that
|
||||||
|
// will be set on extracted vectors, depending on the original execution height.
|
||||||
|
//
|
||||||
|
// Implementers rely on these names to filter the vectors they can run through
|
||||||
|
// their implementations, based on their support level
|
||||||
|
var ProtocolCodenames = []struct {
|
||||||
|
firstEpoch abi.ChainEpoch
|
||||||
|
name string
|
||||||
|
}{
|
||||||
|
{0, "genesis"},
|
||||||
|
{build.UpgradeBreezeHeight + 1, "breeze"},
|
||||||
|
{build.UpgradeSmokeHeight + 1, "smoke"},
|
||||||
|
{build.UpgradeIgnitionHeight + 1, "ignition"},
|
||||||
|
{build.UpgradeRefuelHeight + 1, "refuel"},
|
||||||
|
{build.UpgradeActorsV2Height + 1, "actorsv2"},
|
||||||
|
{build.UpgradeTapeHeight + 1, "tape"},
|
||||||
|
{build.UpgradeLiftoffHeight + 1, "liftoff"},
|
||||||
|
{build.UpgradeKumquatHeight + 1, "postliftoff"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetProtocolCodename gets the protocol codename associated with a height.
|
||||||
|
func GetProtocolCodename(height abi.ChainEpoch) string {
|
||||||
|
for i, v := range ProtocolCodenames {
|
||||||
|
if height < v.firstEpoch {
|
||||||
|
// found the cutoff, return previous.
|
||||||
|
return ProtocolCodenames[i-1].name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ProtocolCodenames[len(ProtocolCodenames)-1].name
|
||||||
|
}
|
28
cmd/tvx/codenames_test.go
Normal file
28
cmd/tvx/codenames_test.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestProtocolCodenames(t *testing.T) {
|
||||||
|
if height := abi.ChainEpoch(100); GetProtocolCodename(height) != "genesis" {
|
||||||
|
t.Fatal("expected genesis codename")
|
||||||
|
}
|
||||||
|
|
||||||
|
if height := abi.ChainEpoch(build.UpgradeBreezeHeight + 1); GetProtocolCodename(height) != "breeze" {
|
||||||
|
t.Fatal("expected breeze codename")
|
||||||
|
}
|
||||||
|
|
||||||
|
if height := build.UpgradeActorsV2Height + 1; GetProtocolCodename(height) != "actorsv2" {
|
||||||
|
t.Fatal("expected actorsv2 codename")
|
||||||
|
}
|
||||||
|
|
||||||
|
if height := abi.ChainEpoch(math.MaxInt64); GetProtocolCodename(height) != ProtocolCodenames[len(ProtocolCodenames)-1].name {
|
||||||
|
t.Fatal("expected last codename")
|
||||||
|
}
|
||||||
|
}
|
@ -72,20 +72,24 @@ func runExecLotus(_ *cli.Context) error {
|
|||||||
|
|
||||||
func executeTestVector(tv schema.TestVector) error {
|
func executeTestVector(tv schema.TestVector) error {
|
||||||
log.Println("executing test vector:", tv.Meta.ID)
|
log.Println("executing test vector:", tv.Meta.ID)
|
||||||
r := new(conformance.LogReporter)
|
|
||||||
switch class := tv.Class; class {
|
|
||||||
case "message":
|
|
||||||
conformance.ExecuteMessageVector(r, &tv)
|
|
||||||
case "tipset":
|
|
||||||
conformance.ExecuteTipsetVector(r, &tv)
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("test vector class %s not supported", class)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.Failed() {
|
for _, v := range tv.Pre.Variants {
|
||||||
log.Println(color.HiRedString("❌ test vector failed"))
|
r := new(conformance.LogReporter)
|
||||||
} else {
|
|
||||||
log.Println(color.GreenString("✅ test vector succeeded"))
|
switch class, v := tv.Class, v; class {
|
||||||
|
case "message":
|
||||||
|
conformance.ExecuteMessageVector(r, &tv, &v)
|
||||||
|
case "tipset":
|
||||||
|
conformance.ExecuteTipsetVector(r, &tv, &v)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("test vector class %s not supported", class)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Failed() {
|
||||||
|
log.Println(color.HiRedString("❌ test vector failed for variant %s", v.ID))
|
||||||
|
} else {
|
||||||
|
log.Println(color.GreenString("✅ test vector succeeded for variant %s", v.ID))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -135,7 +135,7 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the circulating supply before the message was executed.
|
// 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 {
|
if err != nil {
|
||||||
return fmt.Errorf("failed while fetching circulating supply: %w", err)
|
return fmt.Errorf("failed while fetching circulating supply: %w", err)
|
||||||
}
|
}
|
||||||
@ -347,6 +347,13 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nv, err := fapi.StateNetworkVersion(ctx, execTs.Key())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
codename := GetProtocolCodename(execTs.Height())
|
||||||
|
|
||||||
// Write out the test vector.
|
// Write out the test vector.
|
||||||
vector := schema.TestVector{
|
vector := schema.TestVector{
|
||||||
Class: schema.ClassMessage,
|
Class: schema.ClassMessage,
|
||||||
@ -363,10 +370,15 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
|
|||||||
{Source: fmt.Sprintf("execution_tipset:%s", execTs.Key().String())},
|
{Source: fmt.Sprintf("execution_tipset:%s", execTs.Key().String())},
|
||||||
{Source: "github.com/filecoin-project/lotus", Version: version.String()}},
|
{Source: "github.com/filecoin-project/lotus", Version: version.String()}},
|
||||||
},
|
},
|
||||||
|
Selector: schema.Selector{
|
||||||
|
schema.SelectorMinProtocolVersion: codename,
|
||||||
|
},
|
||||||
Randomness: recordingRand.Recorded(),
|
Randomness: recordingRand.Recorded(),
|
||||||
CAR: out.Bytes(),
|
CAR: out.Bytes(),
|
||||||
Pre: &schema.Preconditions{
|
Pre: &schema.Preconditions{
|
||||||
Epoch: int64(execTs.Height()),
|
Variants: []schema.Variant{
|
||||||
|
{ID: codename, Epoch: int64(execTs.Height()), NetworkVersion: uint(nv)},
|
||||||
|
},
|
||||||
CircSupply: circSupply.Int,
|
CircSupply: circSupply.Int,
|
||||||
BaseFee: basefee.Int,
|
BaseFee: basefee.Int,
|
||||||
StateTree: &schema.StateTree{
|
StateTree: &schema.StateTree{
|
||||||
|
@ -87,7 +87,7 @@ type proxyingBlockstore struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
api api.FullNode
|
api api.FullNode
|
||||||
|
|
||||||
lk sync.RWMutex
|
lk sync.Mutex
|
||||||
tracing bool
|
tracing bool
|
||||||
traced map[cid.Cid]struct{}
|
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) {
|
func (pb *proxyingBlockstore) Get(cid cid.Cid) (blocks.Block, error) {
|
||||||
pb.lk.RLock()
|
pb.lk.Lock()
|
||||||
if pb.tracing {
|
if pb.tracing {
|
||||||
pb.traced[cid] = struct{}{}
|
pb.traced[cid] = struct{}{}
|
||||||
}
|
}
|
||||||
pb.lk.RUnlock()
|
pb.lk.Unlock()
|
||||||
|
|
||||||
if block, err := pb.Blockstore.Get(cid); err == nil {
|
if block, err := pb.Blockstore.Get(cid); err == nil {
|
||||||
return block, err
|
return block, err
|
||||||
@ -140,3 +140,12 @@ func (pb *proxyingBlockstore) Get(cid cid.Cid) (blocks.Block, error) {
|
|||||||
|
|
||||||
return block, nil
|
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)
|
||||||
|
}
|
||||||
|
@ -11,6 +11,11 @@ import (
|
|||||||
"github.com/filecoin-project/test-vectors/schema"
|
"github.com/filecoin-project/test-vectors/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var invokees = map[schema.Class]func(Reporter, *schema.TestVector, *schema.Variant){
|
||||||
|
schema.ClassMessage: ExecuteMessageVector,
|
||||||
|
schema.ClassTipset: ExecuteTipsetVector,
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// EnvSkipConformance, if 1, skips the conformance test suite.
|
// EnvSkipConformance, if 1, skips the conformance test suite.
|
||||||
EnvSkipConformance = "SKIP_CONFORMANCE"
|
EnvSkipConformance = "SKIP_CONFORMANCE"
|
||||||
@ -120,13 +125,16 @@ func TestConformance(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dispatch the execution depending on the vector class.
|
// dispatch the execution depending on the vector class.
|
||||||
switch vector.Class {
|
invokee, ok := invokees[vector.Class]
|
||||||
case "message":
|
if !ok {
|
||||||
ExecuteMessageVector(t, &vector)
|
t.Fatalf("unsupported test vector class: %s", vector.Class)
|
||||||
case "tipset":
|
}
|
||||||
ExecuteTipsetVector(t, &vector)
|
|
||||||
default:
|
for _, variant := range vector.Pre.Variants {
|
||||||
t.Fatalf("test vector class not supported: %s", vector.Class)
|
variant := variant
|
||||||
|
t.Run(variant.ID, func(t *testing.T) {
|
||||||
|
invokee(t, &vector, &variant)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ type ExecuteTipsetResult struct {
|
|||||||
// This method returns the the receipts root, the poststate root, and the VM
|
// This method returns the the receipts root, the poststate root, and the VM
|
||||||
// message results. The latter _include_ implicit messages, such as cron ticks
|
// message results. The latter _include_ implicit messages, such as cron ticks
|
||||||
// and reward withdrawal per miner.
|
// and reward withdrawal per miner.
|
||||||
func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, preroot cid.Cid, parentEpoch abi.ChainEpoch, tipset *schema.Tipset) (*ExecuteTipsetResult, error) {
|
func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, preroot cid.Cid, parentEpoch abi.ChainEpoch, tipset *schema.Tipset, execEpoch abi.ChainEpoch) (*ExecuteTipsetResult, error) {
|
||||||
var (
|
var (
|
||||||
syscalls = vm.Syscalls(ffiwrapper.ProofVerifier)
|
syscalls = vm.Syscalls(ffiwrapper.ProofVerifier)
|
||||||
vmRand = NewFixedRand()
|
vmRand = NewFixedRand()
|
||||||
@ -121,11 +121,10 @@ func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, preroot
|
|||||||
messages []*types.Message
|
messages []*types.Message
|
||||||
results []*vm.ApplyRet
|
results []*vm.ApplyRet
|
||||||
|
|
||||||
epoch = abi.ChainEpoch(tipset.Epoch)
|
|
||||||
basefee = abi.NewTokenAmount(tipset.BaseFee.Int64())
|
basefee = abi.NewTokenAmount(tipset.BaseFee.Int64())
|
||||||
)
|
)
|
||||||
|
|
||||||
postcid, receiptsroot, err := sm.ApplyBlocks(context.Background(), parentEpoch, preroot, blocks, epoch, vmRand, func(_ cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
|
postcid, receiptsroot, err := sm.ApplyBlocks(context.Background(), parentEpoch, preroot, blocks, execEpoch, vmRand, func(_ cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
|
||||||
messages = append(messages, msg)
|
messages = append(messages, msg)
|
||||||
results = append(results, ret)
|
results = append(results, ret)
|
||||||
return nil
|
return nil
|
||||||
|
@ -30,11 +30,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ExecuteMessageVector executes a message-class test vector.
|
// ExecuteMessageVector executes a message-class test vector.
|
||||||
func ExecuteMessageVector(r Reporter, vector *schema.TestVector) {
|
func ExecuteMessageVector(r Reporter, vector *schema.TestVector, variant *schema.Variant) {
|
||||||
var (
|
var (
|
||||||
ctx = context.Background()
|
ctx = context.Background()
|
||||||
epoch = vector.Pre.Epoch
|
baseEpoch = variant.Epoch
|
||||||
root = vector.Pre.StateTree.RootCID
|
root = vector.Pre.StateTree.RootCID
|
||||||
)
|
)
|
||||||
|
|
||||||
// Load the CAR into a new temporary Blockstore.
|
// Load the CAR into a new temporary Blockstore.
|
||||||
@ -53,16 +53,16 @@ func ExecuteMessageVector(r Reporter, vector *schema.TestVector) {
|
|||||||
r.Fatalf("failed to deserialize message: %s", err)
|
r.Fatalf("failed to deserialize message: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add an epoch if one's set.
|
// add the epoch offset if one is set.
|
||||||
if m.Epoch != nil {
|
if m.EpochOffset != nil {
|
||||||
epoch = *m.Epoch
|
baseEpoch += *m.EpochOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the message.
|
// Execute the message.
|
||||||
var ret *vm.ApplyRet
|
var ret *vm.ApplyRet
|
||||||
ret, root, err = driver.ExecuteMessage(bs, ExecuteMessageParams{
|
ret, root, err = driver.ExecuteMessage(bs, ExecuteMessageParams{
|
||||||
Preroot: root,
|
Preroot: root,
|
||||||
Epoch: abi.ChainEpoch(epoch),
|
Epoch: abi.ChainEpoch(baseEpoch),
|
||||||
Message: msg,
|
Message: msg,
|
||||||
BaseFee: BaseFeeOrDefault(vector.Pre.BaseFee),
|
BaseFee: BaseFeeOrDefault(vector.Pre.BaseFee),
|
||||||
CircSupply: CircSupplyOrDefault(vector.Pre.CircSupply),
|
CircSupply: CircSupplyOrDefault(vector.Pre.CircSupply),
|
||||||
@ -86,10 +86,10 @@ func ExecuteMessageVector(r Reporter, vector *schema.TestVector) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteTipsetVector executes a tipset-class test vector.
|
// ExecuteTipsetVector executes a tipset-class test vector.
|
||||||
func ExecuteTipsetVector(r Reporter, vector *schema.TestVector) {
|
func ExecuteTipsetVector(r Reporter, vector *schema.TestVector, variant *schema.Variant) {
|
||||||
var (
|
var (
|
||||||
ctx = context.Background()
|
ctx = context.Background()
|
||||||
prevEpoch = vector.Pre.Epoch
|
baseEpoch = abi.ChainEpoch(variant.Epoch)
|
||||||
root = vector.Pre.StateTree.RootCID
|
root = vector.Pre.StateTree.RootCID
|
||||||
tmpds = ds.NewMapDatastore()
|
tmpds = ds.NewMapDatastore()
|
||||||
)
|
)
|
||||||
@ -105,9 +105,11 @@ func ExecuteTipsetVector(r Reporter, vector *schema.TestVector) {
|
|||||||
|
|
||||||
// Apply every tipset.
|
// Apply every tipset.
|
||||||
var receiptsIdx int
|
var receiptsIdx int
|
||||||
|
var prevEpoch = baseEpoch
|
||||||
for i, ts := range vector.ApplyTipsets {
|
for i, ts := range vector.ApplyTipsets {
|
||||||
ts := ts // capture
|
ts := ts // capture
|
||||||
ret, err := driver.ExecuteTipset(bs, tmpds, root, abi.ChainEpoch(prevEpoch), &ts)
|
execEpoch := baseEpoch + abi.ChainEpoch(ts.EpochOffset)
|
||||||
|
ret, err := driver.ExecuteTipset(bs, tmpds, root, prevEpoch, &ts, execEpoch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Fatalf("failed to apply tipset %d message: %s", i, err)
|
r.Fatalf("failed to apply tipset %d message: %s", i, err)
|
||||||
}
|
}
|
||||||
@ -122,7 +124,7 @@ func ExecuteTipsetVector(r Reporter, vector *schema.TestVector) {
|
|||||||
r.Errorf("post receipts root doesn't match; expected: %s, was: %s", expected, actual)
|
r.Errorf("post receipts root doesn't match; expected: %s, was: %s", expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
prevEpoch = ts.Epoch
|
prevEpoch = execEpoch
|
||||||
root = ret.PostStateRoot
|
root = ret.PostStateRoot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
* [ClientMinerQueryOffer](#ClientMinerQueryOffer)
|
* [ClientMinerQueryOffer](#ClientMinerQueryOffer)
|
||||||
* [ClientQueryAsk](#ClientQueryAsk)
|
* [ClientQueryAsk](#ClientQueryAsk)
|
||||||
* [ClientRemoveImport](#ClientRemoveImport)
|
* [ClientRemoveImport](#ClientRemoveImport)
|
||||||
|
* [ClientRestartDataTransfer](#ClientRestartDataTransfer)
|
||||||
* [ClientRetrieve](#ClientRetrieve)
|
* [ClientRetrieve](#ClientRetrieve)
|
||||||
* [ClientRetrieveTryRestartInsufficientFunds](#ClientRetrieveTryRestartInsufficientFunds)
|
* [ClientRetrieveTryRestartInsufficientFunds](#ClientRetrieveTryRestartInsufficientFunds)
|
||||||
* [ClientRetrieveWithEvents](#ClientRetrieveWithEvents)
|
* [ClientRetrieveWithEvents](#ClientRetrieveWithEvents)
|
||||||
@ -155,7 +156,6 @@
|
|||||||
* [StateMinerRecoveries](#StateMinerRecoveries)
|
* [StateMinerRecoveries](#StateMinerRecoveries)
|
||||||
* [StateMinerSectorCount](#StateMinerSectorCount)
|
* [StateMinerSectorCount](#StateMinerSectorCount)
|
||||||
* [StateMinerSectors](#StateMinerSectors)
|
* [StateMinerSectors](#StateMinerSectors)
|
||||||
* [StateMsgGasCost](#StateMsgGasCost)
|
|
||||||
* [StateNetworkName](#StateNetworkName)
|
* [StateNetworkName](#StateNetworkName)
|
||||||
* [StateNetworkVersion](#StateNetworkVersion)
|
* [StateNetworkVersion](#StateNetworkVersion)
|
||||||
* [StateReadState](#StateReadState)
|
* [StateReadState](#StateReadState)
|
||||||
@ -165,6 +165,7 @@
|
|||||||
* [StateSectorGetInfo](#StateSectorGetInfo)
|
* [StateSectorGetInfo](#StateSectorGetInfo)
|
||||||
* [StateSectorPartition](#StateSectorPartition)
|
* [StateSectorPartition](#StateSectorPartition)
|
||||||
* [StateSectorPreCommitInfo](#StateSectorPreCommitInfo)
|
* [StateSectorPreCommitInfo](#StateSectorPreCommitInfo)
|
||||||
|
* [StateVMCirculatingSupplyInternal](#StateVMCirculatingSupplyInternal)
|
||||||
* [StateVerifiedClientStatus](#StateVerifiedClientStatus)
|
* [StateVerifiedClientStatus](#StateVerifiedClientStatus)
|
||||||
* [StateVerifiedRegistryRootKey](#StateVerifiedRegistryRootKey)
|
* [StateVerifiedRegistryRootKey](#StateVerifiedRegistryRootKey)
|
||||||
* [StateVerifierStatus](#StateVerifierStatus)
|
* [StateVerifierStatus](#StateVerifierStatus)
|
||||||
@ -226,7 +227,7 @@ Response:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"Version": "string value",
|
"Version": "string value",
|
||||||
"APIVersion": 4096,
|
"APIVersion": 4352,
|
||||||
"BlockDelay": 42
|
"BlockDelay": 42
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -462,7 +463,10 @@ Response:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -1160,6 +1164,23 @@ Inputs:
|
|||||||
|
|
||||||
Response: `{}`
|
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
|
||||||
ClientRetrieve initiates the retrieval of a file, as specified in the order.
|
ClientRetrieve initiates the retrieval of a file, as specified in the order.
|
||||||
|
|
||||||
@ -1333,7 +1354,10 @@ Inputs:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
9,
|
9,
|
||||||
[
|
[
|
||||||
@ -1369,7 +1393,10 @@ Inputs:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -1429,7 +1456,10 @@ Inputs:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"MaxFee": "0"
|
"MaxFee": "0"
|
||||||
@ -1457,7 +1487,10 @@ Response:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -1741,11 +1774,17 @@ Inputs:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Signature": {
|
"Signature": {
|
||||||
"Type": 2,
|
"Type": 2,
|
||||||
"Data": "Ynl0ZSBhcnJheQ=="
|
"Data": "Ynl0ZSBhcnJheQ=="
|
||||||
|
},
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -1782,7 +1821,10 @@ Inputs:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"MaxFee": "0"
|
"MaxFee": "0"
|
||||||
@ -1803,11 +1845,17 @@ Response:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Signature": {
|
"Signature": {
|
||||||
"Type": 2,
|
"Type": 2,
|
||||||
"Data": "Ynl0ZSBhcnJheQ=="
|
"Data": "Ynl0ZSBhcnJheQ=="
|
||||||
|
},
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -1832,11 +1880,17 @@ Inputs:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Signature": {
|
"Signature": {
|
||||||
"Type": 2,
|
"Type": 2,
|
||||||
"Data": "Ynl0ZSBhcnJheQ=="
|
"Data": "Ynl0ZSBhcnJheQ=="
|
||||||
|
},
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -1916,11 +1970,17 @@ Response:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Signature": {
|
"Signature": {
|
||||||
"Type": 2,
|
"Type": 2,
|
||||||
"Data": "Ynl0ZSBhcnJheQ=="
|
"Data": "Ynl0ZSBhcnJheQ=="
|
||||||
|
},
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2928,7 +2988,7 @@ Response:
|
|||||||
|
|
||||||
## State
|
## State
|
||||||
The State methods are used to query, inspect, and interact with chain state.
|
The State methods are used to query, inspect, and interact with chain state.
|
||||||
All methods take a TipSetKey as a parameter. The state looked up is the state at that tipset.
|
Most methods take a TipSetKey as a parameter. The state looked up is the state at that tipset.
|
||||||
A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used.
|
A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used.
|
||||||
|
|
||||||
|
|
||||||
@ -2997,7 +3057,10 @@ Inputs:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -3013,6 +3076,9 @@ Inputs:
|
|||||||
Response:
|
Response:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
"MsgCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"Msg": {
|
"Msg": {
|
||||||
"Version": 42,
|
"Version": 42,
|
||||||
"To": "t01234",
|
"To": "t01234",
|
||||||
@ -3023,13 +3089,28 @@ Response:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"MsgRct": {
|
"MsgRct": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9
|
||||||
},
|
},
|
||||||
|
"GasCost": {
|
||||||
|
"Message": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
|
"GasUsed": "0",
|
||||||
|
"BaseFeeBurn": "0",
|
||||||
|
"OverEstimationBurn": "0",
|
||||||
|
"MinerPenalty": "0",
|
||||||
|
"MinerTip": "0",
|
||||||
|
"Refund": "0",
|
||||||
|
"TotalCost": "0"
|
||||||
|
},
|
||||||
"ExecutionTrace": {
|
"ExecutionTrace": {
|
||||||
"Msg": {
|
"Msg": {
|
||||||
"Version": 42,
|
"Version": 42,
|
||||||
@ -3041,7 +3122,10 @@ Response:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"MsgRct": {
|
"MsgRct": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
@ -3094,7 +3178,8 @@ Response:
|
|||||||
```
|
```
|
||||||
|
|
||||||
### StateCirculatingSupply
|
### 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
|
Perms: read
|
||||||
@ -3113,16 +3198,7 @@ Inputs:
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Response:
|
Response: `"0"`
|
||||||
```json
|
|
||||||
{
|
|
||||||
"FilVested": "0",
|
|
||||||
"FilMined": "0",
|
|
||||||
"FilBurnt": "0",
|
|
||||||
"FilLocked": "0",
|
|
||||||
"FilCirculating": "0"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### StateCompute
|
### StateCompute
|
||||||
StateCompute is a flexible command that applies the given messages on the given tipset.
|
StateCompute is a flexible command that applies the given messages on the given tipset.
|
||||||
@ -3287,16 +3363,8 @@ Inputs:
|
|||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Version": 42,
|
"To": "f01234",
|
||||||
"To": "t01234",
|
"From": "f01234"
|
||||||
"From": "t01234",
|
|
||||||
"Nonce": 42,
|
|
||||||
"Value": "0",
|
|
||||||
"GasLimit": 9,
|
|
||||||
"GasFeeCap": "0",
|
|
||||||
"GasPremium": "0",
|
|
||||||
"Method": 1,
|
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -3906,45 +3974,6 @@ Inputs:
|
|||||||
|
|
||||||
Response: `null`
|
Response: `null`
|
||||||
|
|
||||||
### StateMsgGasCost
|
|
||||||
StateMsgGasCost searches for a message in the chain, and returns details of the messages gas costs, including the penalty and miner tip
|
|
||||||
|
|
||||||
|
|
||||||
Perms: read
|
|
||||||
|
|
||||||
Inputs:
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
|
||||||
},
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
Response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"Message": {
|
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
|
||||||
},
|
|
||||||
"GasUsed": "0",
|
|
||||||
"BaseFeeBurn": "0",
|
|
||||||
"OverEstimationBurn": "0",
|
|
||||||
"MinerPenalty": "0",
|
|
||||||
"MinerTip": "0",
|
|
||||||
"Refund": "0",
|
|
||||||
"TotalCost": "0"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### StateNetworkName
|
### StateNetworkName
|
||||||
StateNetworkName returns the name of the network the node is synced to
|
StateNetworkName returns the name of the network the node is synced to
|
||||||
|
|
||||||
@ -3975,7 +4004,7 @@ Inputs:
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Response: `5`
|
Response: `6`
|
||||||
|
|
||||||
### StateReadState
|
### StateReadState
|
||||||
StateReadState returns the indicated actor's state.
|
StateReadState returns the indicated actor's state.
|
||||||
@ -4007,7 +4036,8 @@ Response:
|
|||||||
```
|
```
|
||||||
|
|
||||||
### StateReplay
|
### StateReplay
|
||||||
StateReplay returns the result of executing the indicated message, assuming it was executed in the indicated tipset.
|
StateReplay replays a given message, assuming it was included in a block in the specified tipset.
|
||||||
|
If no tipset key is provided, the appropriate tipset is looked up.
|
||||||
|
|
||||||
|
|
||||||
Perms: read
|
Perms: read
|
||||||
@ -4032,6 +4062,9 @@ Inputs:
|
|||||||
Response:
|
Response:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
"MsgCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"Msg": {
|
"Msg": {
|
||||||
"Version": 42,
|
"Version": 42,
|
||||||
"To": "t01234",
|
"To": "t01234",
|
||||||
@ -4042,13 +4075,28 @@ Response:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"MsgRct": {
|
"MsgRct": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9
|
||||||
},
|
},
|
||||||
|
"GasCost": {
|
||||||
|
"Message": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
|
"GasUsed": "0",
|
||||||
|
"BaseFeeBurn": "0",
|
||||||
|
"OverEstimationBurn": "0",
|
||||||
|
"MinerPenalty": "0",
|
||||||
|
"MinerTip": "0",
|
||||||
|
"Refund": "0",
|
||||||
|
"TotalCost": "0"
|
||||||
|
},
|
||||||
"ExecutionTrace": {
|
"ExecutionTrace": {
|
||||||
"Msg": {
|
"Msg": {
|
||||||
"Version": 42,
|
"Version": 42,
|
||||||
@ -4060,7 +4108,10 @@ Response:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"MsgRct": {
|
"MsgRct": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
@ -4265,6 +4316,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
|
||||||
StateVerifiedClientStatus returns the data cap for the given address.
|
StateVerifiedClientStatus returns the data cap for the given address.
|
||||||
Returns nil if there is no entry in the data cap table for the
|
Returns nil if there is no entry in the data cap table for the
|
||||||
@ -4710,7 +4793,7 @@ Inputs:
|
|||||||
Response:
|
Response:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"Type": "string value",
|
"Type": "bls",
|
||||||
"PrivateKey": "Ynl0ZSBhcnJheQ=="
|
"PrivateKey": "Ynl0ZSBhcnJheQ=="
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -4740,7 +4823,7 @@ Inputs:
|
|||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Type": "string value",
|
"Type": "bls",
|
||||||
"PrivateKey": "Ynl0ZSBhcnJheQ=="
|
"PrivateKey": "Ynl0ZSBhcnJheQ=="
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -4760,6 +4843,8 @@ Response: `null`
|
|||||||
|
|
||||||
### WalletNew
|
### WalletNew
|
||||||
WalletNew creates a new address in the wallet with the given sigType.
|
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
|
Perms: write
|
||||||
@ -4767,7 +4852,7 @@ Perms: write
|
|||||||
Inputs:
|
Inputs:
|
||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
2
|
"bls"
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -4830,7 +4915,10 @@ Inputs:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
@ -4848,11 +4936,17 @@ Response:
|
|||||||
"GasFeeCap": "0",
|
"GasFeeCap": "0",
|
||||||
"GasPremium": "0",
|
"GasPremium": "0",
|
||||||
"Method": 1,
|
"Method": 1,
|
||||||
"Params": "Ynl0ZSBhcnJheQ=="
|
"Params": "Ynl0ZSBhcnJheQ==",
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Signature": {
|
"Signature": {
|
||||||
"Type": 2,
|
"Type": 2,
|
||||||
"Data": "Ynl0ZSBhcnJheQ=="
|
"Data": "Ynl0ZSBhcnJheQ=="
|
||||||
|
},
|
||||||
|
"CID": {
|
||||||
|
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
2
extern/oni
vendored
2
extern/oni
vendored
@ -1 +1 @@
|
|||||||
Subproject commit dbee44e4f940a502971f17116ccbba61ceaf2674
|
Subproject commit 10ed9ef576836186de3b8513c03cdc3fb18c44ed
|
9
extern/sector-storage/mock/mock.go
vendored
9
extern/sector-storage/mock/mock.go
vendored
@ -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) {
|
func (mgr *SectorMgr) SealCommit2(ctx context.Context, sid abi.SectorID, phase1Out storage.Commit1Out) (proof storage.Proof, err error) {
|
||||||
var out [32]byte
|
var out [1920]byte
|
||||||
for i := range out {
|
for i := range out[:len(phase1Out)] {
|
||||||
out[i] = phase1Out[i] ^ byte(sid.Number&0xff)
|
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) {
|
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
|
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] {
|
if b != svi.UnsealedCID.Bytes()[i]+svi.SealedCID.Bytes()[31-i]-svi.InteractiveRandomness[i]*svi.Randomness[i] {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
2
extern/test-vectors
vendored
2
extern/test-vectors
vendored
@ -1 +1 @@
|
|||||||
Subproject commit a8f968adeba1995f161f7be0048188affc425079
|
Subproject commit d9a75a7873aee0db28b87e3970d2ea16a2f37c6a
|
16
go.mod
16
go.mod
@ -20,28 +20,28 @@ require (
|
|||||||
github.com/drand/kyber v1.1.2
|
github.com/drand/kyber v1.1.2
|
||||||
github.com/dustin/go-humanize v1.0.0
|
github.com/dustin/go-humanize v1.0.0
|
||||||
github.com/elastic/go-sysinfo v1.3.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/filecoin-ffi v0.30.4-0.20200716204036-cddc56607e1d
|
||||||
github.com/filecoin-project/go-address v0.0.4
|
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-amt-ipld/v2 v2.1.1-0.20201006184820-924ee87a1349 // indirect
|
||||||
github.com/filecoin-project/go-bitfield v0.2.1
|
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-cbor-util v0.0.0-20191219014500-08c40a1e63a2
|
||||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
|
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-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-jsonrpc v0.1.2-0.20201008195726-68c6a2704e49
|
||||||
github.com/filecoin-project/go-multistore v0.0.3
|
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-padreader v0.0.0-20200903213702-ed5fae088b20
|
||||||
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261
|
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261
|
||||||
github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b
|
github.com/filecoin-project/go-state-types v0.0.0-20201013222834-41ea465f274f
|
||||||
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe
|
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-statestore v0.1.0
|
||||||
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b
|
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 v0.9.12
|
||||||
github.com/filecoin-project/specs-actors/v2 v2.1.0
|
github.com/filecoin-project/specs-actors/v2 v2.2.0
|
||||||
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796
|
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796
|
||||||
github.com/filecoin-project/test-vectors/schema v0.0.4
|
github.com/filecoin-project/test-vectors/schema v0.0.5
|
||||||
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
|
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
|
||||||
github.com/go-kit/kit v0.10.0
|
github.com/go-kit/kit v0.10.0
|
||||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||||
@ -66,7 +66,7 @@ require (
|
|||||||
github.com/ipfs/go-ds-pebble v0.0.2-0.20200921225637-ce220f8ac459
|
github.com/ipfs/go-ds-pebble v0.0.2-0.20200921225637-ce220f8ac459
|
||||||
github.com/ipfs/go-filestore v1.0.0
|
github.com/ipfs/go-filestore v1.0.0
|
||||||
github.com/ipfs/go-fs-lock v0.0.6
|
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-blockstore v1.0.1
|
||||||
github.com/ipfs/go-ipfs-chunker v0.0.5
|
github.com/ipfs/go-ipfs-chunker v0.0.5
|
||||||
github.com/ipfs/go-ipfs-ds-help v1.0.0
|
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-tls v0.1.3
|
||||||
github.com/libp2p/go-libp2p-yamux v0.2.8
|
github.com/libp2p/go-libp2p-yamux v0.2.8
|
||||||
github.com/libp2p/go-maddr-filter v0.1.0
|
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/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/multiformats/go-base32 v0.0.3
|
github.com/multiformats/go-base32 v0.0.3
|
||||||
@ -120,6 +121,7 @@ require (
|
|||||||
github.com/urfave/cli/v2 v2.2.0
|
github.com/urfave/cli/v2 v2.2.0
|
||||||
github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba
|
github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba
|
||||||
github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163
|
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/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
|
||||||
github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d
|
github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d
|
||||||
github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542
|
github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542
|
||||||
|
44
go.sum
44
go.sum
@ -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.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 h1:5bzFgL+oy7JITMTxUPJ00n7VxmYd/PdMp5mHFX40/RY=
|
||||||
github.com/fatih/color v1.8.0/go.mod h1:3l45GVGkyrnYNl9HoIjnp2NnNWvh6hLAqD8yTfGjnw8=
|
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/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 h1:eVfbdjEbpbzIrbiSa+PiGUY+oDK9HnUn+M1R/ggoHf8=
|
||||||
github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8=
|
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-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 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus=
|
||||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ=
|
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.9.0 h1:nTT8j7Hu3TM0wRWrGy83/ctawG7sleJGdFWtIsUsKgY=
|
||||||
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/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 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-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 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-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.9.1 h1:MgO+UkpreD6x8DV2Zkw2xlBogixfpw9/wf4+nBii7bU=
|
||||||
github.com/filecoin-project/go-fil-markets v0.7.1/go.mod h1:5Pt4DXQqUoUrp9QzlSdlYTpItXxwAtqKrxRWQ6hAOqk=
|
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 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=
|
github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24=
|
||||||
@ -262,12 +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-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-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-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 h1:cEDC5Ei8UuT99hPWhCjA72SM9AuRtnpvdSTIYbnzN8I=
|
||||||
github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g=
|
github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g=
|
||||||
github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b h1:bMUfG6Sy6YSMbsjQAO1Q2vEZldbSdsbRy/FX3OlTck0=
|
github.com/filecoin-project/go-state-types v0.0.0-20201013222834-41ea465f274f h1:TZDTu4MtBKSFLXWGKLy+cvC3nHfMFIrVgWLAz/+GgZQ=
|
||||||
github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g=
|
github.com/filecoin-project/go-state-types v0.0.0-20201013222834-41ea465f274f/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g=
|
||||||
github.com/filecoin-project/go-statemachine v0.0.0-20200714194326-a77c3ae20989/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
|
|
||||||
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw=
|
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw=
|
||||||
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
|
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=
|
github.com/filecoin-project/go-statestore v0.1.0 h1:t56reH59843TwXHkMcwyuayStBIiWBRilQjQ+5IiwdQ=
|
||||||
@ -275,15 +275,15 @@ 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 h1:fkRZSPrYpk42PV3/lIXiL0LHetxde7vyYYvSsttQtfg=
|
||||||
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/go.mod h1:Q0GQOBtKf1oE10eSXSlhN45kDBdGvEcVOqMiffqX+N8=
|
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.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 h1:iIvk58tuMtmloFNHhAOQHG+4Gci6Lui0n7DYQGi3cJk=
|
||||||
github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao=
|
github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao=
|
||||||
github.com/filecoin-project/specs-actors/v2 v2.1.0 h1:ocEuGz8DG2cUWw32c/tvF8D6xT+dGVWJTr5yDevU00g=
|
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/go.mod h1:E7fAX4CZkDVQvDNRCxfq+hc3nx56KcCKyuZf0hlQJ20=
|
github.com/filecoin-project/specs-actors/v2 v2.2.0 h1:IyCICb0NHYeD0sdSqjVGwWydn/7r7xXuxdpvGAcRCGY=
|
||||||
|
github.com/filecoin-project/specs-actors/v2 v2.2.0/go.mod h1:rlv5Mx9wUhV8Qsz+vUezZNm+zL4tK08O0HreKKPB2Wc=
|
||||||
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 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/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=
|
github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg=
|
||||||
github.com/filecoin-project/test-vectors/schema v0.0.4/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E=
|
github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E=
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||||
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNpjmVH56sVtS/RfclBAYocb4as=
|
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNpjmVH56sVtS/RfclBAYocb4as=
|
||||||
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ=
|
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ=
|
||||||
@ -538,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 h1:sn3TWwNVQqSeNjlWy6zQ1uUGAZrV3hPOyEA6y1/N2a0=
|
||||||
github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM=
|
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.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE=
|
||||||
github.com/ipfs/go-graphsync v0.2.1 h1:MdehhqBSuTI2LARfKLkpYnt0mUrqHs/mtuDnESXHBfU=
|
github.com/ipfs/go-graphsync v0.3.0 h1:I6Y20kSuCWkUvPoUWo4V3am704/9QjgDVVkf0zIV8+8=
|
||||||
github.com/ipfs/go-graphsync v0.2.1/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10=
|
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 h1:0IQdvwnAAUKmDE+PMJa5y1QiwOPHpI9+eAbQEEEYthk=
|
||||||
github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk=
|
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=
|
github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08=
|
||||||
@ -1047,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.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
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.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.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.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.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 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.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.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 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
|
||||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
@ -1424,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-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.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/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/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-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
|
||||||
github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
|
github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
|
||||||
@ -1445,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/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/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/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 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs=
|
||||||
go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw=
|
go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw=
|
||||||
go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ=
|
go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ=
|
||||||
@ -1517,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-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-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-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-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-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
@ -1660,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-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-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-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-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-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-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-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-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-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-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -18,19 +18,18 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
ds "github.com/ipfs/go-datastore"
|
ds "github.com/ipfs/go-datastore"
|
||||||
dssync "github.com/ipfs/go-datastore/sync"
|
|
||||||
|
|
||||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewTemporary returns a temporary blockstore.
|
// NewTemporary returns a temporary blockstore.
|
||||||
func NewTemporary() blockstore.Blockstore {
|
func NewTemporary() MemStore {
|
||||||
return NewBlockstore(ds.NewMapDatastore())
|
return make(MemStore)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTemporarySync returns a thread-safe temporary blockstore.
|
// NewTemporarySync returns a thread-safe temporary blockstore.
|
||||||
func NewTemporarySync() blockstore.Blockstore {
|
func NewTemporarySync() *SyncStore {
|
||||||
return NewBlockstore(dssync.MutexWrap(ds.NewMapDatastore()))
|
return &SyncStore{bs: make(MemStore)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WrapIDStore wraps the underlying blockstore in an "identity" blockstore.
|
// WrapIDStore wraps the underlying blockstore in an "identity" blockstore.
|
||||||
|
80
lib/blockstore/memstore.go
Normal file
80
lib/blockstore/memstore.go
Normal file
@ -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
|
||||||
|
}
|
68
lib/blockstore/syncstore.go
Normal file
68
lib/blockstore/syncstore.go
Normal file
@ -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
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user