Merge remote-tracking branch 'origin/master' into feat/mpool-gateway-api

This commit is contained in:
Łukasz Magiera 2020-10-02 23:09:55 +02:00
commit 3bebdb3882
265 changed files with 14234 additions and 6829 deletions

1
.github/CODEOWNERS vendored
View File

@ -13,3 +13,4 @@
### Conformance testing. ### Conformance testing.
conformance/ @raulk conformance/ @raulk
extern/test-vectors @raulk extern/test-vectors @raulk
cmd/tvx @raulk

View File

@ -1,5 +1,163 @@
# Lotus changelog # Lotus changelog
# 0.8.1 / 2020-09-30
This optional release of Lotus introduces a new version of markets which switches to CBOR-map encodings, and allows datastore migrations. The release also introduces several improvements to the mining process, a few performance optimizations, and a battery of UX additions and enhancements.
## Changes
#### Dependencies
- Markets 0.7.0 with updated data stores (https://github.com/filecoin-project/lotus/pull/4089)
- Update ffi to code with blst fixes (https://github.com/filecoin-project/lotus/pull/3998)
#### Core Lotus
- Fix GetPower with no miner address (https://github.com/filecoin-project/lotus/pull/4049)
- Refactor: Move nonce generation out of mpool (https://github.com/filecoin-project/lotus/pull/3970)
#### Performance
- Implement caching syscalls for import-bench (https://github.com/filecoin-project/lotus/pull/3888)
- Fetch tipset blocks in parallel (https://github.com/filecoin-project/lotus/pull/4074)
- Optimize Tipset equals() (https://github.com/filecoin-project/lotus/pull/4056)
- Make state transition in validation async (https://github.com/filecoin-project/lotus/pull/3868)
#### Mining
- Add trace window post (https://github.com/filecoin-project/lotus/pull/4020)
- Use abstract types for Dont recompute post on revert (https://github.com/filecoin-project/lotus/pull/4022)
- Fix injectNulls logic in test miner (https://github.com/filecoin-project/lotus/pull/4058)
- Fix potential panic in FinalizeSector (https://github.com/filecoin-project/lotus/pull/4092)
- Don't recompute post on revert (https://github.com/filecoin-project/lotus/pull/3924)
- Fix some failed precommit handling (https://github.com/filecoin-project/lotus/pull/3445)
- Add --no-swap flag for worker (https://github.com/filecoin-project/lotus/pull/4107)
- Allow some single-thread tasks to run in parallel with PC2/C2 (https://github.com/filecoin-project/lotus/pull/4116)
#### UX
- Add an envvar to set address network version (https://github.com/filecoin-project/lotus/pull/4028)
- Add logging to chain export (https://github.com/filecoin-project/lotus/pull/4030)
- Add JSON output to state compute (https://github.com/filecoin-project/lotus/pull/4038)
- Wallet list CLI: Print balances/nonces (https://github.com/filecoin-project/lotus/pull/4088)
- Added an option to show or not show sector info for `lotus-miner info` (https://github.com/filecoin-project/lotus/pull/4003)
- Add a command to import an ipld object into the chainstore (https://github.com/filecoin-project/lotus/pull/3434)
- Improve the lotus-shed dealtracker (https://github.com/filecoin-project/lotus/pull/4051)
- Docs review and re-organization (https://github.com/filecoin-project/lotus/pull/3431)
- Fix wallet list (https://github.com/filecoin-project/lotus/pull/4104)
- Add an endpoint to validate whether a string is a well-formed address (https://github.com/filecoin-project/lotus/pull/4106)
- Add an option to set config path (https://github.com/filecoin-project/lotus/pull/4103)
- Add printf in TestWindowPost (https://github.com/filecoin-project/lotus/pull/4043)
- Improve miner sectors list UX (https://github.com/filecoin-project/lotus/pull/4108)
#### Tooling
- Move policy change to seal bench (https://github.com/filecoin-project/lotus/pull/4032)
- Add back network power to stats (https://github.com/filecoin-project/lotus/pull/4050)
- Conformance: Record and feed circulating supply (https://github.com/filecoin-project/lotus/pull/4078)
- Snapshot import progress bar, add HTTP support (https://github.com/filecoin-project/lotus/pull/4070)
- Add lotus shed util to validate a tipset (https://github.com/filecoin-project/lotus/pull/4065)
- tvx: a test vector extraction and execution tool (https://github.com/filecoin-project/lotus/pull/4064)
#### Bootstrap
- Add new bootstrappers (https://github.com/filecoin-project/lotus/pull/4007)
- Add Glif node to bootstrap peers (https://github.com/filecoin-project/lotus/pull/4004)
- Add one more node located in China (https://github.com/filecoin-project/lotus/pull/4041)
- Add ipfsmain bootstrapper (https://github.com/filecoin-project/lotus/pull/4067)
# 0.8.0 / 2020-09-26
This consensus-breaking release of Lotus introduces an upgrade to the network. The changes that break consensus are:
- Upgrading to specs-actors v0.9.11, which reduces WindowPoSt faults per [FIP 0002](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0002.md) to reduce cost for honest miners with occasional faults (see https://github.com/filecoin-project/specs-actors/pull/1181)
- Revisions to some cryptoeconomics and network params
This release also updates go-fil-markets to fix an incompatibility issue between v0.7.2 and earlier versions.
## Changes
#### Dependencies
- Update spec actors to 0.9.11 (https://github.com/filecoin-project/lotus/pull/4039)
- Update markets to 0.6.3 (https://github.com/filecoin-project/lotus/pull/4013)
#### Core Lotus
- Network upgrade (https://github.com/filecoin-project/lotus/pull/4039)
- Fix AddSupportedProofTypes (https://github.com/filecoin-project/lotus/pull/4033)
- Return an error when we fail to find a sector when checking sector expiration (https://github.com/filecoin-project/lotus/pull/4026)
- Batch blockstore copies after block validation (https://github.com/filecoin-project/lotus/pull/3980)
- Remove a misleading miner actor abstraction (https://github.com/filecoin-project/lotus/pull/3977)
- Fix out-of-bounds when loading all sector infos (https://github.com/filecoin-project/lotus/pull/3976)
- Fix break condition in the miner (https://github.com/filecoin-project/lotus/pull/3953)
#### UX
- Correct helptext around miners setting ask (https://github.com/filecoin-project/lotus/pull/4009)
- Make sync wait nicer (https://github.com/filecoin-project/lotus/pull/3991)
#### Tooling and validation
- Small adjustments following network upgradability changes (https://github.com/filecoin-project/lotus/pull/3996)
- Add some more big pictures stats to stateroot stat (https://github.com/filecoin-project/lotus/pull/3995)
- Add some actors policy setters for testing (https://github.com/filecoin-project/lotus/pull/3975)
## Contributors
The following contributors had 5 or more commits go into this release.
We are grateful for every contribution!
| Contributor | Commits | Lines ± |
|--------------------|---------|---------------|
| arajasek | 66 | +3140/-1261 |
| Stebalien | 64 | +3797/-3434 |
| magik6k | 48 | +1892/-976 |
| raulk | 40 | +2412/-1549 |
| vyzo | 22 | +287/-196 |
| alanshaw | 15 | +761/-146 |
| whyrusleeping | 15 | +736/-52 |
| hannahhoward | 14 | +1237/837- |
| anton | 6 | +32/-8 |
| travisperson | 5 | +502/-6 |
| Frank | 5 | +78/-39 |
| Jennifer | 5 | +148/-41 |
# 0.7.2 / 2020-09-23
This optional release of Lotus introduces a major refactor around how a Lotus node interacts with code from the specs-actors repo. We now use interfaces to read the state of actors, which is required to be able to reason about different versions of actors code at the same time.
Additionally, this release introduces various improvements to the sync process, as well as changes to better the overall UX experience.
## Changes
#### Core Lotus
- Network upgrade support (https://github.com/filecoin-project/lotus/pull/3781)
- Upgrade markets to `v0.6.2` (https://github.com/filecoin-project/lotus/pull/3974)
- Validate chain sync response indices when fetching messages (https://github.com/filecoin-project/lotus/pull/3939)
- Add height diff to sync wait (https://github.com/filecoin-project/lotus/pull/3926)
- Replace Requires with Wants (https://github.com/filecoin-project/lotus/pull/3898)
- Update state diffing for market actor (https://github.com/filecoin-project/lotus/pull/3889)
- Parallel fetch for sync (https://github.com/filecoin-project/lotus/pull/3887)
- Fix SectorState (https://github.com/filecoin-project/lotus/pull/3881)
#### User Experience
- Add basic deal stats api server for spacerace slingshot (https://github.com/filecoin-project/lotus/pull/3963)
- When doing `sectors update-state`, show a list of existing states if user inputs an invalid one (https://github.com/filecoin-project/lotus/pull/3944)
- Fix `lotus-miner storage find` error (https://github.com/filecoin-project/lotus/pull/3927)
- Log shutdown method for lotus daemon and miner (https://github.com/filecoin-project/lotus/pull/3925)
- Update build and setup instruction link (https://github.com/filecoin-project/lotus/pull/3919)
- Add an option to hide removed sectors from `sectors list` output (https://github.com/filecoin-project/lotus/pull/3903)
#### Testing and validation
- Add init.State#Remove() for testing (https://github.com/filecoin-project/lotus/pull/3971)
- lotus-shed: add consensus check command (https://github.com/filecoin-project/lotus/pull/3933)
- Add keyinfo verify and jwt token command to lotus-shed (https://github.com/filecoin-project/lotus/pull/3914)
- Fix conformance gen (https://github.com/filecoin-project/lotus/pull/3892)
# 0.7.1 / 2020-09-17 # 0.7.1 / 2020-09-17
This optional release of Lotus introduces some critical fixes to the window PoSt process. It also upgrades some core dependencies, and introduces many improvements to the mining process, deal-making cycle, and overall User Experience. This optional release of Lotus introduces some critical fixes to the window PoSt process. It also upgrades some core dependencies, and introduces many improvements to the mining process, deal-making cycle, and overall User Experience.

View File

@ -1,5 +1,5 @@
<p align="center"> <p align="center">
<a href="https://lotu.sh/" title="Lotus Docs"> <a href="https://docs.filecoin.io/" title="Filecoin Docs">
<img src="documentation/images/lotus_logo_h.png" alt="Project Lotus Logo" width="244" /> <img src="documentation/images/lotus_logo_h.png" alt="Project Lotus Logo" width="244" />
</a> </a>
</p> </p>
@ -18,7 +18,7 @@ Lotus is an implementation of the Filecoin Distributed Storage Network. For more
## Building & Documentation ## Building & Documentation
For instructions on how to build lotus from source, please visit [https://lotu.sh](https://lotu.sh) or read the source [here](https://github.com/filecoin-project/lotus/tree/master/documentation). For instructions on how to build, install and setup lotus, please visit [https://docs.filecoin.io/get-started/lotus](https://docs.filecoin.io/get-started/lotus/).
## Reporting a Vulnerability ## Reporting a Vulnerability

View File

@ -5,9 +5,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/specs-actors/actors/runtime/proof"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
@ -20,12 +18,13 @@ import (
"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/go-state-types/crypto"
"github.com/filecoin-project/specs-actors/actors/builtin/market" "github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power" "github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
marketevents "github.com/filecoin-project/lotus/markets/loggers" marketevents "github.com/filecoin-project/lotus/markets/loggers"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
@ -77,6 +76,9 @@ type FullNode interface {
// blockstore and returns raw bytes. // blockstore and returns raw bytes.
ChainReadObj(context.Context, cid.Cid) ([]byte, error) ChainReadObj(context.Context, cid.Cid) ([]byte, error)
// ChainDeleteObj deletes node referenced by the given CID
ChainDeleteObj(context.Context, cid.Cid) error
// ChainHasObj checks if a given CID exists in the chain blockstore. // ChainHasObj checks if a given CID exists in the chain blockstore.
ChainHasObj(context.Context, cid.Cid) (bool, error) ChainHasObj(context.Context, cid.Cid) (bool, error)
@ -174,6 +176,9 @@ type FullNode interface {
// the reason. // the reason.
SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error)
// SyncValidateTipset indicates whether the provided tipset is valid or not
SyncValidateTipset(ctx context.Context, tsk types.TipSetKey) (bool, error)
// MethodGroup: Mpool // MethodGroup: Mpool
// The Mpool methods are for interacting with the message pool. The message pool // The Mpool methods are for interacting with the message pool. The message pool
// manages all incoming and outgoing 'messages' going over the network. // manages all incoming and outgoing 'messages' going over the network.
@ -234,7 +239,7 @@ type FullNode interface {
WalletSignMessage(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) WalletSignMessage(context.Context, address.Address, *types.Message) (*types.SignedMessage, error)
// WalletVerify takes an address, a signature, and some bytes, and indicates whether the signature is valid. // WalletVerify takes an address, a signature, and some bytes, and indicates whether the signature is valid.
// The address does not have to be in the wallet. // The address does not have to be in the wallet.
WalletVerify(context.Context, address.Address, []byte, *crypto.Signature) bool WalletVerify(context.Context, address.Address, []byte, *crypto.Signature) (bool, error)
// WalletDefaultAddress returns the address marked as default in the wallet. // WalletDefaultAddress returns the address marked as default in the wallet.
WalletDefaultAddress(context.Context) (address.Address, error) WalletDefaultAddress(context.Context) (address.Address, error)
// WalletSetDefault marks the given address as as the default one. // WalletSetDefault marks the given address as as the default one.
@ -245,6 +250,8 @@ type FullNode interface {
WalletImport(context.Context, *types.KeyInfo) (address.Address, error) WalletImport(context.Context, *types.KeyInfo) (address.Address, error)
// WalletDelete deletes an address from the wallet. // WalletDelete deletes an address from the wallet.
WalletDelete(context.Context, address.Address) error WalletDelete(context.Context, address.Address) error
// WalletValidateAddress validates whether a given string can be decoded as a well-formed address
WalletValidateAddress(context.Context, string) (address.Address, error)
// Other // Other
@ -276,7 +283,7 @@ type FullNode interface {
// of status updates. // of status updates.
ClientRetrieveWithEvents(ctx context.Context, order RetrievalOrder, ref *FileRef) (<-chan marketevents.RetrievalEvent, error) ClientRetrieveWithEvents(ctx context.Context, order RetrievalOrder, ref *FileRef) (<-chan marketevents.RetrievalEvent, error)
// ClientQueryAsk returns a signed StorageAsk from the specified miner. // ClientQueryAsk returns a signed StorageAsk from the specified miner.
ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error)
// ClientCalcCommP calculates the CommP for a specified file // ClientCalcCommP calculates the CommP for a specified file
ClientCalcCommP(ctx context.Context, inpath string) (*CommPRet, error) ClientCalcCommP(ctx context.Context, inpath string) (*CommPRet, error)
// ClientGenCar generates a CAR file for the specified file. // ClientGenCar generates a CAR file for the specified file.
@ -317,22 +324,20 @@ type FullNode interface {
// 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)
// StateMinerSectors returns info about the given miner's sectors. If the filter bitfield is nil, all sectors are included. // StateMinerSectors returns info about the given miner's sectors. If the filter bitfield is nil, all sectors are included.
// If the filterOut boolean is set to true, any sectors in the filter are excluded. StateMinerSectors(context.Context, address.Address, *bitfield.BitField, types.TipSetKey) ([]*miner.SectorOnChainInfo, error)
// If false, only those sectors in the filter are included.
StateMinerSectors(context.Context, address.Address, *bitfield.BitField, bool, types.TipSetKey) ([]*ChainSectorInfo, error)
// StateMinerActiveSectors returns info about sectors that a given miner is actively proving. // StateMinerActiveSectors returns info about sectors that a given miner is actively proving.
StateMinerActiveSectors(context.Context, address.Address, types.TipSetKey) ([]*ChainSectorInfo, error) StateMinerActiveSectors(context.Context, address.Address, types.TipSetKey) ([]*miner.SectorOnChainInfo, error)
// StateMinerProvingDeadline calculates the deadline at some epoch for a proving period // StateMinerProvingDeadline calculates the deadline at some epoch for a proving period
// and returns the deadline-related calculations. // and returns the deadline-related calculations.
StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error)
// StateMinerPower returns the power of the indicated miner // StateMinerPower returns the power of the indicated miner
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error) StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error)
// StateMinerInfo returns info about the indicated miner // StateMinerInfo returns info about the indicated miner
StateMinerInfo(context.Context, address.Address, types.TipSetKey) (MinerInfo, error) StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error)
// StateMinerDeadlines returns all the proving deadlines for the given miner // StateMinerDeadlines returns all the proving deadlines for the given miner
StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]*miner.Deadline, error) StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]Deadline, error)
// StateMinerPartitions loads miner partitions for the specified miner/deadline // StateMinerPartitions returns all partitions in the specified deadline
StateMinerPartitions(context.Context, address.Address, uint64, types.TipSetKey) ([]*miner.Partition, error) StateMinerPartitions(ctx context.Context, m address.Address, dlIdx uint64, tsk types.TipSetKey) ([]Partition, error)
// StateMinerFaults returns a bitfield indicating the faulty sectors of the given miner // StateMinerFaults returns a bitfield indicating the faulty sectors of the given miner
StateMinerFaults(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) StateMinerFaults(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error)
// StateAllMinerFaults returns all non-expired Faults that occur within lookback epochs of the given tipset // StateAllMinerFaults returns all non-expired Faults that occur within lookback epochs of the given tipset
@ -352,9 +357,9 @@ type FullNode interface {
// expiration epoch // expiration epoch
StateSectorGetInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error) StateSectorGetInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error)
// StateSectorExpiration returns epoch at which given sector will expire // StateSectorExpiration returns epoch at which given sector will expire
StateSectorExpiration(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*SectorExpiration, error) StateSectorExpiration(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorExpiration, error)
// StateSectorPartition finds deadline/partition with the specified sector // StateSectorPartition finds deadline/partition with the specified sector
StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*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 searches for a message in the chain, and returns details of the messages gas costs, including the penalty and miner tip
@ -391,13 +396,15 @@ type FullNode interface {
// 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
// address. // address.
StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*verifreg.DataCap, error) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error)
// StateDealProviderCollateralBounds returns the min and max collateral a storage provider // StateDealProviderCollateralBounds returns the min and max collateral a storage provider
// 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 circulating supply of Filecoin at the given tipset
StateCirculatingSupply(context.Context, types.TipSetKey) (CirculatingSupply, error) StateCirculatingSupply(context.Context, types.TipSetKey) (CirculatingSupply, error)
// StateNetworkVersion returns the network version at the given tipset
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
// MethodGroup: Msig // MethodGroup: Msig
// The Msig methods are used to interact with multisig wallets on the // The Msig methods are used to interact with multisig wallets on the
@ -479,21 +486,12 @@ type FileRef struct {
} }
type MinerSectors struct { type MinerSectors struct {
Sectors uint64 // Live sectors that should be proven.
Active uint64 Live uint64
} // Sectors actively contributing to power.
Active uint64
type SectorExpiration struct { // Sectors with failed proofs.
OnTime abi.ChainEpoch Faulty uint64
// non-zero if sector is faulty, epoch at which it will be permanently
// removed if it doesn't recover
Early abi.ChainEpoch
}
type SectorLocation struct {
Deadline uint64
Partition uint64
} }
type ImportRes struct { type ImportRes struct {
@ -559,11 +557,6 @@ type Message struct {
Message *types.Message Message *types.Message
} }
type ChainSectorInfo struct {
Info miner.SectorOnChainInfo
ID abi.SectorNumber
}
type ActorState struct { type ActorState struct {
Balance types.BigInt Balance types.BigInt
State interface{} State interface{}
@ -635,8 +628,9 @@ type VoucherCreateResult struct {
} }
type MinerPower struct { type MinerPower struct {
MinerPower power.Claim MinerPower power.Claim
TotalPower power.Claim TotalPower power.Claim
HasMinPower bool
} }
type QueryOffer struct { type QueryOffer struct {
@ -739,6 +733,8 @@ type ActiveSync struct {
type SyncState struct { type SyncState struct {
ActiveSyncs []ActiveSync ActiveSyncs []ActiveSync
VMApplied uint64
} }
type SyncStateStage int type SyncStateStage int
@ -805,7 +801,7 @@ type CirculatingSupply struct {
type MiningBaseInfo struct { type MiningBaseInfo struct {
MinerPower types.BigInt MinerPower types.BigInt
NetworkPower types.BigInt NetworkPower types.BigInt
Sectors []proof.SectorInfo Sectors []builtin.SectorInfo
WorkerKey address.Address WorkerKey address.Address
SectorSize abi.SectorSize SectorSize abi.SectorSize
PrevBeaconEntry types.BeaconEntry PrevBeaconEntry types.BeaconEntry
@ -822,7 +818,7 @@ type BlockTemplate struct {
Messages []*types.SignedMessage Messages []*types.SignedMessage
Epoch abi.ChainEpoch Epoch abi.ChainEpoch
Timestamp uint64 Timestamp uint64
WinningPoStProof []proof.PoStProof WinningPoStProof []builtin.PoStProof
} }
type DataSize struct { type DataSize struct {
@ -846,6 +842,18 @@ const (
MsigCancel MsigCancel
) )
type Deadline struct {
PostSubmissions bitfield.BitField
}
type Partition struct {
AllSectors bitfield.BitField
FaultySectors bitfield.BitField
RecoveringSectors bitfield.BitField
LiveSectors bitfield.BitField
ActiveSectors bitfield.BitField
}
type Fault struct { type Fault struct {
Miner address.Address Miner address.Address
Epoch abi.ChainEpoch Epoch abi.ChainEpoch

View File

@ -71,7 +71,7 @@ type StorageMiner interface {
stores.SectorIndex stores.SectorIndex
MarketImportDealData(ctx context.Context, propcid cid.Cid, path string) error MarketImportDealData(ctx context.Context, propcid cid.Cid, path string) error
MarketListDeals(ctx context.Context) ([]storagemarket.StorageDeal, error) MarketListDeals(ctx context.Context) ([]MarketDeal, error)
MarketListRetrievalDeals(ctx context.Context) ([]retrievalmarket.ProviderDealState, error) MarketListRetrievalDeals(ctx context.Context) ([]retrievalmarket.ProviderDealState, error)
MarketGetDealUpdates(ctx context.Context) (<-chan storagemarket.MinerDeal, error) MarketGetDealUpdates(ctx context.Context) (<-chan storagemarket.MinerDeal, error)
MarketListIncompleteDeals(ctx context.Context) ([]storagemarket.MinerDeal, error) MarketListIncompleteDeals(ctx context.Context) ([]storagemarket.MinerDeal, error)
@ -83,7 +83,7 @@ type StorageMiner interface {
MarketDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error) MarketDataTransferUpdates(ctx context.Context) (<-chan DataTransferChannel, error)
DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error
DealsList(ctx context.Context) ([]storagemarket.StorageDeal, error) DealsList(ctx context.Context) ([]MarketDeal, error)
DealsConsiderOnlineStorageDeals(context.Context) (bool, error) DealsConsiderOnlineStorageDeals(context.Context) (bool, error)
DealsSetConsiderOnlineStorageDeals(context.Context, bool) error DealsSetConsiderOnlineStorageDeals(context.Context, bool) error
DealsConsiderOnlineRetrievalDeals(context.Context) (bool, error) DealsConsiderOnlineRetrievalDeals(context.Context) (bool, error)

View File

@ -1,12 +1,16 @@
package api package api
import ( import (
"encoding/json"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"reflect"
"runtime" "runtime"
"strings" "strings"
"testing" "testing"
"github.com/stretchr/testify/require"
) )
func goCmd() string { func goCmd() string {
@ -32,3 +36,68 @@ func TestDoesntDependOnFFI(t *testing.T) {
} }
} }
} }
func TestReturnTypes(t *testing.T) {
errType := reflect.TypeOf(new(error)).Elem()
bareIface := reflect.TypeOf(new(interface{})).Elem()
jmarsh := reflect.TypeOf(new(json.Marshaler)).Elem()
tst := func(api interface{}) func(t *testing.T) {
return func(t *testing.T) {
ra := reflect.TypeOf(api).Elem()
for i := 0; i < ra.NumMethod(); i++ {
m := ra.Method(i)
switch m.Type.NumOut() {
case 1: // if 1 return value, it must be an error
require.Equal(t, errType, m.Type.Out(0), m.Name)
case 2: // if 2 return values, first cant be an interface/function, second must be an error
seen := map[reflect.Type]struct{}{}
todo := []reflect.Type{m.Type.Out(0)}
for len(todo) > 0 {
typ := todo[len(todo)-1]
todo = todo[:len(todo)-1]
if _, ok := seen[typ]; ok {
continue
}
seen[typ] = struct{}{}
if typ.Kind() == reflect.Interface && typ != bareIface && !typ.Implements(jmarsh) {
t.Error("methods can't return interfaces", m.Name)
}
switch typ.Kind() {
case reflect.Ptr:
fallthrough
case reflect.Array:
fallthrough
case reflect.Slice:
fallthrough
case reflect.Chan:
todo = append(todo, typ.Elem())
case reflect.Map:
todo = append(todo, typ.Elem())
todo = append(todo, typ.Key())
case reflect.Struct:
for i := 0; i < typ.NumField(); i++ {
todo = append(todo, typ.Field(i).Type)
}
}
}
require.NotEqual(t, reflect.Func.String(), m.Type.Out(0).Kind().String(), m.Name)
require.Equal(t, errType, m.Type.Out(1), m.Name)
default:
t.Error("methods can only have 1 or 2 return values", m.Name)
}
}
}
}
t.Run("common", tst(new(Common)))
t.Run("full", tst(new(FullNode)))
t.Run("miner", tst(new(StorageMiner)))
t.Run("worker", tst(new(WorkerAPI)))
}

View File

@ -5,7 +5,7 @@ import (
"io" "io"
"time" "time"
"github.com/filecoin-project/go-state-types/dline" stnetwork "github.com/filecoin-project/go-state-types/network"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
metrics "github.com/libp2p/go-libp2p-core/metrics" metrics "github.com/libp2p/go-libp2p-core/metrics"
@ -23,18 +23,18 @@ import (
"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/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil" "github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
"github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks"
"github.com/filecoin-project/lotus/extern/sector-storage/stores" "github.com/filecoin-project/lotus/extern/sector-storage/stores"
"github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/lotus/extern/sector-storage/storiface"
marketevents "github.com/filecoin-project/lotus/markets/loggers" marketevents "github.com/filecoin-project/lotus/markets/loggers"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-storage/storage" "github.com/filecoin-project/specs-storage/storage"
"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/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
) )
@ -87,6 +87,7 @@ type FullNodeStruct struct {
ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"` ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"`
ChainGetTipSetByHeight func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) `perm:"read"` ChainGetTipSetByHeight func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"` ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
ChainDeleteObj func(context.Context, cid.Cid) error `perm:"admin"`
ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"` ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"`
ChainStatObj func(context.Context, cid.Cid, cid.Cid) (api.ObjStat, error) `perm:"read"` ChainStatObj func(context.Context, cid.Cid, cid.Cid) (api.ObjStat, error) `perm:"read"`
ChainSetHead func(context.Context, types.TipSetKey) error `perm:"admin"` ChainSetHead func(context.Context, types.TipSetKey) error `perm:"admin"`
@ -111,6 +112,7 @@ type FullNodeStruct struct {
SyncMarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"` SyncMarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"`
SyncUnmarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"` SyncUnmarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"`
SyncCheckBad func(ctx context.Context, bcid cid.Cid) (string, error) `perm:"read"` SyncCheckBad func(ctx context.Context, bcid cid.Cid) (string, error) `perm:"read"`
SyncValidateTipset func(ctx context.Context, tsk types.TipSetKey) (bool, error) `perm:"read"`
MpoolGetConfig func(context.Context) (*types.MpoolConfig, error) `perm:"read"` MpoolGetConfig func(context.Context) (*types.MpoolConfig, error) `perm:"read"`
MpoolSetConfig func(context.Context, *types.MpoolConfig) error `perm:"write"` MpoolSetConfig func(context.Context, *types.MpoolConfig) error `perm:"write"`
@ -130,18 +132,19 @@ 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, crypto.SigType) (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"`
WalletSign func(context.Context, address.Address, []byte) (*crypto.Signature, error) `perm:"sign"` WalletSign func(context.Context, address.Address, []byte) (*crypto.Signature, error) `perm:"sign"`
WalletSignMessage func(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) `perm:"sign"` WalletSignMessage func(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
WalletVerify func(context.Context, address.Address, []byte, *crypto.Signature) bool `perm:"read"` WalletVerify func(context.Context, address.Address, []byte, *crypto.Signature) (bool, error) `perm:"read"`
WalletDefaultAddress func(context.Context) (address.Address, error) `perm:"write"` WalletDefaultAddress func(context.Context) (address.Address, error) `perm:"write"`
WalletSetDefault func(context.Context, address.Address) error `perm:"admin"` WalletSetDefault func(context.Context, address.Address) error `perm:"admin"`
WalletExport func(context.Context, address.Address) (*types.KeyInfo, error) `perm:"admin"` WalletExport func(context.Context, address.Address) (*types.KeyInfo, error) `perm:"admin"`
WalletImport func(context.Context, *types.KeyInfo) (address.Address, error) `perm:"admin"` WalletImport func(context.Context, *types.KeyInfo) (address.Address, error) `perm:"admin"`
WalletDelete func(context.Context, address.Address) error `perm:"write"` WalletDelete func(context.Context, address.Address) error `perm:"write"`
WalletValidateAddress func(context.Context, string) (address.Address, error) `perm:"read"`
ClientImport func(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) `perm:"admin"` ClientImport func(ctx context.Context, ref api.FileRef) (*api.ImportRes, error) `perm:"admin"`
ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"` ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"`
@ -155,7 +158,7 @@ type FullNodeStruct struct {
ClientGetDealUpdates func(ctx context.Context) (<-chan api.DealInfo, error) `perm:"read"` ClientGetDealUpdates func(ctx context.Context) (<-chan api.DealInfo, error) `perm:"read"`
ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error `perm:"admin"` ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error `perm:"admin"`
ClientRetrieveWithEvents func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) (<-chan marketevents.RetrievalEvent, error) `perm:"admin"` ClientRetrieveWithEvents func(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) (<-chan marketevents.RetrievalEvent, error) `perm:"admin"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) `perm:"read"` ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error) `perm:"read"`
ClientCalcCommP func(ctx context.Context, inpath string) (*api.CommPRet, error) `perm:"read"` ClientCalcCommP func(ctx context.Context, inpath string) (*api.CommPRet, error) `perm:"read"`
ClientGenCar func(ctx context.Context, ref api.FileRef, outpath string) error `perm:"write"` ClientGenCar func(ctx context.Context, ref api.FileRef, outpath string) error `perm:"write"`
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"`
@ -164,13 +167,13 @@ type FullNodeStruct struct {
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"`
StateMinerSectors func(context.Context, address.Address, *bitfield.BitField, bool, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"` StateMinerSectors func(context.Context, address.Address, *bitfield.BitField, types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"`
StateMinerActiveSectors func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"` StateMinerActiveSectors func(context.Context, address.Address, types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"`
StateMinerProvingDeadline func(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) `perm:"read"` StateMinerProvingDeadline func(context.Context, address.Address, types.TipSetKey) (*dline.Info, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) `perm:"read"` StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) `perm:"read"`
StateMinerInfo func(context.Context, address.Address, types.TipSetKey) (api.MinerInfo, error) `perm:"read"` StateMinerInfo func(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) `perm:"read"`
StateMinerDeadlines func(context.Context, address.Address, types.TipSetKey) ([]*miner.Deadline, error) `perm:"read"` StateMinerDeadlines func(context.Context, address.Address, types.TipSetKey) ([]api.Deadline, error) `perm:"read"`
StateMinerPartitions func(context.Context, address.Address, uint64, types.TipSetKey) ([]*miner.Partition, error) `perm:"read"` StateMinerPartitions func(ctx context.Context, m address.Address, dlIdx uint64, tsk types.TipSetKey) ([]api.Partition, error) `perm:"read"`
StateMinerFaults func(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) `perm:"read"` StateMinerFaults func(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) `perm:"read"`
StateAllMinerFaults func(context.Context, abi.ChainEpoch, types.TipSetKey) ([]*api.Fault, error) `perm:"read"` StateAllMinerFaults func(context.Context, abi.ChainEpoch, types.TipSetKey) ([]*api.Fault, error) `perm:"read"`
StateMinerRecoveries func(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) `perm:"read"` StateMinerRecoveries func(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error) `perm:"read"`
@ -179,8 +182,8 @@ type FullNodeStruct struct {
StateMinerAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"` StateMinerAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
StateSectorPreCommitInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"` StateSectorPreCommitInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"`
StateSectorGetInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"` StateSectorGetInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"`
StateSectorExpiration func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*api.SectorExpiration, error) `perm:"read"` StateSectorExpiration func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorExpiration, error) `perm:"read"`
StateSectorPartition func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*api.SectorLocation, error) `perm:"read"` StateSectorPartition func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorLocation, error) `perm:"read"`
StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) `perm:"read"` StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) `perm:"read"`
StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"` StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"`
StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"` StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"`
@ -201,9 +204,10 @@ type FullNodeStruct struct {
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 *types.Message, 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"`
StateVerifiedClientStatus func(context.Context, address.Address, types.TipSetKey) (*verifreg.DataCap, error) `perm:"read"` StateVerifiedClientStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, 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) (api.CirculatingSupply, error) `perm:"read"`
StateNetworkVersion func(context.Context, types.TipSetKey) (stnetwork.Version, error) `perm:"read"`
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"` MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
MsigGetVested func(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) `perm:"read"` MsigGetVested func(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) `perm:"read"`
@ -254,7 +258,7 @@ type StorageMinerStruct struct {
MiningBase func(context.Context) (*types.TipSet, error) `perm:"read"` MiningBase func(context.Context) (*types.TipSet, error) `perm:"read"`
MarketImportDealData func(context.Context, cid.Cid, string) error `perm:"write"` MarketImportDealData func(context.Context, cid.Cid, string) error `perm:"write"`
MarketListDeals func(ctx context.Context) ([]storagemarket.StorageDeal, error) `perm:"read"` MarketListDeals func(ctx context.Context) ([]api.MarketDeal, error) `perm:"read"`
MarketListRetrievalDeals func(ctx context.Context) ([]retrievalmarket.ProviderDealState, error) `perm:"read"` MarketListRetrievalDeals func(ctx context.Context) ([]retrievalmarket.ProviderDealState, error) `perm:"read"`
MarketGetDealUpdates func(ctx context.Context) (<-chan storagemarket.MinerDeal, error) `perm:"read"` MarketGetDealUpdates func(ctx context.Context) (<-chan storagemarket.MinerDeal, error) `perm:"read"`
MarketListIncompleteDeals func(ctx context.Context) ([]storagemarket.MinerDeal, error) `perm:"read"` MarketListIncompleteDeals func(ctx context.Context) ([]storagemarket.MinerDeal, error) `perm:"read"`
@ -299,7 +303,7 @@ type StorageMinerStruct struct {
StorageTryLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) (bool, error) `perm:"admin"` StorageTryLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) (bool, error) `perm:"admin"`
DealsImportData func(ctx context.Context, dealPropCid cid.Cid, file string) error `perm:"write"` DealsImportData func(ctx context.Context, dealPropCid cid.Cid, file string) error `perm:"write"`
DealsList func(ctx context.Context) ([]storagemarket.StorageDeal, error) `perm:"read"` DealsList func(ctx context.Context) ([]api.MarketDeal, error) `perm:"read"`
DealsConsiderOnlineStorageDeals func(context.Context) (bool, error) `perm:"read"` DealsConsiderOnlineStorageDeals func(context.Context) (bool, error) `perm:"read"`
DealsSetConsiderOnlineStorageDeals func(context.Context, bool) error `perm:"admin"` DealsSetConsiderOnlineStorageDeals func(context.Context, bool) error `perm:"admin"`
DealsConsiderOnlineRetrievalDeals func(context.Context) (bool, error) `perm:"read"` DealsConsiderOnlineRetrievalDeals func(context.Context) (bool, error) `perm:"read"`
@ -484,7 +488,7 @@ func (c *FullNodeStruct) ClientRetrieveWithEvents(ctx context.Context, order api
return c.Internal.ClientRetrieveWithEvents(ctx, order, ref) return c.Internal.ClientRetrieveWithEvents(ctx, order, ref)
} }
func (c *FullNodeStruct) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) { func (c *FullNodeStruct) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.StorageAsk, error) {
return c.Internal.ClientQueryAsk(ctx, p, miner) return c.Internal.ClientQueryAsk(ctx, p, miner)
} }
func (c *FullNodeStruct) ClientCalcCommP(ctx context.Context, inpath string) (*api.CommPRet, error) { func (c *FullNodeStruct) ClientCalcCommP(ctx context.Context, inpath string) (*api.CommPRet, error) {
@ -611,7 +615,7 @@ func (c *FullNodeStruct) WalletSignMessage(ctx context.Context, k address.Addres
return c.Internal.WalletSignMessage(ctx, k, msg) return c.Internal.WalletSignMessage(ctx, k, msg)
} }
func (c *FullNodeStruct) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) bool { func (c *FullNodeStruct) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *crypto.Signature) (bool, error) {
return c.Internal.WalletVerify(ctx, k, msg, sig) return c.Internal.WalletVerify(ctx, k, msg, sig)
} }
@ -635,6 +639,10 @@ func (c *FullNodeStruct) WalletDelete(ctx context.Context, addr address.Address)
return c.Internal.WalletDelete(ctx, addr) return c.Internal.WalletDelete(ctx, addr)
} }
func (c *FullNodeStruct) WalletValidateAddress(ctx context.Context, str string) (address.Address, error) {
return c.Internal.WalletValidateAddress(ctx, str)
}
func (c *FullNodeStruct) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) { func (c *FullNodeStruct) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) {
return c.Internal.MpoolGetNonce(ctx, addr) return c.Internal.MpoolGetNonce(ctx, addr)
} }
@ -667,6 +675,10 @@ func (c *FullNodeStruct) ChainReadObj(ctx context.Context, obj cid.Cid) ([]byte,
return c.Internal.ChainReadObj(ctx, obj) return c.Internal.ChainReadObj(ctx, obj)
} }
func (c *FullNodeStruct) ChainDeleteObj(ctx context.Context, obj cid.Cid) error {
return c.Internal.ChainDeleteObj(ctx, obj)
}
func (c *FullNodeStruct) ChainHasObj(ctx context.Context, o cid.Cid) (bool, error) { func (c *FullNodeStruct) ChainHasObj(ctx context.Context, o cid.Cid) (bool, error) {
return c.Internal.ChainHasObj(ctx, o) return c.Internal.ChainHasObj(ctx, o)
} }
@ -735,15 +747,19 @@ func (c *FullNodeStruct) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string
return c.Internal.SyncCheckBad(ctx, bcid) return c.Internal.SyncCheckBad(ctx, bcid)
} }
func (c *FullNodeStruct) SyncValidateTipset(ctx context.Context, tsk types.TipSetKey) (bool, error) {
return c.Internal.SyncValidateTipset(ctx, tsk)
}
func (c *FullNodeStruct) StateNetworkName(ctx context.Context) (dtypes.NetworkName, error) { func (c *FullNodeStruct) StateNetworkName(ctx context.Context) (dtypes.NetworkName, error) {
return c.Internal.StateNetworkName(ctx) return c.Internal.StateNetworkName(ctx)
} }
func (c *FullNodeStruct) StateMinerSectors(ctx context.Context, addr address.Address, filter *bitfield.BitField, filterOut bool, tsk types.TipSetKey) ([]*api.ChainSectorInfo, error) { func (c *FullNodeStruct) StateMinerSectors(ctx context.Context, addr address.Address, sectorNos *bitfield.BitField, tsk types.TipSetKey) ([]*miner.SectorOnChainInfo, error) {
return c.Internal.StateMinerSectors(ctx, addr, filter, filterOut, tsk) return c.Internal.StateMinerSectors(ctx, addr, sectorNos, tsk)
} }
func (c *FullNodeStruct) StateMinerActiveSectors(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.ChainSectorInfo, error) { func (c *FullNodeStruct) StateMinerActiveSectors(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*miner.SectorOnChainInfo, error) {
return c.Internal.StateMinerActiveSectors(ctx, addr, tsk) return c.Internal.StateMinerActiveSectors(ctx, addr, tsk)
} }
@ -755,15 +771,15 @@ func (c *FullNodeStruct) StateMinerPower(ctx context.Context, a address.Address,
return c.Internal.StateMinerPower(ctx, a, tsk) return c.Internal.StateMinerPower(ctx, a, tsk)
} }
func (c *FullNodeStruct) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (api.MinerInfo, error) { func (c *FullNodeStruct) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) {
return c.Internal.StateMinerInfo(ctx, actor, tsk) return c.Internal.StateMinerInfo(ctx, actor, tsk)
} }
func (c *FullNodeStruct) StateMinerDeadlines(ctx context.Context, m address.Address, tsk types.TipSetKey) ([]*miner.Deadline, error) { func (c *FullNodeStruct) StateMinerDeadlines(ctx context.Context, actor address.Address, tsk types.TipSetKey) ([]api.Deadline, error) {
return c.Internal.StateMinerDeadlines(ctx, m, tsk) return c.Internal.StateMinerDeadlines(ctx, actor, tsk)
} }
func (c *FullNodeStruct) StateMinerPartitions(ctx context.Context, m address.Address, dlIdx uint64, tsk types.TipSetKey) ([]*miner.Partition, error) { func (c *FullNodeStruct) StateMinerPartitions(ctx context.Context, m address.Address, dlIdx uint64, tsk types.TipSetKey) ([]api.Partition, error) {
return c.Internal.StateMinerPartitions(ctx, m, dlIdx, tsk) return c.Internal.StateMinerPartitions(ctx, m, dlIdx, tsk)
} }
@ -799,11 +815,11 @@ func (c *FullNodeStruct) StateSectorGetInfo(ctx context.Context, maddr address.A
return c.Internal.StateSectorGetInfo(ctx, maddr, n, tsk) return c.Internal.StateSectorGetInfo(ctx, maddr, n, tsk)
} }
func (c *FullNodeStruct) StateSectorExpiration(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*api.SectorExpiration, error) { func (c *FullNodeStruct) StateSectorExpiration(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (*miner.SectorExpiration, error) {
return c.Internal.StateSectorExpiration(ctx, maddr, n, tsk) return c.Internal.StateSectorExpiration(ctx, maddr, n, tsk)
} }
func (c *FullNodeStruct) StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*api.SectorLocation, error) { func (c *FullNodeStruct) StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*miner.SectorLocation, error) {
return c.Internal.StateSectorPartition(ctx, maddr, sectorNumber, tok) return c.Internal.StateSectorPartition(ctx, maddr, sectorNumber, tok)
} }
@ -883,7 +899,7 @@ func (c *FullNodeStruct) StateCompute(ctx context.Context, height abi.ChainEpoch
return c.Internal.StateCompute(ctx, height, msgs, tsk) return c.Internal.StateCompute(ctx, height, msgs, tsk)
} }
func (c *FullNodeStruct) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*verifreg.DataCap, error) { func (c *FullNodeStruct) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) {
return c.Internal.StateVerifiedClientStatus(ctx, addr, tsk) return c.Internal.StateVerifiedClientStatus(ctx, addr, tsk)
} }
@ -895,6 +911,10 @@ func (c *FullNodeStruct) StateCirculatingSupply(ctx context.Context, tsk types.T
return c.Internal.StateCirculatingSupply(ctx, tsk) return c.Internal.StateCirculatingSupply(ctx, tsk)
} }
func (c *FullNodeStruct) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) {
return c.Internal.StateNetworkVersion(ctx, tsk)
}
func (c *FullNodeStruct) MsigGetAvailableBalance(ctx context.Context, a address.Address, tsk types.TipSetKey) (types.BigInt, error) { func (c *FullNodeStruct) MsigGetAvailableBalance(ctx context.Context, a address.Address, tsk types.TipSetKey) (types.BigInt, error) {
return c.Internal.MsigGetAvailableBalance(ctx, a, tsk) return c.Internal.MsigGetAvailableBalance(ctx, a, tsk)
} }
@ -1143,7 +1163,7 @@ func (c *StorageMinerStruct) MarketImportDealData(ctx context.Context, propcid c
return c.Internal.MarketImportDealData(ctx, propcid, path) return c.Internal.MarketImportDealData(ctx, propcid, path)
} }
func (c *StorageMinerStruct) MarketListDeals(ctx context.Context) ([]storagemarket.StorageDeal, error) { func (c *StorageMinerStruct) MarketListDeals(ctx context.Context) ([]api.MarketDeal, error) {
return c.Internal.MarketListDeals(ctx) return c.Internal.MarketListDeals(ctx)
} }
@ -1187,7 +1207,7 @@ func (c *StorageMinerStruct) DealsImportData(ctx context.Context, dealPropCid ci
return c.Internal.DealsImportData(ctx, dealPropCid, file) return c.Internal.DealsImportData(ctx, dealPropCid, file)
} }
func (c *StorageMinerStruct) DealsList(ctx context.Context) ([]storagemarket.StorageDeal, error) { func (c *StorageMinerStruct) DealsList(ctx context.Context) ([]api.MarketDeal, error) {
return c.Internal.DealsList(ctx) return c.Internal.DealsList(ctx)
} }

View File

@ -114,6 +114,7 @@ func init() {
addExample(retrievalmarket.ClientEventDealAccepted) addExample(retrievalmarket.ClientEventDealAccepted)
addExample(retrievalmarket.DealStatusNew) addExample(retrievalmarket.DealStatusNew)
addExample(network.ReachabilityPublic) addExample(network.ReachabilityPublic)
addExample(build.NewestNetworkVersion)
addExample(&types.ExecutionTrace{ addExample(&types.ExecutionTrace{
Msg: exampleValue(reflect.TypeOf(&types.Message{}), nil).(*types.Message), Msg: exampleValue(reflect.TypeOf(&types.Message{}), nil).(*types.Message),
MsgRct: exampleValue(reflect.TypeOf(&types.MessageReceipt{}), nil).(*types.MessageReceipt), MsgRct: exampleValue(reflect.TypeOf(&types.MessageReceipt{}), nil).(*types.MessageReceipt),

View File

@ -85,6 +85,7 @@ func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
{ {
exp, err := client.StateSectorExpiration(ctx, maddr, CC, types.EmptyTSK) exp, err := client.StateSectorExpiration(ctx, maddr, CC, types.EmptyTSK)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, exp)
require.Greater(t, 50000, int(exp.OnTime)) require.Greater(t, 50000, int(exp.OnTime))
} }
{ {
@ -93,6 +94,22 @@ func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
require.Less(t, 50000, int(exp.OnTime)) require.Less(t, 50000, int(exp.OnTime))
} }
dlInfo, err := client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
// Sector should expire.
for {
// Wait for the sector to expire.
status, err := miner.SectorsStatus(ctx, CC, true)
require.NoError(t, err)
if status.OnTime == 0 && status.Early == 0 {
break
}
t.Log("waiting for sector to expire")
// wait one deadline per loop.
time.Sleep(time.Duration(dlInfo.WPoStChallengeWindow) * blocktime)
}
fmt.Println("shutting down mining") fmt.Println("shutting down mining")
atomic.AddInt64(&mine, -1) atomic.AddInt64(&mine, -1)
<-done <-done

View File

@ -15,7 +15,6 @@ import (
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/extern/sector-storage/mock" "github.com/filecoin-project/lotus/extern/sector-storage/mock"
sealing "github.com/filecoin-project/lotus/extern/storage-sealing" sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
miner2 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
@ -154,18 +153,16 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
require.NoError(t, err) require.NoError(t, err)
fmt.Printf("Running one proving period\n") fmt.Printf("Running one proving period\n")
fmt.Printf("End for head.Height > %d\n", di.PeriodStart+di.WPoStProvingPeriod+2)
for { for {
head, err := client.ChainHead(ctx) head, err := client.ChainHead(ctx)
require.NoError(t, err) require.NoError(t, err)
if head.Height() > di.PeriodStart+(miner2.WPoStProvingPeriod)+2 { if head.Height() > di.PeriodStart+(di.WPoStProvingPeriod)+2 {
fmt.Printf("Now head.Height = %d\n", head.Height())
break break
} }
if head.Height()%100 == 0 {
fmt.Printf("@%d\n", head.Height())
}
build.Clock.Sleep(blocktime) build.Clock.Sleep(blocktime)
} }
@ -186,12 +183,13 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
require.NoError(t, err) require.NoError(t, err)
require.Greater(t, len(parts), 0) require.Greater(t, len(parts), 0)
n, err := parts[0].Sectors.Count() secs := parts[0].AllSectors
n, err := secs.Count()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, uint64(2), n) require.Equal(t, uint64(2), n)
// Drop the partition // Drop the partition
err = parts[0].Sectors.ForEach(func(sid uint64) error { err = secs.ForEach(func(sid uint64) error {
return miner.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).MarkCorrupted(abi.SectorID{ return miner.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).MarkCorrupted(abi.SectorID{
Miner: abi.ActorID(mid), Miner: abi.ActorID(mid),
Number: abi.SectorNumber(sid), Number: abi.SectorNumber(sid),
@ -208,15 +206,16 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
require.NoError(t, err) require.NoError(t, err)
require.Greater(t, len(parts), 0) require.Greater(t, len(parts), 0)
n, err := parts[0].Sectors.Count() secs := parts[0].AllSectors
n, err := secs.Count()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, uint64(2), n) require.Equal(t, uint64(2), n)
// Drop the sector // Drop the sector
sn, err := parts[0].Sectors.First() sn, err := secs.First()
require.NoError(t, err) require.NoError(t, err)
all, err := parts[0].Sectors.All(2) all, err := secs.All(2)
require.NoError(t, err) require.NoError(t, err)
fmt.Println("the sectors", all) fmt.Println("the sectors", all)
@ -233,18 +232,17 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
require.NoError(t, err) require.NoError(t, err)
fmt.Printf("Go through another PP, wait for sectors to become faulty\n") fmt.Printf("Go through another PP, wait for sectors to become faulty\n")
fmt.Printf("End for head.Height > %d\n", di.PeriodStart+di.WPoStProvingPeriod+2)
for { for {
head, err := client.ChainHead(ctx) head, err := client.ChainHead(ctx)
require.NoError(t, err) require.NoError(t, err)
if head.Height() > di.PeriodStart+(miner2.WPoStProvingPeriod)+2 { if head.Height() > di.PeriodStart+(di.WPoStProvingPeriod)+2 {
fmt.Printf("Now head.Height = %d\n", head.Height())
break break
} }
if head.Height()%100 == 0 {
fmt.Printf("@%d\n", head.Height())
}
build.Clock.Sleep(blocktime) build.Clock.Sleep(blocktime)
} }
@ -264,17 +262,17 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
di, err = client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK) di, err = client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
require.NoError(t, err) require.NoError(t, err)
fmt.Printf("End for head.Height > %d\n", di.PeriodStart+di.WPoStProvingPeriod+2)
for { for {
head, err := client.ChainHead(ctx) head, err := client.ChainHead(ctx)
require.NoError(t, err) require.NoError(t, err)
if head.Height() > di.PeriodStart+(miner2.WPoStProvingPeriod)+2 { if head.Height() > di.PeriodStart+di.WPoStProvingPeriod+2 {
fmt.Printf("Now head.Height = %d\n", head.Height())
break break
} }
if head.Height()%100 == 0 {
fmt.Printf("@%d\n", head.Height())
}
build.Clock.Sleep(blocktime) build.Clock.Sleep(blocktime)
} }
@ -297,12 +295,14 @@ func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSector
require.NoError(t, err) require.NoError(t, err)
waitUntil := head.Height() + 10 waitUntil := head.Height() + 10
fmt.Printf("End for head.Height > %d\n", waitUntil)
for { for {
head, err := client.ChainHead(ctx) head, err := client.ChainHead(ctx)
require.NoError(t, err) require.NoError(t, err)
if head.Height() > waitUntil { if head.Height() > waitUntil {
fmt.Printf("Now head.Height = %d\n", head.Height())
break break
} }
} }

View File

@ -4,11 +4,9 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/filecoin-project/go-address"
datatransfer "github.com/filecoin-project/go-data-transfer" datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
@ -49,48 +47,6 @@ type PubsubScore struct {
Score *pubsub.PeerScoreSnapshot Score *pubsub.PeerScoreSnapshot
} }
type MinerInfo struct {
Owner address.Address // Must be an ID-address.
Worker address.Address // Must be an ID-address.
NewWorker address.Address // Must be an ID-address.
ControlAddresses []address.Address // Must be an ID-addresses.
WorkerChangeEpoch abi.ChainEpoch
PeerId *peer.ID
Multiaddrs []abi.Multiaddrs
SealProofType abi.RegisteredSealProof
SectorSize abi.SectorSize
WindowPoStPartitionSectors uint64
}
func NewApiMinerInfo(info *miner.MinerInfo) MinerInfo {
var pid *peer.ID
if peerID, err := peer.IDFromBytes(info.PeerId); err == nil {
pid = &peerID
}
mi := MinerInfo{
Owner: info.Owner,
Worker: info.Worker,
ControlAddresses: info.ControlAddresses,
NewWorker: address.Undef,
WorkerChangeEpoch: -1,
PeerId: pid,
Multiaddrs: info.Multiaddrs,
SealProofType: info.SealProofType,
SectorSize: info.SectorSize,
WindowPoStPartitionSectors: info.WindowPoStPartitionSectors,
}
if info.PendingWorkerKey != nil {
mi.NewWorker = info.PendingWorkerKey.NewWorker
mi.WorkerChangeEpoch = info.PendingWorkerKey.EffectiveAt
}
return mi
}
type MessageSendSpec struct { type MessageSendSpec struct {
MaxFee abi.TokenAmount MaxFee abi.TokenAmount
} }

View File

@ -4,3 +4,9 @@
/dns4/bootstrap-4.testnet.fildev.network/tcp/1347/p2p/12D3KooWPkL9LrKRQgHtq7kn9ecNhGU9QaziG8R5tX8v9v7t3h34 /dns4/bootstrap-4.testnet.fildev.network/tcp/1347/p2p/12D3KooWPkL9LrKRQgHtq7kn9ecNhGU9QaziG8R5tX8v9v7t3h34
/dns4/bootstrap-3.testnet.fildev.network/tcp/1347/p2p/12D3KooWKYSsbpgZ3HAjax5M1BXCwXLa6gVkUARciz7uN3FNtr7T /dns4/bootstrap-3.testnet.fildev.network/tcp/1347/p2p/12D3KooWKYSsbpgZ3HAjax5M1BXCwXLa6gVkUARciz7uN3FNtr7T
/dns4/bootstrap-5.testnet.fildev.network/tcp/1347/p2p/12D3KooWQYzqnLASJAabyMpPb1GcWZvNSe7JDcRuhdRqonFoiK9W /dns4/bootstrap-5.testnet.fildev.network/tcp/1347/p2p/12D3KooWQYzqnLASJAabyMpPb1GcWZvNSe7JDcRuhdRqonFoiK9W
/dns4/lotus-bootstrap.forceup.cn/tcp/41778/p2p/12D3KooWFQsv3nRMUevZNWWsY1Wu6NUzUbawnWU5NcRhgKuJA37C
/dns4/bootstrap-0.starpool.in/tcp/12757/p2p/12D3KooWGHpBMeZbestVEWkfdnC9u7p6uFHXL1n7m1ZBqsEmiUzz
/dns4/bootstrap-1.starpool.in/tcp/12757/p2p/12D3KooWQZrGH1PxSNZPum99M1zNvjNFM33d1AAu5DcvdHptuU7u
/dns4/node.glif.io/tcp/1235/p2p/12D3KooWBF8cpp65hp2u9LK5mh19x67ftAam84z9LsfaquTDSBpt
/dns4/bootstrap-0.ipfsmain.cn/tcp/34721/p2p/12D3KooWQnwEGNqcM2nAcPtRR9rAX8Hrg4k9kJLCHoTR5chJfz6d
/dns4/bootstrap-1.ipfsmain.cn/tcp/34723/p2p/12D3KooWMKxMkD5DMpSWsW7dBddKxKT7L2GgbNuckz9otxvkvByP

View File

@ -4,27 +4,25 @@ package build
import ( import (
"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/specs-actors/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
) )
const UpgradeBreezeHeight = -1 const UpgradeBreezeHeight = -1
const BreezeGasTampingDuration = 0 const BreezeGasTampingDuration = 0
const UpgradeSmokeHeight = -1 const UpgradeSmokeHeight = -1
const UpgradeIgnitionHeight = -2
const UpgradeLiftoffHeight = -3
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet, 0: DrandMainnet,
} }
func init() { func init() {
power.ConsensusMinerMinPower = big.NewInt(2048) policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{ policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
abi.RegisteredSealProof_StackedDrg2KiBV1: {}, policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
}
verifreg.MinVerifiedDealSize = big.NewInt(256)
BuildType |= Build2k BuildType |= Build2k
} }

View File

@ -3,17 +3,19 @@ package build
import ( import (
"sort" "sort"
"github.com/filecoin-project/go-address"
"github.com/libp2p/go-libp2p-core/protocol" "github.com/libp2p/go-libp2p-core/protocol"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
) )
func DefaultSectorSize() abi.SectorSize { func DefaultSectorSize() abi.SectorSize {
szs := make([]abi.SectorSize, 0, len(miner.SupportedProofTypes)) szs := make([]abi.SectorSize, 0, len(miner0.SupportedProofTypes))
for spt := range miner.SupportedProofTypes { for spt := range miner0.SupportedProofTypes {
ss, err := spt.SectorSize() ss, err := spt.SectorSize()
if err != nil { if err != nil {
panic(err) panic(err)
@ -44,3 +46,7 @@ func UseNewestNetwork() bool {
} }
return false return false
} }
func SetAddressNetwork(n address.Network) {
address.CurrentNetwork = n
}

View File

@ -4,12 +4,15 @@ package build
import ( import (
"math/big" "math/big"
"os"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
) )
// ///// // /////
@ -22,7 +25,8 @@ const UnixfsLinksPerLevel = 1024
// Consensus / Network // Consensus / Network
const AllowableClockDriftSecs = uint64(1) const AllowableClockDriftSecs = uint64(1)
const NewestNetworkVersion = network.Version2 const NewestNetworkVersion = network.Version3
const ActorUpgradeNetworkVersion = network.Version4
// Epochs // Epochs
const ForkLengthThreshold = Finality const ForkLengthThreshold = Finality
@ -31,7 +35,7 @@ const ForkLengthThreshold = Finality
var BlocksPerEpoch = uint64(builtin.ExpectedLeadersPerEpoch) var BlocksPerEpoch = uint64(builtin.ExpectedLeadersPerEpoch)
// Epochs // Epochs
const Finality = miner.ChainFinality const Finality = miner0.ChainFinality
const MessageConfidence = uint64(5) const MessageConfidence = uint64(5)
// constants for Weight calculation // constants for Weight calculation
@ -59,9 +63,16 @@ const TicketRandomnessLookback = abi.ChainEpoch(1)
const WinningPoStSectorSetLookback = abi.ChainEpoch(10) const WinningPoStSectorSetLookback = abi.ChainEpoch(10)
// /////
// Address
const AddressMainnetEnvVar = "_mainnet_"
// ///// // /////
// Devnet settings // Devnet settings
var Devnet = true
const FilBase = uint64(2_000_000_000) const FilBase = uint64(2_000_000_000)
const FilAllocStorageMining = uint64(1_100_000_000) const FilAllocStorageMining = uint64(1_100_000_000)
@ -74,6 +85,10 @@ var InitialRewardBalance *big.Int
func init() { func init() {
InitialRewardBalance = big.NewInt(int64(FilAllocStorageMining)) InitialRewardBalance = big.NewInt(int64(FilAllocStorageMining))
InitialRewardBalance = InitialRewardBalance.Mul(InitialRewardBalance, big.NewInt(int64(FilecoinPrecision))) InitialRewardBalance = InitialRewardBalance.Mul(InitialRewardBalance, big.NewInt(int64(FilecoinPrecision)))
if os.Getenv("LOTUS_ADDRESS_TYPE") == AddressMainnetEnvVar {
SetAddressNetwork(address.Mainnet)
}
} }
// Sync // Sync

View File

@ -13,7 +13,7 @@ import (
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
) )
var ( var (
@ -32,7 +32,7 @@ var (
AllowableClockDriftSecs = uint64(1) AllowableClockDriftSecs = uint64(1)
Finality = miner.ChainFinality Finality = miner0.ChainFinality
ForkLengthThreshold = Finality ForkLengthThreshold = Finality
SlashablePowerDelay = 20 SlashablePowerDelay = 20
@ -74,11 +74,16 @@ var (
UpgradeBreezeHeight abi.ChainEpoch = -1 UpgradeBreezeHeight abi.ChainEpoch = -1
BreezeGasTampingDuration abi.ChainEpoch = 0 BreezeGasTampingDuration abi.ChainEpoch = 0
UpgradeSmokeHeight abi.ChainEpoch = -1 UpgradeSmokeHeight abi.ChainEpoch = -1
UpgradeIgnitionHeight abi.ChainEpoch = -2
UpgradeLiftoffHeight abi.ChainEpoch = -3
DrandSchedule = map[abi.ChainEpoch]DrandEnum{ DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet, 0: DrandMainnet,
} }
NewestNetworkVersion = network.Version2 NewestNetworkVersion = network.Version2
ActorUpgradeNetworkVersion = network.Version3
Devnet = true
) )

View File

@ -6,10 +6,9 @@ package build
import ( import (
"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/lotus/chain/actors/policy"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
) )
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
@ -22,14 +21,22 @@ const BreezeGasTampingDuration = 120
const UpgradeSmokeHeight = 51000 const UpgradeSmokeHeight = 51000
const UpgradeIgnitionHeight = 94000
// This signals our tentative epoch for mainnet launch. Can make it later, but not earlier.
// Miners, clients, developers, custodians all need time to prepare.
// We still have upgrades and state changes to do, but can happen after signaling timing here.
const UpgradeLiftoffHeight = 148888
func init() { func init() {
power.ConsensusMinerMinPower = big.NewInt(10 << 40) policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40))
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{ policy.SetSupportedProofTypes(
abi.RegisteredSealProof_StackedDrg32GiBV1: {}, abi.RegisteredSealProof_StackedDrg32GiBV1,
abi.RegisteredSealProof_StackedDrg64GiBV1: {}, abi.RegisteredSealProof_StackedDrg64GiBV1,
} )
Devnet = false
} }
const BlockDelaySecs = uint64(builtin.EpochDurationSeconds) const BlockDelaySecs = uint64(builtin0.EpochDurationSeconds)
const PropagationDelaySecs = uint64(6) const PropagationDelaySecs = uint64(6)

View File

@ -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.7.1" const BuildVersion = "0.8.1"
func UserVersion() string { func UserVersion() string {
return BuildVersion + buildType() + CurrentCommit return BuildVersion + buildType() + CurrentCommit
@ -83,9 +83,9 @@ 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, 15, 0) FullAPIVersion = newVer(0, 16, 0)
MinerAPIVersion = newVer(0, 14, 0) MinerAPIVersion = newVer(0, 15, 0)
WorkerAPIVersion = newVer(0, 14, 0) WorkerAPIVersion = newVer(0, 15, 0)
) )
//nolint:varcheck,deadcode //nolint:varcheck,deadcode

65
chain/actors/adt/adt.go Normal file
View File

@ -0,0 +1,65 @@
package adt
import (
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/builtin"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
)
type Map interface {
Root() (cid.Cid, error)
Put(k abi.Keyer, v cbor.Marshaler) error
Get(k abi.Keyer, v cbor.Unmarshaler) (bool, error)
Delete(k abi.Keyer) error
ForEach(v cbor.Unmarshaler, fn func(key string) error) error
}
func AsMap(store Store, root cid.Cid, version builtin.Version) (Map, error) {
switch version {
case builtin.Version0:
return adt0.AsMap(store, root)
}
return nil, xerrors.Errorf("unknown network version: %d", version)
}
func NewMap(store Store, version builtin.Version) (Map, error) {
switch version {
case builtin.Version0:
return adt0.MakeEmptyMap(store), nil
}
return nil, xerrors.Errorf("unknown network version: %d", version)
}
type Array interface {
Root() (cid.Cid, error)
Set(idx uint64, v cbor.Marshaler) error
Get(idx uint64, v cbor.Unmarshaler) (bool, error)
Delete(idx uint64) error
Length() uint64
ForEach(v cbor.Unmarshaler, fn func(idx int64) error) error
}
func AsArray(store Store, root cid.Cid, version network.Version) (Array, error) {
switch builtin.VersionForNetwork(version) {
case builtin.Version0:
return adt0.AsArray(store, root)
}
return nil, xerrors.Errorf("unknown network version: %d", version)
}
func NewArray(store Store, version builtin.Version) (Array, error) {
switch version {
case builtin.Version0:
return adt0.MakeEmptyArray(store), nil
}
return nil, xerrors.Errorf("unknown network version: %d", version)
}

View File

@ -1,10 +1,9 @@
package state package adt
import ( import (
"bytes" "bytes"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/util/adt"
typegen "github.com/whyrusleeping/cbor-gen" typegen "github.com/whyrusleeping/cbor-gen"
) )
@ -27,7 +26,8 @@ type AdtArrayDiff interface {
// - All values that exist in curArr nnd not in prevArr are passed to adtArrayDiff.Add() // - All values that exist in curArr nnd not in prevArr are passed to adtArrayDiff.Add()
// - All values that exist in preArr and in curArr are passed to AdtArrayDiff.Modify() // - All values that exist in preArr and in curArr are passed to AdtArrayDiff.Modify()
// - It is the responsibility of AdtArrayDiff.Modify() to determine if the values it was passed have been modified. // - It is the responsibility of AdtArrayDiff.Modify() to determine if the values it was passed have been modified.
func DiffAdtArray(preArr, curArr *adt.Array, out AdtArrayDiff) error { func DiffAdtArray(preArr, curArr Array, out AdtArrayDiff) error {
notNew := make(map[int64]struct{}, curArr.Length())
prevVal := new(typegen.Deferred) prevVal := new(typegen.Deferred)
if err := preArr.ForEach(prevVal, func(i int64) error { if err := preArr.ForEach(prevVal, func(i int64) error {
curVal := new(typegen.Deferred) curVal := new(typegen.Deferred)
@ -48,14 +48,17 @@ func DiffAdtArray(preArr, curArr *adt.Array, out AdtArrayDiff) error {
return err return err
} }
} }
notNew[i] = struct{}{}
return curArr.Delete(uint64(i)) return nil
}); err != nil { }); err != nil {
return err return err
} }
curVal := new(typegen.Deferred) curVal := new(typegen.Deferred)
return curArr.ForEach(curVal, func(i int64) error { return curArr.ForEach(curVal, func(i int64) error {
if _, ok := notNew[i]; ok {
return nil
}
return out.Add(uint64(i), curVal) return out.Add(uint64(i), curVal)
}) })
} }
@ -76,7 +79,8 @@ type AdtMapDiff interface {
Remove(key string, val *typegen.Deferred) error Remove(key string, val *typegen.Deferred) error
} }
func DiffAdtMap(preMap, curMap *adt.Map, out AdtMapDiff) error { func DiffAdtMap(preMap, curMap Map, out AdtMapDiff) error {
notNew := make(map[string]struct{})
prevVal := new(typegen.Deferred) prevVal := new(typegen.Deferred)
if err := preMap.ForEach(prevVal, func(key string) error { if err := preMap.ForEach(prevVal, func(key string) error {
curVal := new(typegen.Deferred) curVal := new(typegen.Deferred)
@ -102,14 +106,17 @@ func DiffAdtMap(preMap, curMap *adt.Map, out AdtMapDiff) error {
return err return err
} }
} }
notNew[key] = struct{}{}
return curMap.Delete(k) return nil
}); err != nil { }); err != nil {
return err return err
} }
curVal := new(typegen.Deferred) curVal := new(typegen.Deferred)
return curMap.ForEach(curVal, func(key string) error { return curMap.ForEach(curVal, func(key string) error {
if _, ok := notNew[key]; ok {
return nil
}
return out.Add(key, curVal) return out.Add(key, curVal)
}) })
} }

View File

@ -1,4 +1,4 @@
package state package adt
import ( import (
"bytes" "bytes"
@ -13,7 +13,7 @@ import (
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/runtime" "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt" adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
bstore "github.com/filecoin-project/lotus/lib/blockstore" bstore "github.com/filecoin-project/lotus/lib/blockstore"
) )
@ -22,8 +22,8 @@ func TestDiffAdtArray(t *testing.T) {
ctxstoreA := newContextStore() ctxstoreA := newContextStore()
ctxstoreB := newContextStore() ctxstoreB := newContextStore()
arrA := adt.MakeEmptyArray(ctxstoreA) arrA := adt0.MakeEmptyArray(ctxstoreA)
arrB := adt.MakeEmptyArray(ctxstoreB) arrB := adt0.MakeEmptyArray(ctxstoreB)
require.NoError(t, arrA.Set(0, runtime.CBORBytes([]byte{0}))) // delete require.NoError(t, arrA.Set(0, runtime.CBORBytes([]byte{0}))) // delete
@ -76,8 +76,8 @@ func TestDiffAdtMap(t *testing.T) {
ctxstoreA := newContextStore() ctxstoreA := newContextStore()
ctxstoreB := newContextStore() ctxstoreB := newContextStore()
mapA := adt.MakeEmptyMap(ctxstoreA) mapA := adt0.MakeEmptyMap(ctxstoreA)
mapB := adt.MakeEmptyMap(ctxstoreB) mapB := adt0.MakeEmptyMap(ctxstoreB)
require.NoError(t, mapA.Put(abi.UIntKey(0), runtime.CBORBytes([]byte{0}))) // delete require.NoError(t, mapA.Put(abi.UIntKey(0), runtime.CBORBytes([]byte{0}))) // delete
@ -292,12 +292,9 @@ func (t *TestDiffArray) Remove(key uint64, val *typegen.Deferred) error {
return nil return nil
} }
func newContextStore() *contextStore { func newContextStore() Store {
ctx := context.Background() ctx := context.Background()
bs := bstore.NewTemporarySync() bs := bstore.NewTemporarySync()
store := cbornode.NewCborStore(bs) store := cbornode.NewCborStore(bs)
return &contextStore{ return WrapStore(ctx, store)
ctx: ctx,
cst: store,
}
} }

17
chain/actors/adt/store.go Normal file
View File

@ -0,0 +1,17 @@
package adt
import (
"context"
adt "github.com/filecoin-project/specs-actors/actors/util/adt"
cbor "github.com/ipfs/go-ipld-cbor"
)
type Store interface {
Context() context.Context
cbor.IpldStore
}
func WrapStore(ctx context.Context, store cbor.IpldStore) Store {
return adt.WrapStore(ctx, store)
}

View File

@ -0,0 +1,29 @@
# Actors
This package contains shims for abstracting over different actor versions.
## Design
Shims in this package follow a few common design principles.
### Structure Agnostic
Shims interfaces defined in this package should (ideally) not change even if the
structure of the underlying data changes. For example:
* All shims store an internal "store" object. That way, state can be moved into
a separate object without needing to add a store to the function signature.
* All functions must return an error, even if unused for now.
### Minimal
These interfaces should be expanded only as necessary to reduce maintenance burden.
### Queries, not field assessors.
When possible, functions should query the state instead of simply acting as
field assessors. These queries are more likely to remain stable across
specs-actor upgrades than specific state fields.
Note: there is a trade-off here. Avoid implementing _complicated_ query logic
inside these shims, as it will need to be replicated in every shim.

View File

@ -0,0 +1,31 @@
package account
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
)
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
case builtin0.AccountActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
PubkeyAddress() (address.Address, error)
}

View File

@ -0,0 +1,18 @@
package account
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/specs-actors/actors/builtin/account"
)
var _ State = (*state0)(nil)
type state0 struct {
account.State
store adt.Store
}
func (s *state0) PubkeyAddress() (address.Address, error) {
return s.Address, nil
}

View File

@ -0,0 +1,43 @@
package builtin
import (
"fmt"
"github.com/filecoin-project/go-state-types/abi"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof"
smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing"
"github.com/filecoin-project/go-state-types/network"
)
type Version int
const (
Version0 = iota
)
// Converts a network version into a specs-actors version.
func VersionForNetwork(version network.Version) Version {
switch version {
case network.Version0, network.Version1, network.Version2, network.Version3:
return Version0
default:
panic(fmt.Sprintf("unsupported network version %d", version))
}
}
// TODO: Why does actors have 2 different versions of this?
type SectorInfo = proof0.SectorInfo
type PoStProof = proof0.PoStProof
type FilterEstimate = smoothing0.FilterEstimate
func FromV0FilterEstimate(v0 smoothing0.FilterEstimate) FilterEstimate {
return (FilterEstimate)(v0)
}
// Doesn't change between actors v0 and v1
func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower {
return miner0.QAPowerForWeight(size, duration, dealWeight, verifiedWeight)
}

View File

@ -0,0 +1,44 @@
package init
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes"
)
var Address = builtin0.InitActorAddr
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
case builtin0.InitActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
ResolveAddress(address address.Address) (address.Address, bool, error)
MapAddressToNewID(address address.Address) (address.Address, error)
NetworkName() (dtypes.NetworkName, error)
ForEachActor(func(id abi.ActorID, address address.Address) error) error
// Remove exists to support tooling that manipulates state for testing.
// It should not be used in production code, as init actor entries are
// immutable.
Remove(addrs ...address.Address) error
}

View File

@ -0,0 +1,67 @@
package init
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/node/modules/dtypes"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
)
var _ State = (*state0)(nil)
type state0 struct {
init_.State
store adt.Store
}
func (s *state0) ResolveAddress(address address.Address) (address.Address, bool, error) {
return s.State.ResolveAddress(s.store, address)
}
func (s *state0) MapAddressToNewID(address address.Address) (address.Address, error) {
return s.State.MapAddressToNewID(s.store, address)
}
func (s *state0) ForEachActor(cb func(id abi.ActorID, address address.Address) error) error {
addrs, err := adt0.AsMap(s.store, s.State.AddressMap)
if err != nil {
return err
}
var actorID cbg.CborInt
return addrs.ForEach(&actorID, func(key string) error {
addr, err := address.NewFromBytes([]byte(key))
if err != nil {
return err
}
return cb(abi.ActorID(actorID), addr)
})
}
func (s *state0) NetworkName() (dtypes.NetworkName, error) {
return dtypes.NetworkName(s.State.NetworkName), nil
}
func (s *state0) Remove(addrs ...address.Address) (err error) {
m, err := adt0.AsMap(s.store, s.State.AddressMap)
if err != nil {
return err
}
for _, addr := range addrs {
if err = m.Delete(abi.AddrKey(addr)); err != nil {
return xerrors.Errorf("failed to delete entry for address: %s; err: %w", addr, err)
}
}
amr, err := m.Root()
if err != nil {
return xerrors.Errorf("failed to get address map root: %w", err)
}
s.State.AddressMap = amr
return nil
}

View File

@ -0,0 +1,91 @@
package market
import (
"fmt"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/adt"
cbg "github.com/whyrusleeping/cbor-gen"
)
func DiffDealProposals(pre, cur DealProposals) (*DealProposalChanges, error) {
results := new(DealProposalChanges)
if err := adt.DiffAdtArray(pre.array(), cur.array(), &marketProposalsDiffer{results, pre, cur}); err != nil {
return nil, fmt.Errorf("diffing deal states: %w", err)
}
return results, nil
}
type marketProposalsDiffer struct {
Results *DealProposalChanges
pre, cur DealProposals
}
func (d *marketProposalsDiffer) Add(key uint64, val *cbg.Deferred) error {
dp, err := d.cur.decode(val)
if err != nil {
return err
}
d.Results.Added = append(d.Results.Added, ProposalIDState{abi.DealID(key), *dp})
return nil
}
func (d *marketProposalsDiffer) Modify(key uint64, from, to *cbg.Deferred) error {
// short circuit, DealProposals are static
return nil
}
func (d *marketProposalsDiffer) Remove(key uint64, val *cbg.Deferred) error {
dp, err := d.pre.decode(val)
if err != nil {
return err
}
d.Results.Removed = append(d.Results.Removed, ProposalIDState{abi.DealID(key), *dp})
return nil
}
func DiffDealStates(pre, cur DealStates) (*DealStateChanges, error) {
results := new(DealStateChanges)
if err := adt.DiffAdtArray(pre.array(), cur.array(), &marketStatesDiffer{results, pre, cur}); err != nil {
return nil, fmt.Errorf("diffing deal states: %w", err)
}
return results, nil
}
type marketStatesDiffer struct {
Results *DealStateChanges
pre, cur DealStates
}
func (d *marketStatesDiffer) Add(key uint64, val *cbg.Deferred) error {
ds, err := d.cur.decode(val)
if err != nil {
return err
}
d.Results.Added = append(d.Results.Added, DealIDState{abi.DealID(key), *ds})
return nil
}
func (d *marketStatesDiffer) Modify(key uint64, from, to *cbg.Deferred) error {
dsFrom, err := d.pre.decode(from)
if err != nil {
return err
}
dsTo, err := d.cur.decode(to)
if err != nil {
return err
}
if *dsFrom != *dsTo {
d.Results.Modified = append(d.Results.Modified, DealStateChange{abi.DealID(key), dsFrom, dsTo})
}
return nil
}
func (d *marketStatesDiffer) Remove(key uint64, val *cbg.Deferred) error {
ds, err := d.pre.decode(val)
if err != nil {
return err
}
d.Results.Removed = append(d.Results.Removed, DealIDState{abi.DealID(key), *ds})
return nil
}

View File

@ -0,0 +1,129 @@
package market
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
)
var Address = builtin0.StorageMarketActorAddr
func Load(store adt.Store, act *types.Actor) (st State, err error) {
switch act.Code {
case builtin0.StorageMarketActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
BalancesChanged(State) (bool, error)
EscrowTable() (BalanceTable, error)
LockedTable() (BalanceTable, error)
TotalLocked() (abi.TokenAmount, error)
StatesChanged(State) (bool, error)
States() (DealStates, error)
ProposalsChanged(State) (bool, error)
Proposals() (DealProposals, error)
VerifyDealsForActivation(
minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch,
) (weight, verifiedWeight abi.DealWeight, err error)
}
type BalanceTable interface {
ForEach(cb func(address.Address, abi.TokenAmount) error) error
Get(key address.Address) (abi.TokenAmount, error)
}
type DealStates interface {
ForEach(cb func(id abi.DealID, ds DealState) error) error
Get(id abi.DealID) (*DealState, bool, error)
array() adt.Array
decode(*cbg.Deferred) (*DealState, error)
}
type DealProposals interface {
ForEach(cb func(id abi.DealID, dp DealProposal) error) error
Get(id abi.DealID) (*DealProposal, bool, error)
array() adt.Array
decode(*cbg.Deferred) (*DealProposal, error)
}
type PublishStorageDealsParams = market0.PublishStorageDealsParams
type PublishStorageDealsReturn = market0.PublishStorageDealsReturn
type VerifyDealsForActivationParams = market0.VerifyDealsForActivationParams
type ClientDealProposal = market0.ClientDealProposal
type DealState struct {
SectorStartEpoch abi.ChainEpoch // -1 if not yet included in proven sector
LastUpdatedEpoch abi.ChainEpoch // -1 if deal state never updated
SlashEpoch abi.ChainEpoch // -1 if deal never slashed
}
type DealProposal struct {
PieceCID cid.Cid
PieceSize abi.PaddedPieceSize
VerifiedDeal bool
Client address.Address
Provider address.Address
Label string
StartEpoch abi.ChainEpoch
EndEpoch abi.ChainEpoch
StoragePricePerEpoch abi.TokenAmount
ProviderCollateral abi.TokenAmount
ClientCollateral abi.TokenAmount
}
type DealStateChanges struct {
Added []DealIDState
Modified []DealStateChange
Removed []DealIDState
}
type DealIDState struct {
ID abi.DealID
Deal DealState
}
// DealStateChange is a change in deal state from -> to
type DealStateChange struct {
ID abi.DealID
From *DealState
To *DealState
}
type DealProposalChanges struct {
Added []ProposalIDState
Removed []ProposalIDState
}
type ProposalIDState struct {
ID abi.DealID
Proposal DealProposal
}
func EmptyDealState() *DealState {
return &DealState{
SectorStartEpoch: -1,
SlashEpoch: -1,
LastUpdatedEpoch: -1,
}
}

View File

@ -0,0 +1,192 @@
package market
import (
"bytes"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
cbg "github.com/whyrusleeping/cbor-gen"
)
var _ State = (*state0)(nil)
type state0 struct {
market.State
store adt.Store
}
func (s *state0) TotalLocked() (abi.TokenAmount, error) {
fml := types.BigAdd(s.TotalClientLockedCollateral, s.TotalProviderLockedCollateral)
fml = types.BigAdd(fml, s.TotalClientStorageFee)
return fml, nil
}
func (s *state0) BalancesChanged(otherState State) (bool, error) {
otherState0, ok := otherState.(*state0)
if !ok {
// there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed
return true, nil
}
return !s.State.EscrowTable.Equals(otherState0.State.EscrowTable) || !s.State.LockedTable.Equals(otherState0.State.LockedTable), nil
}
func (s *state0) StatesChanged(otherState State) (bool, error) {
otherState0, ok := otherState.(*state0)
if !ok {
// there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed
return true, nil
}
return !s.State.States.Equals(otherState0.State.States), nil
}
func (s *state0) States() (DealStates, error) {
stateArray, err := adt0.AsArray(s.store, s.State.States)
if err != nil {
return nil, err
}
return &dealStates0{stateArray}, nil
}
func (s *state0) ProposalsChanged(otherState State) (bool, error) {
otherState0, ok := otherState.(*state0)
if !ok {
// there's no way to compare different versions of the state, so let's
// just say that means the state of balances has changed
return true, nil
}
return !s.State.Proposals.Equals(otherState0.State.Proposals), nil
}
func (s *state0) Proposals() (DealProposals, error) {
proposalArray, err := adt0.AsArray(s.store, s.State.Proposals)
if err != nil {
return nil, err
}
return &dealProposals0{proposalArray}, nil
}
func (s *state0) EscrowTable() (BalanceTable, error) {
bt, err := adt0.AsBalanceTable(s.store, s.State.EscrowTable)
if err != nil {
return nil, err
}
return &balanceTable0{bt}, nil
}
func (s *state0) LockedTable() (BalanceTable, error) {
bt, err := adt0.AsBalanceTable(s.store, s.State.LockedTable)
if err != nil {
return nil, err
}
return &balanceTable0{bt}, nil
}
func (s *state0) VerifyDealsForActivation(
minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch,
) (weight, verifiedWeight abi.DealWeight, err error) {
return market.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch)
}
type balanceTable0 struct {
*adt0.BalanceTable
}
func (bt *balanceTable0) ForEach(cb func(address.Address, abi.TokenAmount) error) error {
asMap := (*adt0.Map)(bt.BalanceTable)
var ta abi.TokenAmount
return asMap.ForEach(&ta, func(key string) error {
a, err := address.NewFromBytes([]byte(key))
if err != nil {
return err
}
return cb(a, ta)
})
}
type dealStates0 struct {
adt.Array
}
func (s *dealStates0) Get(dealID abi.DealID) (*DealState, bool, error) {
var deal0 market.DealState
found, err := s.Array.Get(uint64(dealID), &deal0)
if err != nil {
return nil, false, err
}
if !found {
return nil, false, nil
}
deal := fromV0DealState(deal0)
return &deal, true, nil
}
func (s *dealStates0) ForEach(cb func(dealID abi.DealID, ds DealState) error) error {
var ds0 market.DealState
return s.Array.ForEach(&ds0, func(idx int64) error {
return cb(abi.DealID(idx), fromV0DealState(ds0))
})
}
func (s *dealStates0) decode(val *cbg.Deferred) (*DealState, error) {
var ds0 market.DealState
if err := ds0.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err
}
ds := fromV0DealState(ds0)
return &ds, nil
}
func (s *dealStates0) array() adt.Array {
return s.Array
}
func fromV0DealState(v0 market.DealState) DealState {
return (DealState)(v0)
}
type dealProposals0 struct {
adt.Array
}
func (s *dealProposals0) Get(dealID abi.DealID) (*DealProposal, bool, error) {
var proposal0 market.DealProposal
found, err := s.Array.Get(uint64(dealID), &proposal0)
if err != nil {
return nil, false, err
}
if !found {
return nil, false, nil
}
proposal := fromV0DealProposal(proposal0)
return &proposal, true, nil
}
func (s *dealProposals0) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error {
var dp0 market.DealProposal
return s.Array.ForEach(&dp0, func(idx int64) error {
return cb(abi.DealID(idx), fromV0DealProposal(dp0))
})
}
func (s *dealProposals0) decode(val *cbg.Deferred) (*DealProposal, error) {
var dp0 market.DealProposal
if err := dp0.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err
}
dp := fromV0DealProposal(dp0)
return &dp, nil
}
func (s *dealProposals0) array() adt.Array {
return s.Array
}
func fromV0DealProposal(v0 market.DealProposal) DealProposal {
return (DealProposal)(v0)
}

View File

@ -0,0 +1,127 @@
package miner
import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/adt"
cbg "github.com/whyrusleeping/cbor-gen"
)
func DiffPreCommits(pre, cur State) (*PreCommitChanges, error) {
results := new(PreCommitChanges)
prep, err := pre.precommits()
if err != nil {
return nil, err
}
curp, err := cur.precommits()
if err != nil {
return nil, err
}
err = adt.DiffAdtMap(prep, curp, &preCommitDiffer{results, pre, cur})
if err != nil {
return nil, err
}
return results, nil
}
type preCommitDiffer struct {
Results *PreCommitChanges
pre, after State
}
func (m *preCommitDiffer) AsKey(key string) (abi.Keyer, error) {
sector, err := abi.ParseUIntKey(key)
if err != nil {
return nil, err
}
return abi.UIntKey(sector), nil
}
func (m *preCommitDiffer) Add(key string, val *cbg.Deferred) error {
sp, err := m.after.decodeSectorPreCommitOnChainInfo(val)
if err != nil {
return err
}
m.Results.Added = append(m.Results.Added, sp)
return nil
}
func (m *preCommitDiffer) Modify(key string, from, to *cbg.Deferred) error {
return nil
}
func (m *preCommitDiffer) Remove(key string, val *cbg.Deferred) error {
sp, err := m.pre.decodeSectorPreCommitOnChainInfo(val)
if err != nil {
return err
}
m.Results.Removed = append(m.Results.Removed, sp)
return nil
}
func DiffSectors(pre, cur State) (*SectorChanges, error) {
results := new(SectorChanges)
pres, err := pre.sectors()
if err != nil {
return nil, err
}
curs, err := cur.sectors()
if err != nil {
return nil, err
}
err = adt.DiffAdtArray(pres, curs, &sectorDiffer{results, pre, cur})
if err != nil {
return nil, err
}
return results, nil
}
type sectorDiffer struct {
Results *SectorChanges
pre, after State
}
func (m *sectorDiffer) Add(key uint64, val *cbg.Deferred) error {
si, err := m.after.decodeSectorOnChainInfo(val)
if err != nil {
return err
}
m.Results.Added = append(m.Results.Added, si)
return nil
}
func (m *sectorDiffer) Modify(key uint64, from, to *cbg.Deferred) error {
siFrom, err := m.pre.decodeSectorOnChainInfo(from)
if err != nil {
return err
}
siTo, err := m.after.decodeSectorOnChainInfo(to)
if err != nil {
return err
}
if siFrom.Expiration != siTo.Expiration {
m.Results.Extended = append(m.Results.Extended, SectorExtensions{
From: siFrom,
To: siTo,
})
}
return nil
}
func (m *sectorDiffer) Remove(key uint64, val *cbg.Deferred) error {
si, err := m.pre.decodeSectorOnChainInfo(val)
if err != nil {
return err
}
m.Results.Removed = append(m.Results.Removed, si)
return nil
}

View File

@ -0,0 +1,173 @@
package miner
import (
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"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/cbor"
"github.com/filecoin-project/go-state-types/dline"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
)
// Unchanged between v0 and v1 actors
var WPoStProvingPeriod = miner0.WPoStProvingPeriod
var WPoStPeriodDeadlines = miner0.WPoStPeriodDeadlines
var WPoStChallengeWindow = miner0.WPoStChallengeWindow
var WPoStChallengeLookback = miner0.WPoStChallengeLookback
var FaultDeclarationCutoff = miner0.FaultDeclarationCutoff
const MinSectorExpiration = miner0.MinSectorExpiration
func Load(store adt.Store, act *types.Actor) (st State, err error) {
switch act.Code {
case builtin0.StorageMinerActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
// Total available balance to spend.
AvailableBalance(abi.TokenAmount) (abi.TokenAmount, error)
// Funds that will vest by the given epoch.
VestedFunds(abi.ChainEpoch) (abi.TokenAmount, error)
// Funds locked for various reasons.
LockedFunds() (LockedFunds, error)
GetSector(abi.SectorNumber) (*SectorOnChainInfo, error)
FindSector(abi.SectorNumber) (*SectorLocation, error)
GetSectorExpiration(abi.SectorNumber) (*SectorExpiration, error)
GetPrecommittedSector(abi.SectorNumber) (*SectorPreCommitOnChainInfo, error)
LoadSectors(sectorNos *bitfield.BitField) ([]*SectorOnChainInfo, error)
NumLiveSectors() (uint64, error)
IsAllocated(abi.SectorNumber) (bool, error)
LoadDeadline(idx uint64) (Deadline, error)
ForEachDeadline(cb func(idx uint64, dl Deadline) error) error
NumDeadlines() (uint64, error)
DeadlinesChanged(State) (bool, error)
Info() (MinerInfo, error)
DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error)
// Diff helpers. Used by Diff* functions internally.
sectors() (adt.Array, error)
decodeSectorOnChainInfo(*cbg.Deferred) (SectorOnChainInfo, error)
precommits() (adt.Map, error)
decodeSectorPreCommitOnChainInfo(*cbg.Deferred) (SectorPreCommitOnChainInfo, error)
}
type Deadline interface {
LoadPartition(idx uint64) (Partition, error)
ForEachPartition(cb func(idx uint64, part Partition) error) error
PostSubmissions() (bitfield.BitField, error)
PartitionsChanged(Deadline) (bool, error)
}
type Partition interface {
AllSectors() (bitfield.BitField, error)
FaultySectors() (bitfield.BitField, error)
RecoveringSectors() (bitfield.BitField, error)
LiveSectors() (bitfield.BitField, error)
ActiveSectors() (bitfield.BitField, error)
}
type SectorOnChainInfo struct {
SectorNumber abi.SectorNumber
SealProof abi.RegisteredSealProof
SealedCID cid.Cid
DealIDs []abi.DealID
Activation abi.ChainEpoch
Expiration abi.ChainEpoch
DealWeight abi.DealWeight
VerifiedDealWeight abi.DealWeight
InitialPledge abi.TokenAmount
ExpectedDayReward abi.TokenAmount
ExpectedStoragePledge abi.TokenAmount
}
type SectorPreCommitInfo = miner0.SectorPreCommitInfo
type SectorPreCommitOnChainInfo struct {
Info SectorPreCommitInfo
PreCommitDeposit abi.TokenAmount
PreCommitEpoch abi.ChainEpoch
DealWeight abi.DealWeight
VerifiedDealWeight abi.DealWeight
}
type PoStPartition = miner0.PoStPartition
type RecoveryDeclaration = miner0.RecoveryDeclaration
type FaultDeclaration = miner0.FaultDeclaration
// Params
type DeclareFaultsParams = miner0.DeclareFaultsParams
type DeclareFaultsRecoveredParams = miner0.DeclareFaultsRecoveredParams
type SubmitWindowedPoStParams = miner0.SubmitWindowedPoStParams
type ProveCommitSectorParams = miner0.ProveCommitSectorParams
type MinerInfo struct {
Owner address.Address // Must be an ID-address.
Worker address.Address // Must be an ID-address.
NewWorker address.Address // Must be an ID-address.
ControlAddresses []address.Address // Must be an ID-addresses.
WorkerChangeEpoch abi.ChainEpoch
PeerId *peer.ID
Multiaddrs []abi.Multiaddrs
SealProofType abi.RegisteredSealProof
SectorSize abi.SectorSize
WindowPoStPartitionSectors uint64
}
type SectorExpiration struct {
OnTime abi.ChainEpoch
// non-zero if sector is faulty, epoch at which it will be permanently
// removed if it doesn't recover
Early abi.ChainEpoch
}
type SectorLocation struct {
Deadline uint64
Partition uint64
}
type SectorChanges struct {
Added []SectorOnChainInfo
Extended []SectorExtensions
Removed []SectorOnChainInfo
}
type SectorExtensions struct {
From SectorOnChainInfo
To SectorOnChainInfo
}
type PreCommitChanges struct {
Added []SectorPreCommitOnChainInfo
Removed []SectorPreCommitOnChainInfo
}
type LockedFunds struct {
VestingFunds abi.TokenAmount
InitialPledgeRequirement abi.TokenAmount
PreCommitDeposits abi.TokenAmount
}

View File

@ -0,0 +1,28 @@
package miner
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-bitfield"
)
func AllPartSectors(mas State, sget func(Partition) (bitfield.BitField, error)) (bitfield.BitField, error) {
var parts []bitfield.BitField
err := mas.ForEachDeadline(func(dlidx uint64, dl Deadline) error {
return dl.ForEachPartition(func(partidx uint64, part Partition) error {
s, err := sget(part)
if err != nil {
return xerrors.Errorf("getting sector list (dl: %d, part %d): %w", dlidx, partidx, err)
}
parts = append(parts, s)
return nil
})
})
if err != nil {
return bitfield.BitField{}, err
}
return bitfield.MultiMerge(parts...)
}

View File

@ -0,0 +1,373 @@
package miner
import (
"bytes"
"errors"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"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/dline"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/actors/adt"
)
var _ State = (*state0)(nil)
type state0 struct {
miner0.State
store adt.Store
}
type deadline0 struct {
miner0.Deadline
store adt.Store
}
type partition0 struct {
miner0.Partition
store adt.Store
}
func (s *state0) AvailableBalance(bal abi.TokenAmount) (abi.TokenAmount, error) {
return s.GetAvailableBalance(bal), nil
}
func (s *state0) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) {
return s.CheckVestedFunds(s.store, epoch)
}
func (s *state0) LockedFunds() (LockedFunds, error) {
return LockedFunds{
VestingFunds: s.State.LockedFunds,
InitialPledgeRequirement: s.State.InitialPledgeRequirement,
PreCommitDeposits: s.State.PreCommitDeposits,
}, nil
}
func (s *state0) InitialPledge() (abi.TokenAmount, error) {
return s.State.InitialPledgeRequirement, nil
}
func (s *state0) PreCommitDeposits() (abi.TokenAmount, error) {
return s.State.PreCommitDeposits, nil
}
func (s *state0) GetSector(num abi.SectorNumber) (*SectorOnChainInfo, error) {
info, ok, err := s.State.GetSector(s.store, num)
if !ok || err != nil {
return nil, err
}
ret := fromV0SectorOnChainInfo(*info)
return &ret, nil
}
func (s *state0) FindSector(num abi.SectorNumber) (*SectorLocation, error) {
dlIdx, partIdx, err := s.State.FindSector(s.store, num)
if err != nil {
return nil, err
}
return &SectorLocation{
Deadline: dlIdx,
Partition: partIdx,
}, nil
}
func (s *state0) NumLiveSectors() (uint64, error) {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return 0, err
}
var total uint64
if err := dls.ForEach(s.store, func(dlIdx uint64, dl *miner0.Deadline) error {
total += dl.LiveSectors
return nil
}); err != nil {
return 0, err
}
return total, nil
}
// GetSectorExpiration returns the effective expiration of the given sector.
//
// If the sector does not expire early, the Early expiration field is 0.
func (s *state0) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, error) {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return nil, err
}
// NOTE: this can be optimized significantly.
// 1. If the sector is non-faulty, it will either expire on-time (can be
// learned from the sector info), or in the next quantized expiration
// epoch (i.e., the first element in the partition's expiration queue.
// 2. If it's faulty, it will expire early within the first 14 entries
// of the expiration queue.
stopErr := errors.New("stop")
out := SectorExpiration{}
err = dls.ForEach(s.store, func(dlIdx uint64, dl *miner0.Deadline) error {
partitions, err := dl.PartitionsArray(s.store)
if err != nil {
return err
}
quant := s.State.QuantSpecForDeadline(dlIdx)
var part miner0.Partition
return partitions.ForEach(&part, func(partIdx int64) error {
if found, err := part.Sectors.IsSet(uint64(num)); err != nil {
return err
} else if !found {
return nil
}
if found, err := part.Terminated.IsSet(uint64(num)); err != nil {
return err
} else if found {
// already terminated
return stopErr
}
q, err := miner0.LoadExpirationQueue(s.store, part.ExpirationsEpochs, quant)
if err != nil {
return err
}
var exp miner0.ExpirationSet
return q.ForEach(&exp, func(epoch int64) error {
if early, err := exp.EarlySectors.IsSet(uint64(num)); err != nil {
return err
} else if early {
out.Early = abi.ChainEpoch(epoch)
return nil
}
if onTime, err := exp.OnTimeSectors.IsSet(uint64(num)); err != nil {
return err
} else if onTime {
out.OnTime = abi.ChainEpoch(epoch)
return stopErr
}
return nil
})
})
})
if err == stopErr {
err = nil
}
if err != nil {
return nil, err
}
if out.Early == 0 && out.OnTime == 0 {
return nil, xerrors.Errorf("failed to find sector %d", num)
}
return &out, nil
}
func (s *state0) GetPrecommittedSector(num abi.SectorNumber) (*SectorPreCommitOnChainInfo, error) {
info, ok, err := s.State.GetPrecommittedSector(s.store, num)
if !ok || err != nil {
return nil, err
}
ret := fromV0SectorPreCommitOnChainInfo(*info)
return &ret, nil
}
func (s *state0) LoadSectors(snos *bitfield.BitField) ([]*SectorOnChainInfo, error) {
sectors, err := miner0.LoadSectors(s.store, s.State.Sectors)
if err != nil {
return nil, err
}
// If no sector numbers are specified, load all.
if snos == nil {
infos := make([]*SectorOnChainInfo, 0, sectors.Length())
var info0 miner0.SectorOnChainInfo
if err := sectors.ForEach(&info0, func(_ int64) error {
info := fromV0SectorOnChainInfo(info0)
infos = append(infos, &info)
return nil
}); err != nil {
return nil, err
}
return infos, nil
}
// Otherwise, load selected.
infos0, err := sectors.Load(*snos)
if err != nil {
return nil, err
}
infos := make([]*SectorOnChainInfo, len(infos0))
for i, info0 := range infos0 {
info := fromV0SectorOnChainInfo(*info0)
infos[i] = &info
}
return infos, nil
}
func (s *state0) IsAllocated(num abi.SectorNumber) (bool, error) {
var allocatedSectors bitfield.BitField
if err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors); err != nil {
return false, err
}
return allocatedSectors.IsSet(uint64(num))
}
func (s *state0) LoadDeadline(idx uint64) (Deadline, error) {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return nil, err
}
dl, err := dls.LoadDeadline(s.store, idx)
if err != nil {
return nil, err
}
return &deadline0{*dl, s.store}, nil
}
func (s *state0) ForEachDeadline(cb func(uint64, Deadline) error) error {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return err
}
return dls.ForEach(s.store, func(i uint64, dl *miner0.Deadline) error {
return cb(i, &deadline0{*dl, s.store})
})
}
func (s *state0) NumDeadlines() (uint64, error) {
return miner0.WPoStPeriodDeadlines, nil
}
func (s *state0) DeadlinesChanged(other State) (bool, error) {
other0, ok := other.(*state0)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return s.State.Deadlines.Equals(other0.Deadlines), nil
}
func (s *state0) Info() (MinerInfo, error) {
info, err := s.State.GetInfo(s.store)
if err != nil {
return MinerInfo{}, err
}
var pid *peer.ID
if peerID, err := peer.IDFromBytes(info.PeerId); err == nil {
pid = &peerID
}
mi := MinerInfo{
Owner: info.Owner,
Worker: info.Worker,
ControlAddresses: info.ControlAddresses,
NewWorker: address.Undef,
WorkerChangeEpoch: -1,
PeerId: pid,
Multiaddrs: info.Multiaddrs,
SealProofType: info.SealProofType,
SectorSize: info.SectorSize,
WindowPoStPartitionSectors: info.WindowPoStPartitionSectors,
}
if info.PendingWorkerKey != nil {
mi.NewWorker = info.PendingWorkerKey.NewWorker
mi.WorkerChangeEpoch = info.PendingWorkerKey.EffectiveAt
}
return mi, nil
}
func (s *state0) DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error) {
return s.State.DeadlineInfo(epoch), nil
}
func (s *state0) sectors() (adt.Array, error) {
return adt0.AsArray(s.store, s.Sectors)
}
func (s *state0) decodeSectorOnChainInfo(val *cbg.Deferred) (SectorOnChainInfo, error) {
var si miner0.SectorOnChainInfo
err := si.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return SectorOnChainInfo{}, err
}
return fromV0SectorOnChainInfo(si), nil
}
func (s *state0) precommits() (adt.Map, error) {
return adt0.AsMap(s.store, s.PreCommittedSectors)
}
func (s *state0) decodeSectorPreCommitOnChainInfo(val *cbg.Deferred) (SectorPreCommitOnChainInfo, error) {
var sp miner0.SectorPreCommitOnChainInfo
err := sp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return SectorPreCommitOnChainInfo{}, err
}
return fromV0SectorPreCommitOnChainInfo(sp), nil
}
func (d *deadline0) LoadPartition(idx uint64) (Partition, error) {
p, err := d.Deadline.LoadPartition(d.store, idx)
if err != nil {
return nil, err
}
return &partition0{*p, d.store}, nil
}
func (d *deadline0) ForEachPartition(cb func(uint64, Partition) error) error {
ps, err := d.Deadline.PartitionsArray(d.store)
if err != nil {
return err
}
var part miner0.Partition
return ps.ForEach(&part, func(i int64) error {
return cb(uint64(i), &partition0{part, d.store})
})
}
func (d *deadline0) PartitionsChanged(other Deadline) (bool, error) {
other0, ok := other.(*deadline0)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return d.Deadline.Partitions.Equals(other0.Deadline.Partitions), nil
}
func (d *deadline0) PostSubmissions() (bitfield.BitField, error) {
return d.Deadline.PostSubmissions, nil
}
func (p *partition0) AllSectors() (bitfield.BitField, error) {
return p.Partition.Sectors, nil
}
func (p *partition0) FaultySectors() (bitfield.BitField, error) {
return p.Partition.Faults, nil
}
func (p *partition0) RecoveringSectors() (bitfield.BitField, error) {
return p.Partition.Recoveries, nil
}
func fromV0SectorOnChainInfo(v0 miner0.SectorOnChainInfo) SectorOnChainInfo {
return (SectorOnChainInfo)(v0)
}
func fromV0SectorPreCommitOnChainInfo(v0 miner0.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo {
return (SectorPreCommitOnChainInfo)(v0)
}

View File

@ -0,0 +1,43 @@
package multisig
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
)
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
case builtin0.MultisigActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
LockedBalance(epoch abi.ChainEpoch) (abi.TokenAmount, error)
StartEpoch() (abi.ChainEpoch, error)
UnlockDuration() (abi.ChainEpoch, error)
InitialBalance() (abi.TokenAmount, error)
Threshold() (uint64, error)
Signers() ([]address.Address, error)
ForEachPendingTxn(func(id int64, txn Transaction) error) error
}
type Transaction = msig0.Transaction

View File

@ -0,0 +1,59 @@
package multisig
import (
"encoding/binary"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/adt"
"golang.org/x/xerrors"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
)
var _ State = (*state0)(nil)
type state0 struct {
msig0.State
store adt.Store
}
func (s *state0) LockedBalance(currEpoch abi.ChainEpoch) (abi.TokenAmount, error) {
return s.State.AmountLocked(currEpoch - s.State.StartEpoch), nil
}
func (s *state0) StartEpoch() (abi.ChainEpoch, error) {
return s.State.StartEpoch, nil
}
func (s *state0) UnlockDuration() (abi.ChainEpoch, error) {
return s.State.UnlockDuration, nil
}
func (s *state0) InitialBalance() (abi.TokenAmount, error) {
return s.State.InitialBalance, nil
}
func (s *state0) Threshold() (uint64, error) {
return s.State.NumApprovalsThreshold, nil
}
func (s *state0) Signers() ([]address.Address, error) {
return s.State.Signers, nil
}
func (s *state0) ForEachPendingTxn(cb func(id int64, txn Transaction) error) error {
arr, err := adt0.AsMap(s.store, s.State.PendingTxns)
if err != nil {
return err
}
var out msig0.Transaction
return arr.ForEach(&out, func(key string) error {
txid, n := binary.Varint([]byte(key))
if n <= 0 {
return xerrors.Errorf("invalid pending transaction key: %v", key)
}
return cb(txid, (Transaction)(out))
})
}

View File

@ -0,0 +1,89 @@
package mock
import (
"io"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
)
type mockState struct {
from address.Address
to address.Address
settlingAt abi.ChainEpoch
toSend abi.TokenAmount
lanes map[uint64]paych.LaneState
}
type mockLaneState struct {
redeemed big.Int
nonce uint64
}
// NewMockPayChState constructs a state for a payment channel with the set fixed values
// that satisfies the paych.State interface.
func NewMockPayChState(from address.Address,
to address.Address,
settlingAt abi.ChainEpoch,
toSend abi.TokenAmount,
lanes map[uint64]paych.LaneState,
) paych.State {
return &mockState{from, to, settlingAt, toSend, lanes}
}
// NewMockLaneState constructs a state for a payment channel lane with the set fixed values
// that satisfies the paych.LaneState interface. Useful for populating lanes when
// calling NewMockPayChState
func NewMockLaneState(redeemed big.Int, nonce uint64) paych.LaneState {
return &mockLaneState{redeemed, nonce}
}
func (ms *mockState) MarshalCBOR(io.Writer) error {
panic("not implemented")
}
// Channel owner, who has funded the actor
func (ms *mockState) From() (address.Address, error) {
return ms.from, nil
}
// Recipient of payouts from channel
func (ms *mockState) To() (address.Address, error) {
return ms.to, nil
}
// Height at which the channel can be `Collected`
func (ms *mockState) SettlingAt() (abi.ChainEpoch, error) {
return ms.settlingAt, nil
}
// Amount successfully redeemed through the payment channel, paid out on `Collect()`
func (ms *mockState) ToSend() (abi.TokenAmount, error) {
return ms.toSend, nil
}
// Get total number of lanes
func (ms *mockState) LaneCount() (uint64, error) {
return uint64(len(ms.lanes)), nil
}
// Iterate lane states
func (ms *mockState) ForEachLaneState(cb func(idx uint64, dl paych.LaneState) error) error {
var lastErr error
for lane, state := range ms.lanes {
if err := cb(lane, state); err != nil {
lastErr = err
}
}
return lastErr
}
func (mls *mockLaneState) Redeemed() (big.Int, error) {
return mls.redeemed, nil
}
func (mls *mockLaneState) Nonce() (uint64, error) {
return mls.nonce, nil
}

View File

@ -0,0 +1,60 @@
package paych
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
big "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
)
// Load returns an abstract copy of payment channel state, irregardless of actor version
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
case builtin0.PaymentChannelActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
// State is an abstract version of payment channel state that works across
// versions
type State interface {
cbor.Marshaler
// Channel owner, who has funded the actor
From() (address.Address, error)
// Recipient of payouts from channel
To() (address.Address, error)
// Height at which the channel can be `Collected`
SettlingAt() (abi.ChainEpoch, error)
// Amount successfully redeemed through the payment channel, paid out on `Collect()`
ToSend() (abi.TokenAmount, error)
// Get total number of lanes
LaneCount() (uint64, error)
// Iterate lane states
ForEachLaneState(cb func(idx uint64, dl LaneState) error) error
}
// LaneState is an abstract copy of the state of a single lane
type LaneState interface {
Redeemed() (big.Int, error)
Nonce() (uint64, error)
}
type SignedVoucher = paych0.SignedVoucher
type ModVerifyParams = paych0.ModVerifyParams

View File

@ -0,0 +1,91 @@
package paych
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
big "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
)
var _ State = (*state0)(nil)
type state0 struct {
paych.State
store adt.Store
lsAmt *adt0.Array
}
// Channel owner, who has funded the actor
func (s *state0) From() (address.Address, error) {
return s.State.From, nil
}
// Recipient of payouts from channel
func (s *state0) To() (address.Address, error) {
return s.State.To, nil
}
// Height at which the channel can be `Collected`
func (s *state0) SettlingAt() (abi.ChainEpoch, error) {
return s.State.SettlingAt, nil
}
// Amount successfully redeemed through the payment channel, paid out on `Collect()`
func (s *state0) ToSend() (abi.TokenAmount, error) {
return s.State.ToSend, nil
}
func (s *state0) getOrLoadLsAmt() (*adt0.Array, error) {
if s.lsAmt != nil {
return s.lsAmt, nil
}
// Get the lane state from the chain
lsamt, err := adt0.AsArray(s.store, s.State.LaneStates)
if err != nil {
return nil, err
}
s.lsAmt = lsamt
return lsamt, nil
}
// Get total number of lanes
func (s *state0) LaneCount() (uint64, error) {
lsamt, err := s.getOrLoadLsAmt()
if err != nil {
return 0, err
}
return lsamt.Length(), nil
}
// Iterate lane states
func (s *state0) ForEachLaneState(cb func(idx uint64, dl LaneState) error) error {
// Get the lane state from the chain
lsamt, err := s.getOrLoadLsAmt()
if err != nil {
return err
}
// Note: we use a map instead of an array to store laneStates because the
// client sets the lane ID (the index) and potentially they could use a
// very large index.
var ls paych.LaneState
return lsamt.ForEach(&ls, func(i int64) error {
return cb(uint64(i), &laneState0{ls})
})
}
type laneState0 struct {
paych.LaneState
}
func (ls *laneState0) Redeemed() (big.Int, error) {
return ls.LaneState.Redeemed, nil
}
func (ls *laneState0) Nonce() (uint64, error) {
return ls.LaneState.Nonce, nil
}

View File

@ -0,0 +1,53 @@
package power
import (
"github.com/filecoin-project/go-address"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
var Address = builtin0.StoragePowerActorAddr
func Load(store adt.Store, act *types.Actor) (st State, err error) {
switch act.Code {
case builtin0.StoragePowerActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
TotalLocked() (abi.TokenAmount, error)
TotalPower() (Claim, error)
TotalCommitted() (Claim, error)
TotalPowerSmoothed() (builtin.FilterEstimate, error)
// MinerCounts returns the number of miners. Participating is the number
// with power above the minimum miner threshold.
MinerCounts() (participating, total uint64, err error)
MinerPower(address.Address) (Claim, bool, error)
MinerNominalPowerMeetsConsensusMinimum(address.Address) (bool, error)
ListAllMiners() ([]address.Address, error)
}
type Claim struct {
// Sum of raw byte power for a miner's sectors.
RawBytePower abi.StoragePower
// Sum of quality adjusted power for a miner's sectors.
QualityAdjPower abi.StoragePower
}

View File

@ -0,0 +1,85 @@
package power
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/builtin"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/util/adt"
)
var _ State = (*state0)(nil)
type state0 struct {
power0.State
store adt.Store
}
func (s *state0) TotalLocked() (abi.TokenAmount, error) {
return s.TotalPledgeCollateral, nil
}
func (s *state0) TotalPower() (Claim, error) {
return Claim{
RawBytePower: s.TotalRawBytePower,
QualityAdjPower: s.TotalQualityAdjPower,
}, nil
}
// Committed power to the network. Includes miners below the minimum threshold.
func (s *state0) TotalCommitted() (Claim, error) {
return Claim{
RawBytePower: s.TotalBytesCommitted,
QualityAdjPower: s.TotalQABytesCommitted,
}, nil
}
func (s *state0) MinerPower(addr address.Address) (Claim, bool, error) {
claims, err := adt.AsMap(s.store, s.Claims)
if err != nil {
return Claim{}, false, err
}
var claim power0.Claim
ok, err := claims.Get(abi.AddrKey(addr), &claim)
if err != nil {
return Claim{}, false, err
}
return Claim{
RawBytePower: claim.RawBytePower,
QualityAdjPower: claim.QualityAdjPower,
}, ok, nil
}
func (s *state0) MinerNominalPowerMeetsConsensusMinimum(a address.Address) (bool, error) {
return s.State.MinerNominalPowerMeetsConsensusMinimum(s.store, a)
}
func (s *state0) TotalPowerSmoothed() (builtin.FilterEstimate, error) {
return builtin.FromV0FilterEstimate(*s.State.ThisEpochQAPowerSmoothed), nil
}
func (s *state0) MinerCounts() (uint64, uint64, error) {
return uint64(s.State.MinerAboveMinPowerCount), uint64(s.State.MinerCount), nil
}
func (s *state0) ListAllMiners() ([]address.Address, error) {
claims, err := adt.AsMap(s.store, s.Claims)
if err != nil {
return nil, err
}
var miners []address.Address
err = claims.ForEach(nil, func(k string) error {
a, err := address.NewFromBytes([]byte(k))
if err != nil {
return err
}
miners = append(miners, a)
return nil
})
if err != nil {
return nil, err
}
return miners, nil
}

View File

@ -0,0 +1,50 @@
package reward
import (
"github.com/filecoin-project/go-state-types/abi"
reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
)
var Address = builtin0.RewardActorAddr
func Load(store adt.Store, act *types.Actor) (st State, err error) {
switch act.Code {
case builtin0.RewardActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
ThisEpochBaselinePower() (abi.StoragePower, error)
ThisEpochReward() (abi.StoragePower, error)
ThisEpochRewardSmoothed() (builtin.FilterEstimate, error)
EffectiveBaselinePower() (abi.StoragePower, error)
EffectiveNetworkTime() (abi.ChainEpoch, error)
TotalStoragePowerReward() (abi.TokenAmount, error)
CumsumBaseline() (abi.StoragePower, error)
CumsumRealized() (abi.StoragePower, error)
InitialPledgeForPower(abi.StoragePower, abi.TokenAmount, *builtin.FilterEstimate, abi.TokenAmount) (abi.TokenAmount, error)
PreCommitDepositForPower(builtin.FilterEstimate, abi.StoragePower) (abi.TokenAmount, error)
}
type AwardBlockRewardParams = reward0.AwardBlockRewardParams

View File

@ -0,0 +1,71 @@
package reward
import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/specs-actors/actors/util/smoothing"
)
var _ State = (*state0)(nil)
type state0 struct {
reward.State
store adt.Store
}
func (s *state0) ThisEpochReward() (abi.StoragePower, error) {
return s.State.ThisEpochReward, nil
}
func (s *state0) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) {
return builtin.FromV0FilterEstimate(*s.State.ThisEpochRewardSmoothed), nil
}
func (s *state0) ThisEpochBaselinePower() (abi.StoragePower, error) {
return s.State.ThisEpochBaselinePower, nil
}
func (s *state0) TotalStoragePowerReward() (abi.TokenAmount, error) {
return s.State.TotalMined, nil
}
func (s *state0) EffectiveBaselinePower() (abi.StoragePower, error) {
return s.State.EffectiveBaselinePower, nil
}
func (s *state0) EffectiveNetworkTime() (abi.ChainEpoch, error) {
return s.State.EffectiveNetworkTime, nil
}
func (s *state0) CumsumBaseline() (abi.StoragePower, error) {
return s.State.CumsumBaseline, nil
}
func (s *state0) CumsumRealized() (abi.StoragePower, error) {
return s.State.CumsumBaseline, nil
}
func (s *state0) InitialPledgeForPower(sectorWeight abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) {
return miner0.InitialPledgeForPower(
sectorWeight,
s.State.ThisEpochBaselinePower,
networkTotalPledge,
s.State.ThisEpochRewardSmoothed,
&smoothing.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
},
circSupply), nil
}
func (s *state0) PreCommitDepositForPower(networkQAPower builtin.FilterEstimate, sectorWeight abi.StoragePower) (abi.TokenAmount, error) {
return miner0.PreCommitDepositForPower(s.State.ThisEpochRewardSmoothed,
&smoothing.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
},
sectorWeight), nil
}

View File

@ -0,0 +1,71 @@
package verifreg
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors/adt"
)
var _ State = (*state0)(nil)
type state0 struct {
verifreg0.State
store adt.Store
}
func getDataCap(store adt.Store, root cid.Cid, addr address.Address) (bool, abi.StoragePower, error) {
if addr.Protocol() != address.ID {
return false, big.Zero(), xerrors.Errorf("can only look up ID addresses")
}
vh, err := adt0.AsMap(store, root)
if err != nil {
return false, big.Zero(), xerrors.Errorf("loading verifreg: %w", err)
}
var dcap abi.StoragePower
if found, err := vh.Get(abi.AddrKey(addr), &dcap); err != nil {
return false, big.Zero(), xerrors.Errorf("looking up addr: %w", err)
} else if !found {
return false, big.Zero(), nil
}
return true, dcap, nil
}
func (s *state0) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) {
return getDataCap(s.store, s.State.VerifiedClients, addr)
}
func (s *state0) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) {
return getDataCap(s.store, s.State.Verifiers, addr)
}
func forEachCap(store adt.Store, root cid.Cid, cb func(addr address.Address, dcap abi.StoragePower) error) error {
vh, err := adt0.AsMap(store, root)
if err != nil {
return xerrors.Errorf("loading verified clients: %w", err)
}
var dcap abi.StoragePower
return vh.ForEach(&dcap, func(key string) error {
a, err := address.NewFromBytes([]byte(key))
if err != nil {
return err
}
return cb(a, dcap)
})
}
func (s *state0) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error {
return forEachCap(s.store, s.State.Verifiers, cb)
}
func (s *state0) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error {
return forEachCap(s.store, s.State.VerifiedClients, cb)
}

View File

@ -0,0 +1,37 @@
package verifreg
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
)
var Address = builtin0.VerifiedRegistryActorAddr
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
case builtin0.VerifiedRegistryActorCodeID:
out := state0{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
VerifiedClientDataCap(address.Address) (bool, abi.StoragePower, error)
VerifierDataCap(address.Address) (bool, abi.StoragePower, error)
ForEachVerifier(func(addr address.Address, dcap abi.StoragePower) error) error
ForEachClient(func(addr address.Address, dcap abi.StoragePower) error) error
}

View File

@ -0,0 +1,54 @@
package policy
import (
"github.com/filecoin-project/go-state-types/abi"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
)
// SetSupportedProofTypes sets supported proof types, across all actor versions.
// This should only be used for testing.
func SetSupportedProofTypes(types ...abi.RegisteredSealProof) {
newTypes := make(map[abi.RegisteredSealProof]struct{}, len(types))
for _, t := range types {
newTypes[t] = struct{}{}
}
// Set for all miner versions.
miner0.SupportedProofTypes = newTypes
}
// AddSupportedProofTypes sets supported proof types, across all actor versions.
// This should only be used for testing.
func AddSupportedProofTypes(types ...abi.RegisteredSealProof) {
for _, t := range types {
// Set for all miner versions.
miner0.SupportedProofTypes[t] = struct{}{}
}
}
// SetPreCommitChallengeDelay sets the pre-commit challenge delay across all
// actors versions. Use for testing.
func SetPreCommitChallengeDelay(delay abi.ChainEpoch) {
// Set for all miner versions.
miner0.PreCommitChallengeDelay = delay
}
// TODO: this function shouldn't really exist. Instead, the API should expose the precommit delay.
func GetPreCommitChallengeDelay() abi.ChainEpoch {
return miner0.PreCommitChallengeDelay
}
// SetConsensusMinerMinPower sets the minimum power of an individual miner must
// meet for leader election, across all actor versions. This should only be used
// for testing.
func SetConsensusMinerMinPower(p abi.StoragePower) {
power0.ConsensusMinerMinPower = p
}
// SetMinVerifiedDealSize sets the minimum size of a verified deal. This should
// only be used for testing.
func SetMinVerifiedDealSize(size abi.StoragePower) {
verifreg0.MinVerifiedDealSize = size
}

View File

@ -0,0 +1,36 @@
package policy
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-state-types/abi"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
)
func TestSupportedProofTypes(t *testing.T) {
var oldTypes []abi.RegisteredSealProof
for t := range miner0.SupportedProofTypes {
oldTypes = append(oldTypes, t)
}
t.Cleanup(func() {
SetSupportedProofTypes(oldTypes...)
})
SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
require.EqualValues(t,
miner0.SupportedProofTypes,
map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
},
)
AddSupportedProofTypes(abi.RegisteredSealProof_StackedDrg8MiBV1)
require.EqualValues(t,
miner0.SupportedProofTypes,
map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
abi.RegisteredSealProof_StackedDrg8MiBV1: {},
},
)
}

View File

@ -4,20 +4,19 @@ import (
"bytes" "bytes"
"context" "context"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"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/specs-actors/actors/builtin"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
typegen "github.com/whyrusleeping/cbor-gen" typegen "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/lotus/api/apibstore" "github.com/filecoin-project/lotus/api/apibstore"
"github.com/filecoin-project/lotus/chain/actors/adt"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
@ -49,7 +48,7 @@ func NewStatePredicates(api ChainAPI) *StatePredicates {
// - err // - err
type DiffTipSetKeyFunc func(ctx context.Context, oldState, newState types.TipSetKey) (changed bool, user UserData, err error) type DiffTipSetKeyFunc func(ctx context.Context, oldState, newState types.TipSetKey) (changed bool, user UserData, err error)
type DiffActorStateFunc func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error) type DiffActorStateFunc func(ctx context.Context, oldActorState *types.Actor, newActorState *types.Actor) (changed bool, user UserData, err error)
// OnActorStateChanged calls diffStateFunc when the state changes for the given actor // OnActorStateChanged calls diffStateFunc when the state changes for the given actor
func (sp *StatePredicates) OnActorStateChanged(addr address.Address, diffStateFunc DiffActorStateFunc) DiffTipSetKeyFunc { func (sp *StatePredicates) OnActorStateChanged(addr address.Address, diffStateFunc DiffActorStateFunc) DiffTipSetKeyFunc {
@ -66,30 +65,30 @@ func (sp *StatePredicates) OnActorStateChanged(addr address.Address, diffStateFu
if oldActor.Head.Equals(newActor.Head) { if oldActor.Head.Equals(newActor.Head) {
return false, nil, nil return false, nil, nil
} }
return diffStateFunc(ctx, oldActor.Head, newActor.Head) return diffStateFunc(ctx, oldActor, newActor)
} }
} }
type DiffStorageMarketStateFunc func(ctx context.Context, oldState *market.State, newState *market.State) (changed bool, user UserData, err error) type DiffStorageMarketStateFunc func(ctx context.Context, oldState market.State, newState market.State) (changed bool, user UserData, err error)
// OnStorageMarketActorChanged calls diffStorageMarketState when the state changes for the market actor // OnStorageMarketActorChanged calls diffStorageMarketState when the state changes for the market actor
func (sp *StatePredicates) OnStorageMarketActorChanged(diffStorageMarketState DiffStorageMarketStateFunc) DiffTipSetKeyFunc { func (sp *StatePredicates) OnStorageMarketActorChanged(diffStorageMarketState DiffStorageMarketStateFunc) DiffTipSetKeyFunc {
return sp.OnActorStateChanged(builtin.StorageMarketActorAddr, func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error) { return sp.OnActorStateChanged(market.Address, func(ctx context.Context, oldActorState, newActorState *types.Actor) (changed bool, user UserData, err error) {
var oldState market.State oldState, err := market.Load(adt.WrapStore(ctx, sp.cst), oldActorState)
if err := sp.cst.Get(ctx, oldActorStateHead, &oldState); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
var newState market.State newState, err := market.Load(adt.WrapStore(ctx, sp.cst), newActorState)
if err := sp.cst.Get(ctx, newActorStateHead, &newState); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
return diffStorageMarketState(ctx, &oldState, &newState) return diffStorageMarketState(ctx, oldState, newState)
}) })
} }
type BalanceTables struct { type BalanceTables struct {
EscrowTable *adt.BalanceTable EscrowTable market.BalanceTable
LockedTable *adt.BalanceTable LockedTable market.BalanceTable
} }
// DiffBalanceTablesFunc compares two balance tables // DiffBalanceTablesFunc compares two balance tables
@ -97,32 +96,32 @@ type DiffBalanceTablesFunc func(ctx context.Context, oldBalanceTable, newBalance
// OnBalanceChanged runs when the escrow table for available balances changes // OnBalanceChanged runs when the escrow table for available balances changes
func (sp *StatePredicates) OnBalanceChanged(diffBalances DiffBalanceTablesFunc) DiffStorageMarketStateFunc { func (sp *StatePredicates) OnBalanceChanged(diffBalances DiffBalanceTablesFunc) DiffStorageMarketStateFunc {
return func(ctx context.Context, oldState *market.State, newState *market.State) (changed bool, user UserData, err error) { return func(ctx context.Context, oldState market.State, newState market.State) (changed bool, user UserData, err error) {
if oldState.EscrowTable.Equals(newState.EscrowTable) && oldState.LockedTable.Equals(newState.LockedTable) { bc, err := oldState.BalancesChanged(newState)
if err != nil {
return false, nil, err
}
if !bc {
return false, nil, nil return false, nil, nil
} }
ctxStore := &contextStore{ oldEscrowRoot, err := oldState.EscrowTable()
ctx: ctx,
cst: sp.cst,
}
oldEscrowRoot, err := adt.AsBalanceTable(ctxStore, oldState.EscrowTable)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
oldLockedRoot, err := adt.AsBalanceTable(ctxStore, oldState.LockedTable) oldLockedRoot, err := oldState.LockedTable()
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newEscrowRoot, err := adt.AsBalanceTable(ctxStore, newState.EscrowTable) newEscrowRoot, err := newState.EscrowTable()
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newLockedRoot, err := adt.AsBalanceTable(ctxStore, newState.LockedTable) newLockedRoot, err := newState.LockedTable()
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@ -131,25 +130,27 @@ func (sp *StatePredicates) OnBalanceChanged(diffBalances DiffBalanceTablesFunc)
} }
} }
type DiffAdtArraysFunc func(ctx context.Context, oldDealStateRoot, newDealStateRoot *adt.Array) (changed bool, user UserData, err error) type DiffDealStatesFunc func(ctx context.Context, oldDealStateRoot, newDealStateRoot market.DealStates) (changed bool, user UserData, err error)
type DiffDealProposalsFunc func(ctx context.Context, oldDealStateRoot, newDealStateRoot market.DealProposals) (changed bool, user UserData, err error)
type DiffAdtArraysFunc func(ctx context.Context, oldDealStateRoot, newDealStateRoot adt.Array) (changed bool, user UserData, err error)
// OnDealStateChanged calls diffDealStates when the market deal state changes // OnDealStateChanged calls diffDealStates when the market deal state changes
func (sp *StatePredicates) OnDealStateChanged(diffDealStates DiffAdtArraysFunc) DiffStorageMarketStateFunc { func (sp *StatePredicates) OnDealStateChanged(diffDealStates DiffDealStatesFunc) DiffStorageMarketStateFunc {
return func(ctx context.Context, oldState *market.State, newState *market.State) (changed bool, user UserData, err error) { return func(ctx context.Context, oldState market.State, newState market.State) (changed bool, user UserData, err error) {
if oldState.States.Equals(newState.States) { sc, err := oldState.StatesChanged(newState)
return false, nil, nil
}
ctxStore := &contextStore{
ctx: ctx,
cst: sp.cst,
}
oldRoot, err := adt.AsArray(ctxStore, oldState.States)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newRoot, err := adt.AsArray(ctxStore, newState.States)
if !sc {
return false, nil, nil
}
oldRoot, err := oldState.States()
if err != nil {
return false, nil, err
}
newRoot, err := newState.States()
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@ -159,22 +160,22 @@ func (sp *StatePredicates) OnDealStateChanged(diffDealStates DiffAdtArraysFunc)
} }
// OnDealProposalChanged calls diffDealProps when the market proposal state changes // OnDealProposalChanged calls diffDealProps when the market proposal state changes
func (sp *StatePredicates) OnDealProposalChanged(diffDealProps DiffAdtArraysFunc) DiffStorageMarketStateFunc { func (sp *StatePredicates) OnDealProposalChanged(diffDealProps DiffDealProposalsFunc) DiffStorageMarketStateFunc {
return func(ctx context.Context, oldState *market.State, newState *market.State) (changed bool, user UserData, err error) { return func(ctx context.Context, oldState market.State, newState market.State) (changed bool, user UserData, err error) {
if oldState.Proposals.Equals(newState.Proposals) { pc, err := oldState.ProposalsChanged(newState)
return false, nil, nil
}
ctxStore := &contextStore{
ctx: ctx,
cst: sp.cst,
}
oldRoot, err := adt.AsArray(ctxStore, oldState.Proposals)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newRoot, err := adt.AsArray(ctxStore, newState.Proposals)
if !pc {
return false, nil, nil
}
oldRoot, err := oldState.Proposals()
if err != nil {
return false, nil, err
}
newRoot, err := newState.Proposals()
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@ -183,51 +184,14 @@ func (sp *StatePredicates) OnDealProposalChanged(diffDealProps DiffAdtArraysFunc
} }
} }
var _ AdtArrayDiff = &MarketDealProposalChanges{}
type MarketDealProposalChanges struct {
Added []ProposalIDState
Removed []ProposalIDState
}
type ProposalIDState struct {
ID abi.DealID
Proposal market.DealProposal
}
func (m *MarketDealProposalChanges) Add(key uint64, val *typegen.Deferred) error {
dp := new(market.DealProposal)
err := dp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Added = append(m.Added, ProposalIDState{abi.DealID(key), *dp})
return nil
}
func (m *MarketDealProposalChanges) Modify(key uint64, from, to *typegen.Deferred) error {
// short circuit, DealProposals are static
return nil
}
func (m *MarketDealProposalChanges) Remove(key uint64, val *typegen.Deferred) error {
dp := new(market.DealProposal)
err := dp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Removed = append(m.Removed, ProposalIDState{abi.DealID(key), *dp})
return nil
}
// OnDealProposalAmtChanged detects changes in the deal proposal AMT for all deal proposals and returns a MarketProposalsChanges structure containing: // OnDealProposalAmtChanged detects changes in the deal proposal AMT for all deal proposals and returns a MarketProposalsChanges structure containing:
// - Added Proposals // - Added Proposals
// - Modified Proposals // - Modified Proposals
// - Removed Proposals // - Removed Proposals
func (sp *StatePredicates) OnDealProposalAmtChanged() DiffAdtArraysFunc { func (sp *StatePredicates) OnDealProposalAmtChanged() DiffDealProposalsFunc {
return func(ctx context.Context, oldDealProps, newDealProps *adt.Array) (changed bool, user UserData, err error) { return func(ctx context.Context, oldDealProps, newDealProps market.DealProposals) (changed bool, user UserData, err error) {
proposalChanges := new(MarketDealProposalChanges) proposalChanges, err := market.DiffDealProposals(oldDealProps, newDealProps)
if err := DiffAdtArray(oldDealProps, newDealProps, proposalChanges); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@ -239,64 +203,14 @@ func (sp *StatePredicates) OnDealProposalAmtChanged() DiffAdtArraysFunc {
} }
} }
var _ AdtArrayDiff = &MarketDealStateChanges{}
type MarketDealStateChanges struct {
Added []DealIDState
Modified []DealStateChange
Removed []DealIDState
}
type DealIDState struct {
ID abi.DealID
Deal market.DealState
}
func (m *MarketDealStateChanges) Add(key uint64, val *typegen.Deferred) error {
ds := new(market.DealState)
err := ds.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Added = append(m.Added, DealIDState{abi.DealID(key), *ds})
return nil
}
func (m *MarketDealStateChanges) Modify(key uint64, from, to *typegen.Deferred) error {
dsFrom := new(market.DealState)
if err := dsFrom.UnmarshalCBOR(bytes.NewReader(from.Raw)); err != nil {
return err
}
dsTo := new(market.DealState)
if err := dsTo.UnmarshalCBOR(bytes.NewReader(to.Raw)); err != nil {
return err
}
if *dsFrom != *dsTo {
m.Modified = append(m.Modified, DealStateChange{abi.DealID(key), dsFrom, dsTo})
}
return nil
}
func (m *MarketDealStateChanges) Remove(key uint64, val *typegen.Deferred) error {
ds := new(market.DealState)
err := ds.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Removed = append(m.Removed, DealIDState{abi.DealID(key), *ds})
return nil
}
// OnDealStateAmtChanged detects changes in the deal state AMT for all deal states and returns a MarketDealStateChanges structure containing: // OnDealStateAmtChanged detects changes in the deal state AMT for all deal states and returns a MarketDealStateChanges structure containing:
// - Added Deals // - Added Deals
// - Modified Deals // - Modified Deals
// - Removed Deals // - Removed Deals
func (sp *StatePredicates) OnDealStateAmtChanged() DiffAdtArraysFunc { func (sp *StatePredicates) OnDealStateAmtChanged() DiffDealStatesFunc {
return func(ctx context.Context, oldDealStates, newDealStates *adt.Array) (changed bool, user UserData, err error) { return func(ctx context.Context, oldDealStates, newDealStates market.DealStates) (changed bool, user UserData, err error) {
dealStateChanges := new(MarketDealStateChanges) dealStateChanges, err := market.DiffDealStates(oldDealStates, newDealStates)
if err := DiffAdtArray(oldDealStates, newDealStates, dealStateChanges); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@ -309,42 +223,29 @@ func (sp *StatePredicates) OnDealStateAmtChanged() DiffAdtArraysFunc {
} }
// ChangedDeals is a set of changes to deal state // ChangedDeals is a set of changes to deal state
type ChangedDeals map[abi.DealID]DealStateChange type ChangedDeals map[abi.DealID]market.DealStateChange
// DealStateChange is a change in deal state from -> to
type DealStateChange struct {
ID abi.DealID
From *market.DealState
To *market.DealState
}
// DealStateChangedForIDs detects changes in the deal state AMT for the given deal IDs // DealStateChangedForIDs detects changes in the deal state AMT for the given deal IDs
func (sp *StatePredicates) DealStateChangedForIDs(dealIds []abi.DealID) DiffAdtArraysFunc { func (sp *StatePredicates) DealStateChangedForIDs(dealIds []abi.DealID) DiffDealStatesFunc {
return func(ctx context.Context, oldDealStateArray, newDealStateArray *adt.Array) (changed bool, user UserData, err error) { return func(ctx context.Context, oldDealStates, newDealStates market.DealStates) (changed bool, user UserData, err error) {
changedDeals := make(ChangedDeals) changedDeals := make(ChangedDeals)
for _, dealID := range dealIds { for _, dealID := range dealIds {
var oldDealPtr, newDealPtr *market.DealState
var oldDeal, newDeal market.DealState
// If the deal has been removed, we just set it to nil // If the deal has been removed, we just set it to nil
found, err := oldDealStateArray.Get(uint64(dealID), &oldDeal) oldDeal, oldFound, err := oldDealStates.Get(dealID)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
if found {
oldDealPtr = &oldDeal
}
found, err = newDealStateArray.Get(uint64(dealID), &newDeal) newDeal, newFound, err := newDealStates.Get(dealID)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
if found {
newDealPtr = &newDeal
}
if oldDeal != newDeal { existenceChanged := oldFound != newFound
changedDeals[dealID] = DealStateChange{dealID, oldDealPtr, newDealPtr} valueChanged := (oldFound && newFound) && *oldDeal != *newDeal
if existenceChanged || valueChanged {
changedDeals[dealID] = market.DealStateChange{ID: dealID, From: oldDeal, To: newDeal}
} }
} }
if len(changedDeals) > 0 { if len(changedDeals) > 0 {
@ -405,124 +306,43 @@ func (sp *StatePredicates) AvailableBalanceChangedForAddresses(getAddrs func() [
} }
} }
type DiffMinerActorStateFunc func(ctx context.Context, oldState *miner.State, newState *miner.State) (changed bool, user UserData, err error) type DiffMinerActorStateFunc func(ctx context.Context, oldState miner.State, newState miner.State) (changed bool, user UserData, err error)
func (sp *StatePredicates) OnInitActorChange(diffInitActorState DiffInitActorStateFunc) DiffTipSetKeyFunc { func (sp *StatePredicates) OnInitActorChange(diffInitActorState DiffInitActorStateFunc) DiffTipSetKeyFunc {
return sp.OnActorStateChanged(builtin.InitActorAddr, func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error) { return sp.OnActorStateChanged(init_.Address, func(ctx context.Context, oldActorState, newActorState *types.Actor) (changed bool, user UserData, err error) {
var oldState init_.State oldState, err := init_.Load(adt.WrapStore(ctx, sp.cst), oldActorState)
if err := sp.cst.Get(ctx, oldActorStateHead, &oldState); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
var newState init_.State newState, err := init_.Load(adt.WrapStore(ctx, sp.cst), newActorState)
if err := sp.cst.Get(ctx, newActorStateHead, &newState); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
return diffInitActorState(ctx, &oldState, &newState) return diffInitActorState(ctx, oldState, newState)
}) })
} }
func (sp *StatePredicates) OnMinerActorChange(minerAddr address.Address, diffMinerActorState DiffMinerActorStateFunc) DiffTipSetKeyFunc { func (sp *StatePredicates) OnMinerActorChange(minerAddr address.Address, diffMinerActorState DiffMinerActorStateFunc) DiffTipSetKeyFunc {
return sp.OnActorStateChanged(minerAddr, func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error) { return sp.OnActorStateChanged(minerAddr, func(ctx context.Context, oldActorState, newActorState *types.Actor) (changed bool, user UserData, err error) {
var oldState miner.State oldState, err := miner.Load(adt.WrapStore(ctx, sp.cst), oldActorState)
if err := sp.cst.Get(ctx, oldActorStateHead, &oldState); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
var newState miner.State newState, err := miner.Load(adt.WrapStore(ctx, sp.cst), newActorState)
if err := sp.cst.Get(ctx, newActorStateHead, &newState); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
return diffMinerActorState(ctx, &oldState, &newState) return diffMinerActorState(ctx, oldState, newState)
}) })
} }
type MinerSectorChanges struct {
Added []miner.SectorOnChainInfo
Extended []SectorExtensions
Removed []miner.SectorOnChainInfo
}
var _ AdtArrayDiff = &MinerSectorChanges{}
type SectorExtensions struct {
From miner.SectorOnChainInfo
To miner.SectorOnChainInfo
}
func (m *MinerSectorChanges) Add(key uint64, val *typegen.Deferred) error {
si := new(miner.SectorOnChainInfo)
err := si.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Added = append(m.Added, *si)
return nil
}
func (m *MinerSectorChanges) Modify(key uint64, from, to *typegen.Deferred) error {
siFrom := new(miner.SectorOnChainInfo)
err := siFrom.UnmarshalCBOR(bytes.NewReader(from.Raw))
if err != nil {
return err
}
siTo := new(miner.SectorOnChainInfo)
err = siTo.UnmarshalCBOR(bytes.NewReader(to.Raw))
if err != nil {
return err
}
if siFrom.Expiration != siTo.Expiration {
m.Extended = append(m.Extended, SectorExtensions{
From: *siFrom,
To: *siTo,
})
}
return nil
}
func (m *MinerSectorChanges) Remove(key uint64, val *typegen.Deferred) error {
si := new(miner.SectorOnChainInfo)
err := si.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Removed = append(m.Removed, *si)
return nil
}
func (sp *StatePredicates) OnMinerSectorChange() DiffMinerActorStateFunc { func (sp *StatePredicates) OnMinerSectorChange() DiffMinerActorStateFunc {
return func(ctx context.Context, oldState, newState *miner.State) (changed bool, user UserData, err error) { return func(ctx context.Context, oldState, newState miner.State) (changed bool, user UserData, err error) {
ctxStore := &contextStore{ sectorChanges, err := miner.DiffSectors(oldState, newState)
ctx: ctx,
cst: sp.cst,
}
sectorChanges := &MinerSectorChanges{
Added: []miner.SectorOnChainInfo{},
Extended: []SectorExtensions{},
Removed: []miner.SectorOnChainInfo{},
}
// no sector changes
if oldState.Sectors.Equals(newState.Sectors) {
return false, nil, nil
}
oldSectors, err := adt.AsArray(ctxStore, oldState.Sectors)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newSectors, err := adt.AsArray(ctxStore, newState.Sectors)
if err != nil {
return false, nil, err
}
if err := DiffAdtArray(oldSectors, newSectors, sectorChanges); err != nil {
return false, nil, err
}
// nothing changed // nothing changed
if len(sectorChanges.Added)+len(sectorChanges.Extended)+len(sectorChanges.Removed) == 0 { if len(sectorChanges.Added)+len(sectorChanges.Extended)+len(sectorChanges.Removed) == 0 {
return false, nil, nil return false, nil, nil
@ -532,73 +352,13 @@ func (sp *StatePredicates) OnMinerSectorChange() DiffMinerActorStateFunc {
} }
} }
type MinerPreCommitChanges struct {
Added []miner.SectorPreCommitOnChainInfo
Removed []miner.SectorPreCommitOnChainInfo
}
func (m *MinerPreCommitChanges) AsKey(key string) (abi.Keyer, error) {
sector, err := abi.ParseUIntKey(key)
if err != nil {
return nil, err
}
return miner.SectorKey(abi.SectorNumber(sector)), nil
}
func (m *MinerPreCommitChanges) Add(key string, val *typegen.Deferred) error {
sp := new(miner.SectorPreCommitOnChainInfo)
err := sp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Added = append(m.Added, *sp)
return nil
}
func (m *MinerPreCommitChanges) Modify(key string, from, to *typegen.Deferred) error {
return nil
}
func (m *MinerPreCommitChanges) Remove(key string, val *typegen.Deferred) error {
sp := new(miner.SectorPreCommitOnChainInfo)
err := sp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Removed = append(m.Removed, *sp)
return nil
}
func (sp *StatePredicates) OnMinerPreCommitChange() DiffMinerActorStateFunc { func (sp *StatePredicates) OnMinerPreCommitChange() DiffMinerActorStateFunc {
return func(ctx context.Context, oldState, newState *miner.State) (changed bool, user UserData, err error) { return func(ctx context.Context, oldState, newState miner.State) (changed bool, user UserData, err error) {
ctxStore := &contextStore{ precommitChanges, err := miner.DiffPreCommits(oldState, newState)
ctx: ctx,
cst: sp.cst,
}
precommitChanges := &MinerPreCommitChanges{
Added: []miner.SectorPreCommitOnChainInfo{},
Removed: []miner.SectorPreCommitOnChainInfo{},
}
if oldState.PreCommittedSectors.Equals(newState.PreCommittedSectors) {
return false, nil, nil
}
oldPrecommits, err := adt.AsMap(ctxStore, oldState.PreCommittedSectors)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newPrecommits, err := adt.AsMap(ctxStore, newState.PreCommittedSectors)
if err != nil {
return false, nil, err
}
if err := DiffAdtMap(oldPrecommits, newPrecommits, precommitChanges); err != nil {
return false, nil, err
}
if len(precommitChanges.Added)+len(precommitChanges.Removed) == 0 { if len(precommitChanges.Added)+len(precommitChanges.Removed) == 0 {
return false, nil, nil return false, nil, nil
} }
@ -608,20 +368,20 @@ func (sp *StatePredicates) OnMinerPreCommitChange() DiffMinerActorStateFunc {
} }
// DiffPaymentChannelStateFunc is function that compares two states for the payment channel // DiffPaymentChannelStateFunc is function that compares two states for the payment channel
type DiffPaymentChannelStateFunc func(ctx context.Context, oldState *paych.State, newState *paych.State) (changed bool, user UserData, err error) type DiffPaymentChannelStateFunc func(ctx context.Context, oldState paych.State, newState paych.State) (changed bool, user UserData, err error)
// OnPaymentChannelActorChanged calls diffPaymentChannelState when the state changes for the the payment channel actor // OnPaymentChannelActorChanged calls diffPaymentChannelState when the state changes for the the payment channel actor
func (sp *StatePredicates) OnPaymentChannelActorChanged(paychAddr address.Address, diffPaymentChannelState DiffPaymentChannelStateFunc) DiffTipSetKeyFunc { func (sp *StatePredicates) OnPaymentChannelActorChanged(paychAddr address.Address, diffPaymentChannelState DiffPaymentChannelStateFunc) DiffTipSetKeyFunc {
return sp.OnActorStateChanged(paychAddr, func(ctx context.Context, oldActorStateHead, newActorStateHead cid.Cid) (changed bool, user UserData, err error) { return sp.OnActorStateChanged(paychAddr, func(ctx context.Context, oldActorState, newActorState *types.Actor) (changed bool, user UserData, err error) {
var oldState paych.State oldState, err := paych.Load(adt.WrapStore(ctx, sp.cst), oldActorState)
if err := sp.cst.Get(ctx, oldActorStateHead, &oldState); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
var newState paych.State newState, err := paych.Load(adt.WrapStore(ctx, sp.cst), newActorState)
if err := sp.cst.Get(ctx, newActorStateHead, &newState); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
return diffPaymentChannelState(ctx, &oldState, &newState) return diffPaymentChannelState(ctx, oldState, newState)
}) })
} }
@ -633,13 +393,23 @@ type PayChToSendChange struct {
// OnToSendAmountChanges monitors changes on the total amount to send from one party to the other on a payment channel // OnToSendAmountChanges monitors changes on the total amount to send from one party to the other on a payment channel
func (sp *StatePredicates) OnToSendAmountChanges() DiffPaymentChannelStateFunc { func (sp *StatePredicates) OnToSendAmountChanges() DiffPaymentChannelStateFunc {
return func(ctx context.Context, oldState *paych.State, newState *paych.State) (changed bool, user UserData, err error) { return func(ctx context.Context, oldState paych.State, newState paych.State) (changed bool, user UserData, err error) {
if oldState.ToSend.Equals(newState.ToSend) { ots, err := oldState.ToSend()
if err != nil {
return false, nil, err
}
nts, err := newState.ToSend()
if err != nil {
return false, nil, err
}
if ots.Equals(nts) {
return false, nil, nil return false, nil, nil
} }
return true, &PayChToSendChange{ return true, &PayChToSendChange{
OldToSend: oldState.ToSend, OldToSend: ots,
NewToSend: newState.ToSend, NewToSend: nts,
}, nil }, nil
} }
} }
@ -660,7 +430,7 @@ type AddressChange struct {
To AddressPair To AddressPair
} }
type DiffInitActorStateFunc func(ctx context.Context, oldState *init_.State, newState *init_.State) (changed bool, user UserData, err error) type DiffInitActorStateFunc func(ctx context.Context, oldState init_.State, newState init_.State) (changed bool, user UserData, err error)
func (i *InitActorAddressChanges) AsKey(key string) (abi.Keyer, error) { func (i *InitActorAddressChanges) AsKey(key string) (abi.Keyer, error) {
addr, err := address.NewFromBytes([]byte(key)) addr, err := address.NewFromBytes([]byte(key))
@ -748,33 +518,73 @@ func (i *InitActorAddressChanges) Remove(key string, val *typegen.Deferred) erro
} }
func (sp *StatePredicates) OnAddressMapChange() DiffInitActorStateFunc { func (sp *StatePredicates) OnAddressMapChange() DiffInitActorStateFunc {
return func(ctx context.Context, oldState, newState *init_.State) (changed bool, user UserData, err error) { return func(ctx context.Context, oldState, newState init_.State) (changed bool, user UserData, err error) {
ctxStore := &contextStore{
ctx: ctx,
cst: sp.cst,
}
addressChanges := &InitActorAddressChanges{ addressChanges := &InitActorAddressChanges{
Added: []AddressPair{}, Added: []AddressPair{},
Modified: []AddressChange{}, Modified: []AddressChange{},
Removed: []AddressPair{}, Removed: []AddressPair{},
} }
if oldState.AddressMap.Equals(newState.AddressMap) { err = oldState.ForEachActor(func(oldId abi.ActorID, oldAddress address.Address) error {
return false, nil, nil oldIdAddress, err := address.NewIDAddress(uint64(oldId))
} if err != nil {
return err
}
newIdAddress, found, err := newState.ResolveAddress(oldAddress)
if err != nil {
return err
}
if !found {
addressChanges.Removed = append(addressChanges.Removed, AddressPair{
ID: oldIdAddress,
PK: oldAddress,
})
}
if oldIdAddress != newIdAddress {
addressChanges.Modified = append(addressChanges.Modified, AddressChange{
From: AddressPair{
ID: oldIdAddress,
PK: oldAddress,
},
To: AddressPair{
ID: newIdAddress,
PK: oldAddress,
},
})
}
return nil
})
oldAddrs, err := adt.AsMap(ctxStore, oldState.AddressMap)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newAddrs, err := adt.AsMap(ctxStore, newState.AddressMap) err = newState.ForEachActor(func(newId abi.ActorID, newAddress address.Address) error {
if err != nil { newIdAddress, err := address.NewIDAddress(uint64(newId))
return false, nil, err if err != nil {
} return err
}
if err := DiffAdtMap(oldAddrs, newAddrs, addressChanges); err != nil { _, found, err := newState.ResolveAddress(newAddress)
if err != nil {
return err
}
if !found {
addressChanges.Added = append(addressChanges.Added, AddressPair{
ID: newIdAddress,
PK: newAddress,
})
}
return nil
})
if err != nil {
return false, nil, err return false, nil, err
} }

View File

@ -4,6 +4,8 @@ import (
"context" "context"
"testing" "testing"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-bitfield"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -16,8 +18,11 @@ import (
"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/go-state-types/crypto"
"github.com/filecoin-project/specs-actors/actors/builtin/market" "github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
tutils "github.com/filecoin-project/specs-actors/support/testing" tutils "github.com/filecoin-project/specs-actors/support/testing"
@ -69,22 +74,22 @@ func TestMarketPredicates(t *testing.T) {
bs := bstore.NewTemporarySync() bs := bstore.NewTemporarySync()
store := adt.WrapStore(ctx, cbornode.NewCborStore(bs)) store := adt.WrapStore(ctx, cbornode.NewCborStore(bs))
oldDeal1 := &market.DealState{ oldDeal1 := &market0.DealState{
SectorStartEpoch: 1, SectorStartEpoch: 1,
LastUpdatedEpoch: 2, LastUpdatedEpoch: 2,
SlashEpoch: 0, SlashEpoch: 0,
} }
oldDeal2 := &market.DealState{ oldDeal2 := &market0.DealState{
SectorStartEpoch: 4, SectorStartEpoch: 4,
LastUpdatedEpoch: 5, LastUpdatedEpoch: 5,
SlashEpoch: 0, SlashEpoch: 0,
} }
oldDeals := map[abi.DealID]*market.DealState{ oldDeals := map[abi.DealID]*market0.DealState{
abi.DealID(1): oldDeal1, abi.DealID(1): oldDeal1,
abi.DealID(2): oldDeal2, abi.DealID(2): oldDeal2,
} }
oldProp1 := &market.DealProposal{ oldProp1 := &market0.DealProposal{
PieceCID: dummyCid, PieceCID: dummyCid,
PieceSize: 0, PieceSize: 0,
VerifiedDeal: false, VerifiedDeal: false,
@ -96,7 +101,7 @@ func TestMarketPredicates(t *testing.T) {
ProviderCollateral: big.Zero(), ProviderCollateral: big.Zero(),
ClientCollateral: big.Zero(), ClientCollateral: big.Zero(),
} }
oldProp2 := &market.DealProposal{ oldProp2 := &market0.DealProposal{
PieceCID: dummyCid, PieceCID: dummyCid,
PieceSize: 0, PieceSize: 0,
VerifiedDeal: false, VerifiedDeal: false,
@ -108,7 +113,7 @@ func TestMarketPredicates(t *testing.T) {
ProviderCollateral: big.Zero(), ProviderCollateral: big.Zero(),
ClientCollateral: big.Zero(), ClientCollateral: big.Zero(),
} }
oldProps := map[abi.DealID]*market.DealProposal{ oldProps := map[abi.DealID]*market0.DealProposal{
abi.DealID(1): oldProp1, abi.DealID(1): oldProp1,
abi.DealID(2): oldProp2, abi.DealID(2): oldProp2,
} }
@ -122,7 +127,7 @@ func TestMarketPredicates(t *testing.T) {
oldStateC := createMarketState(ctx, t, store, oldDeals, oldProps, oldBalances) oldStateC := createMarketState(ctx, t, store, oldDeals, oldProps, oldBalances)
newDeal1 := &market.DealState{ newDeal1 := &market0.DealState{
SectorStartEpoch: 1, SectorStartEpoch: 1,
LastUpdatedEpoch: 3, LastUpdatedEpoch: 3,
SlashEpoch: 0, SlashEpoch: 0,
@ -131,19 +136,19 @@ func TestMarketPredicates(t *testing.T) {
// deal 2 removed // deal 2 removed
// added // added
newDeal3 := &market.DealState{ newDeal3 := &market0.DealState{
SectorStartEpoch: 1, SectorStartEpoch: 1,
LastUpdatedEpoch: 2, LastUpdatedEpoch: 2,
SlashEpoch: 3, SlashEpoch: 3,
} }
newDeals := map[abi.DealID]*market.DealState{ newDeals := map[abi.DealID]*market0.DealState{
abi.DealID(1): newDeal1, abi.DealID(1): newDeal1,
// deal 2 was removed // deal 2 was removed
abi.DealID(3): newDeal3, abi.DealID(3): newDeal3,
} }
// added // added
newProp3 := &market.DealProposal{ newProp3 := &market0.DealProposal{
PieceCID: dummyCid, PieceCID: dummyCid,
PieceSize: 0, PieceSize: 0,
VerifiedDeal: false, VerifiedDeal: false,
@ -155,7 +160,7 @@ func TestMarketPredicates(t *testing.T) {
ProviderCollateral: big.Zero(), ProviderCollateral: big.Zero(),
ClientCollateral: big.Zero(), ClientCollateral: big.Zero(),
} }
newProps := map[abi.DealID]*market.DealProposal{ newProps := map[abi.DealID]*market0.DealProposal{
abi.DealID(1): oldProp1, // 1 was persisted abi.DealID(1): oldProp1, // 1 was persisted
// prop 2 was removed // prop 2 was removed
abi.DealID(3): newProp3, // new abi.DealID(3): newProp3, // new
@ -178,8 +183,8 @@ func TestMarketPredicates(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
api := newMockAPI(bs) api := newMockAPI(bs)
api.setActor(oldState.Key(), &types.Actor{Head: oldStateC}) api.setActor(oldState.Key(), &types.Actor{Code: builtin0.StorageMarketActorCodeID, Head: oldStateC})
api.setActor(newState.Key(), &types.Actor{Head: newStateC}) api.setActor(newState.Key(), &types.Actor{Code: builtin0.StorageMarketActorCodeID, Head: newStateC})
t.Run("deal ID predicate", func(t *testing.T) { t.Run("deal ID predicate", func(t *testing.T) {
preds := NewStatePredicates(api) preds := NewStatePredicates(api)
@ -221,7 +226,7 @@ func TestMarketPredicates(t *testing.T) {
// Test that OnActorStateChanged does not call the callback if the state has not changed // Test that OnActorStateChanged does not call the callback if the state has not changed
mockAddr, err := address.NewFromString("t01") mockAddr, err := address.NewFromString("t01")
require.NoError(t, err) require.NoError(t, err)
actorDiffFn := preds.OnActorStateChanged(mockAddr, func(context.Context, cid.Cid, cid.Cid) (bool, UserData, error) { actorDiffFn := preds.OnActorStateChanged(mockAddr, func(context.Context, *types.Actor, *types.Actor) (bool, UserData, error) {
t.Fatal("No state change so this should not be called") t.Fatal("No state change so this should not be called")
return false, nil, nil return false, nil, nil
}) })
@ -230,11 +235,18 @@ func TestMarketPredicates(t *testing.T) {
require.False(t, changed) require.False(t, changed)
// Test that OnDealStateChanged does not call the callback if the state has not changed // Test that OnDealStateChanged does not call the callback if the state has not changed
diffDealStateFn := preds.OnDealStateChanged(func(context.Context, *adt.Array, *adt.Array) (bool, UserData, error) { diffDealStateFn := preds.OnDealStateChanged(func(context.Context, market.DealStates, market.DealStates) (bool, UserData, error) {
t.Fatal("No state change so this should not be called") t.Fatal("No state change so this should not be called")
return false, nil, nil return false, nil, nil
}) })
marketState := createEmptyMarketState(t, store) marketState0 := createEmptyMarketState(t, store)
marketCid, err := store.Put(ctx, marketState0)
require.NoError(t, err)
marketState, err := market.Load(store, &types.Actor{
Code: builtin0.StorageMarketActorCodeID,
Head: marketCid,
})
require.NoError(t, err)
changed, _, err = diffDealStateFn(ctx, marketState, marketState) changed, _, err = diffDealStateFn(ctx, marketState, marketState)
require.NoError(t, err) require.NoError(t, err)
require.False(t, changed) require.False(t, changed)
@ -252,18 +264,18 @@ func TestMarketPredicates(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.True(t, changed) require.True(t, changed)
changedDeals, ok := valArr.(*MarketDealStateChanges) changedDeals, ok := valArr.(*market.DealStateChanges)
require.True(t, ok) require.True(t, ok)
require.Len(t, changedDeals.Added, 1) require.Len(t, changedDeals.Added, 1)
require.Equal(t, abi.DealID(3), changedDeals.Added[0].ID) require.Equal(t, abi.DealID(3), changedDeals.Added[0].ID)
require.Equal(t, *newDeal3, changedDeals.Added[0].Deal) require.True(t, dealEquality(*newDeal3, changedDeals.Added[0].Deal))
require.Len(t, changedDeals.Removed, 1) require.Len(t, changedDeals.Removed, 1)
require.Len(t, changedDeals.Modified, 1) require.Len(t, changedDeals.Modified, 1)
require.Equal(t, abi.DealID(1), changedDeals.Modified[0].ID) require.Equal(t, abi.DealID(1), changedDeals.Modified[0].ID)
require.Equal(t, newDeal1, changedDeals.Modified[0].To) require.True(t, dealEquality(*newDeal1, *changedDeals.Modified[0].To))
require.Equal(t, oldDeal1, changedDeals.Modified[0].From) require.True(t, dealEquality(*oldDeal1, *changedDeals.Modified[0].From))
require.Equal(t, abi.DealID(2), changedDeals.Removed[0].ID) require.Equal(t, abi.DealID(2), changedDeals.Removed[0].ID)
}) })
@ -279,17 +291,15 @@ func TestMarketPredicates(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.True(t, changed) require.True(t, changed)
changedProps, ok := valArr.(*MarketDealProposalChanges) changedProps, ok := valArr.(*market.DealProposalChanges)
require.True(t, ok) require.True(t, ok)
require.Len(t, changedProps.Added, 1) require.Len(t, changedProps.Added, 1)
require.Equal(t, abi.DealID(3), changedProps.Added[0].ID) require.Equal(t, abi.DealID(3), changedProps.Added[0].ID)
require.Equal(t, *newProp3, changedProps.Added[0].Proposal)
// proposals cannot be modified -- no modified testing // proposals cannot be modified -- no modified testing
require.Len(t, changedProps.Removed, 1) require.Len(t, changedProps.Removed, 1)
require.Equal(t, abi.DealID(2), changedProps.Removed[0].ID) require.Equal(t, abi.DealID(2), changedProps.Removed[0].ID)
require.Equal(t, *oldProp2, changedProps.Removed[0].Proposal)
}) })
t.Run("balances predicate", func(t *testing.T) { t.Run("balances predicate", func(t *testing.T) {
@ -342,7 +352,14 @@ func TestMarketPredicates(t *testing.T) {
t.Fatal("No state change so this should not be called") t.Fatal("No state change so this should not be called")
return false, nil, nil return false, nil, nil
}) })
marketState := createEmptyMarketState(t, store) marketState0 := createEmptyMarketState(t, store)
marketCid, err := store.Put(ctx, marketState0)
require.NoError(t, err)
marketState, err := market.Load(store, &types.Actor{
Code: builtin0.StorageMarketActorCodeID,
Head: marketCid,
})
require.NoError(t, err)
changed, _, err = diffDealBalancesFn(ctx, marketState, marketState) changed, _, err = diffDealBalancesFn(ctx, marketState, marketState)
require.NoError(t, err) require.NoError(t, err)
require.False(t, changed) require.False(t, changed)
@ -362,12 +379,12 @@ func TestMinerSectorChange(t *testing.T) {
} }
owner, worker := nextIDAddrF(), nextIDAddrF() owner, worker := nextIDAddrF(), nextIDAddrF()
si0 := newSectorOnChainInfo(0, tutils.MakeCID("0", &miner.SealedCIDPrefix), big.NewInt(0), abi.ChainEpoch(0), abi.ChainEpoch(10)) si0 := newSectorOnChainInfo(0, tutils.MakeCID("0", &miner0.SealedCIDPrefix), big.NewInt(0), abi.ChainEpoch(0), abi.ChainEpoch(10))
si1 := newSectorOnChainInfo(1, tutils.MakeCID("1", &miner.SealedCIDPrefix), big.NewInt(1), abi.ChainEpoch(1), abi.ChainEpoch(11)) si1 := newSectorOnChainInfo(1, tutils.MakeCID("1", &miner0.SealedCIDPrefix), big.NewInt(1), abi.ChainEpoch(1), abi.ChainEpoch(11))
si2 := newSectorOnChainInfo(2, tutils.MakeCID("2", &miner.SealedCIDPrefix), big.NewInt(2), abi.ChainEpoch(2), abi.ChainEpoch(11)) si2 := newSectorOnChainInfo(2, tutils.MakeCID("2", &miner0.SealedCIDPrefix), big.NewInt(2), abi.ChainEpoch(2), abi.ChainEpoch(11))
oldMinerC := createMinerState(ctx, t, store, owner, worker, []miner.SectorOnChainInfo{si0, si1, si2}) oldMinerC := createMinerState(ctx, t, store, owner, worker, []miner.SectorOnChainInfo{si0, si1, si2})
si3 := newSectorOnChainInfo(3, tutils.MakeCID("3", &miner.SealedCIDPrefix), big.NewInt(3), abi.ChainEpoch(3), abi.ChainEpoch(12)) si3 := newSectorOnChainInfo(3, tutils.MakeCID("3", &miner0.SealedCIDPrefix), big.NewInt(3), abi.ChainEpoch(3), abi.ChainEpoch(12))
// 0 delete // 0 delete
// 1 extend // 1 extend
// 2 same // 2 same
@ -383,8 +400,8 @@ func TestMinerSectorChange(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
api := newMockAPI(bs) api := newMockAPI(bs)
api.setActor(oldState.Key(), &types.Actor{Head: oldMinerC}) api.setActor(oldState.Key(), &types.Actor{Head: oldMinerC, Code: builtin0.StorageMinerActorCodeID})
api.setActor(newState.Key(), &types.Actor{Head: newMinerC}) api.setActor(newState.Key(), &types.Actor{Head: newMinerC, Code: builtin0.StorageMinerActorCodeID})
preds := NewStatePredicates(api) preds := NewStatePredicates(api)
@ -394,7 +411,7 @@ func TestMinerSectorChange(t *testing.T) {
require.True(t, change) require.True(t, change)
require.NotNil(t, val) require.NotNil(t, val)
sectorChanges, ok := val.(*MinerSectorChanges) sectorChanges, ok := val.(*miner.SectorChanges)
require.True(t, ok) require.True(t, ok)
require.Equal(t, len(sectorChanges.Added), 1) require.Equal(t, len(sectorChanges.Added), 1)
@ -418,7 +435,7 @@ func TestMinerSectorChange(t *testing.T) {
require.True(t, change) require.True(t, change)
require.NotNil(t, val) require.NotNil(t, val)
sectorChanges, ok = val.(*MinerSectorChanges) sectorChanges, ok = val.(*miner.SectorChanges)
require.True(t, ok) require.True(t, ok)
require.Equal(t, 1, len(sectorChanges.Added)) require.Equal(t, 1, len(sectorChanges.Added))
@ -450,7 +467,7 @@ type balance struct {
locked abi.TokenAmount locked abi.TokenAmount
} }
func createMarketState(ctx context.Context, t *testing.T, store adt.Store, deals map[abi.DealID]*market.DealState, props map[abi.DealID]*market.DealProposal, balances map[address.Address]balance) cid.Cid { func createMarketState(ctx context.Context, t *testing.T, store adt.Store, deals map[abi.DealID]*market0.DealState, props map[abi.DealID]*market0.DealProposal, balances map[address.Address]balance) cid.Cid {
dealRootCid := createDealAMT(ctx, t, store, deals) dealRootCid := createDealAMT(ctx, t, store, deals)
propRootCid := createProposalAMT(ctx, t, store, props) propRootCid := createProposalAMT(ctx, t, store, props)
balancesCids := createBalanceTable(ctx, t, store, balances) balancesCids := createBalanceTable(ctx, t, store, balances)
@ -465,15 +482,15 @@ func createMarketState(ctx context.Context, t *testing.T, store adt.Store, deals
return stateC return stateC
} }
func createEmptyMarketState(t *testing.T, store adt.Store) *market.State { func createEmptyMarketState(t *testing.T, store adt.Store) *market0.State {
emptyArrayCid, err := adt.MakeEmptyArray(store).Root() emptyArrayCid, err := adt.MakeEmptyArray(store).Root()
require.NoError(t, err) require.NoError(t, err)
emptyMap, err := adt.MakeEmptyMap(store).Root() emptyMap, err := adt.MakeEmptyMap(store).Root()
require.NoError(t, err) require.NoError(t, err)
return market.ConstructState(emptyArrayCid, emptyMap, emptyMap) return market0.ConstructState(emptyArrayCid, emptyMap, emptyMap)
} }
func createDealAMT(ctx context.Context, t *testing.T, store adt.Store, deals map[abi.DealID]*market.DealState) cid.Cid { func createDealAMT(ctx context.Context, t *testing.T, store adt.Store, deals map[abi.DealID]*market0.DealState) cid.Cid {
root := adt.MakeEmptyArray(store) root := adt.MakeEmptyArray(store)
for dealID, dealState := range deals { for dealID, dealState := range deals {
err := root.Set(uint64(dealID), dealState) err := root.Set(uint64(dealID), dealState)
@ -484,7 +501,7 @@ func createDealAMT(ctx context.Context, t *testing.T, store adt.Store, deals map
return rootCid return rootCid
} }
func createProposalAMT(ctx context.Context, t *testing.T, store adt.Store, props map[abi.DealID]*market.DealProposal) cid.Cid { func createProposalAMT(ctx context.Context, t *testing.T, store adt.Store, props map[abi.DealID]*market0.DealProposal) cid.Cid {
root := adt.MakeEmptyArray(store) root := adt.MakeEmptyArray(store)
for dealID, prop := range props { for dealID, prop := range props {
err := root.Set(uint64(dealID), prop) err := root.Set(uint64(dealID), prop)
@ -532,20 +549,20 @@ func createMinerState(ctx context.Context, t *testing.T, store adt.Store, owner,
return stateC return stateC
} }
func createEmptyMinerState(ctx context.Context, t *testing.T, store adt.Store, owner, worker address.Address) *miner.State { func createEmptyMinerState(ctx context.Context, t *testing.T, store adt.Store, owner, worker address.Address) *miner0.State {
emptyArrayCid, err := adt.MakeEmptyArray(store).Root() emptyArrayCid, err := adt.MakeEmptyArray(store).Root()
require.NoError(t, err) require.NoError(t, err)
emptyMap, err := adt.MakeEmptyMap(store).Root() emptyMap, err := adt.MakeEmptyMap(store).Root()
require.NoError(t, err) require.NoError(t, err)
emptyDeadline, err := store.Put(store.Context(), miner.ConstructDeadline(emptyArrayCid)) emptyDeadline, err := store.Put(store.Context(), miner0.ConstructDeadline(emptyArrayCid))
require.NoError(t, err) require.NoError(t, err)
emptyVestingFunds := miner.ConstructVestingFunds() emptyVestingFunds := miner0.ConstructVestingFunds()
emptyVestingFundsCid, err := store.Put(store.Context(), emptyVestingFunds) emptyVestingFundsCid, err := store.Put(store.Context(), emptyVestingFunds)
require.NoError(t, err) require.NoError(t, err)
emptyDeadlines := miner.ConstructDeadlines(emptyDeadline) emptyDeadlines := miner0.ConstructDeadlines(emptyDeadline)
emptyDeadlinesCid, err := store.Put(store.Context(), emptyDeadlines) emptyDeadlinesCid, err := store.Put(store.Context(), emptyDeadlines)
require.NoError(t, err) require.NoError(t, err)
@ -555,7 +572,7 @@ func createEmptyMinerState(ctx context.Context, t *testing.T, store adt.Store, o
emptyBitfieldCid, err := store.Put(store.Context(), emptyBitfield) emptyBitfieldCid, err := store.Put(store.Context(), emptyBitfield)
require.NoError(t, err) require.NoError(t, err)
state, err := miner.ConstructState(minerInfo, 123, emptyBitfieldCid, emptyArrayCid, emptyMap, emptyDeadlinesCid, emptyVestingFundsCid) state, err := miner0.ConstructState(minerInfo, 123, emptyBitfieldCid, emptyArrayCid, emptyMap, emptyDeadlinesCid, emptyVestingFundsCid)
require.NoError(t, err) require.NoError(t, err)
return state return state
@ -564,7 +581,7 @@ func createEmptyMinerState(ctx context.Context, t *testing.T, store adt.Store, o
func createSectorsAMT(ctx context.Context, t *testing.T, store adt.Store, sectors []miner.SectorOnChainInfo) cid.Cid { func createSectorsAMT(ctx context.Context, t *testing.T, store adt.Store, sectors []miner.SectorOnChainInfo) cid.Cid {
root := adt.MakeEmptyArray(store) root := adt.MakeEmptyArray(store)
for _, sector := range sectors { for _, sector := range sectors {
sector := sector sector := (miner0.SectorOnChainInfo)(sector)
err := root.Set(uint64(sector.SectorNumber), &sector) err := root.Set(uint64(sector.SectorNumber), &sector)
require.NoError(t, err) require.NoError(t, err)
} }
@ -597,8 +614,8 @@ const (
) )
// returns a unique SectorPreCommitInfo with each invocation with SectorNumber set to `sectorNo`. // returns a unique SectorPreCommitInfo with each invocation with SectorNumber set to `sectorNo`.
func newSectorPreCommitInfo(sectorNo abi.SectorNumber, sealed cid.Cid, expiration abi.ChainEpoch) *miner.SectorPreCommitInfo { func newSectorPreCommitInfo(sectorNo abi.SectorNumber, sealed cid.Cid, expiration abi.ChainEpoch) *miner0.SectorPreCommitInfo {
return &miner.SectorPreCommitInfo{ return &miner0.SectorPreCommitInfo{
SealProof: abi.RegisteredSealProof_StackedDrg32GiBV1, SealProof: abi.RegisteredSealProof_StackedDrg32GiBV1,
SectorNumber: sectorNo, SectorNumber: sectorNo,
SealedCID: sealed, SealedCID: sealed,
@ -607,3 +624,9 @@ func newSectorPreCommitInfo(sectorNo abi.SectorNumber, sealed cid.Cid, expiratio
Expiration: expiration, Expiration: expiration,
} }
} }
func dealEquality(expected market0.DealState, actual market.DealState) bool {
return expected.LastUpdatedEpoch == actual.LastUpdatedEpoch &&
expected.SectorStartEpoch == actual.SectorStartEpoch &&
expected.SlashEpoch == actual.SlashEpoch
}

View File

@ -146,7 +146,7 @@ func (t *Response) MarshalCBOR(w io.Writer) error {
scratch := make([]byte, 9) scratch := make([]byte, 9)
// t.Status (blocksync.status) (uint64) // t.Status (exchange.status) (uint64)
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Status)); err != nil { if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Status)); err != nil {
return err return err
@ -164,7 +164,7 @@ func (t *Response) MarshalCBOR(w io.Writer) error {
return err return err
} }
// t.Chain ([]*blocksync.BSTipSet) (slice) // t.Chain ([]*exchange.BSTipSet) (slice)
if len(t.Chain) > cbg.MaxLength { if len(t.Chain) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Chain was too long") return xerrors.Errorf("Slice value in field t.Chain was too long")
} }
@ -198,7 +198,7 @@ func (t *Response) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("cbor input had wrong number of fields") return fmt.Errorf("cbor input had wrong number of fields")
} }
// t.Status (blocksync.status) (uint64) // t.Status (exchange.status) (uint64)
{ {
@ -222,7 +222,7 @@ func (t *Response) UnmarshalCBOR(r io.Reader) error {
t.ErrorMessage = string(sval) t.ErrorMessage = string(sval)
} }
// t.Chain ([]*blocksync.BSTipSet) (slice) // t.Chain ([]*exchange.BSTipSet) (slice)
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
if err != nil { if err != nil {
@ -567,7 +567,7 @@ func (t *BSTipSet) MarshalCBOR(w io.Writer) error {
} }
} }
// t.Messages (blocksync.CompactedMessages) (struct) // t.Messages (exchange.CompactedMessages) (struct)
if err := t.Messages.MarshalCBOR(w); err != nil { if err := t.Messages.MarshalCBOR(w); err != nil {
return err return err
} }
@ -621,7 +621,7 @@ func (t *BSTipSet) UnmarshalCBOR(r io.Reader) error {
t.Blocks[i] = &v t.Blocks[i] = &v
} }
// t.Messages (blocksync.CompactedMessages) (struct) // t.Messages (exchange.CompactedMessages) (struct)
{ {

View File

@ -7,6 +7,7 @@ import (
"math/rand" "math/rand"
"time" "time"
"github.com/libp2p/go-libp2p-core/helpers"
"github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
@ -64,7 +65,15 @@ func NewClient(lc fx.Lifecycle, host host.Host, pmgr peermgr.MaybePeerMgr) Clien
// request options without disrupting external calls. In the future the // request options without disrupting external calls. In the future the
// consumers should be forced to use a more standardized service and // consumers should be forced to use a more standardized service and
// adhere to a single API derived from this function. // adhere to a single API derived from this function.
func (c *client) doRequest(ctx context.Context, req *Request, singlePeer *peer.ID) (*validatedResponse, error) { func (c *client) doRequest(
ctx context.Context,
req *Request,
singlePeer *peer.ID,
// In the `GetChainMessages` case, we won't request the headers but we still
// need them to check the integrity of the `CompactedMessages` in the response
// so the tipset blocks need to be provided by the caller.
tipsets []*types.TipSet,
) (*validatedResponse, error) {
// Validate request. // Validate request.
if req.Length == 0 { if req.Length == 0 {
return nil, xerrors.Errorf("invalid request of length 0") return nil, xerrors.Errorf("invalid request of length 0")
@ -115,7 +124,7 @@ func (c *client) doRequest(ctx context.Context, req *Request, singlePeer *peer.I
} }
// Process and validate response. // Process and validate response.
validRes, err := c.processResponse(req, res) validRes, err := c.processResponse(req, res, tipsets)
if err != nil { if err != nil {
log.Warnf("processing peer %s response failed: %s", log.Warnf("processing peer %s response failed: %s",
peer.String(), err) peer.String(), err)
@ -143,7 +152,7 @@ func (c *client) doRequest(ctx context.Context, req *Request, singlePeer *peer.I
// errors. Peer penalization should happen here then, before returning, so // errors. Peer penalization should happen here then, before returning, so
// we can apply the correct penalties depending on the cause of the error. // we can apply the correct penalties depending on the cause of the error.
// FIXME: Add the `peer` as argument once we implement penalties. // FIXME: Add the `peer` as argument once we implement penalties.
func (c *client) processResponse(req *Request, res *Response) (*validatedResponse, error) { func (c *client) processResponse(req *Request, res *Response, tipsets []*types.TipSet) (*validatedResponse, error) {
err := res.statusToError() err := res.statusToError()
if err != nil { if err != nil {
return nil, xerrors.Errorf("status error: %s", err) return nil, xerrors.Errorf("status error: %s", err)
@ -175,6 +184,16 @@ func (c *client) processResponse(req *Request, res *Response) (*validatedRespons
// Check for valid block sets and extract them into `TipSet`s. // Check for valid block sets and extract them into `TipSet`s.
validRes.tipsets = make([]*types.TipSet, resLength) validRes.tipsets = make([]*types.TipSet, resLength)
for i := 0; i < resLength; i++ { for i := 0; i < resLength; i++ {
if res.Chain[i] == nil {
return nil, xerrors.Errorf("response with nil tipset in pos %d", i)
}
for blockIdx, block := range res.Chain[i].Blocks {
if block == nil {
return nil, xerrors.Errorf("tipset with nil block in pos %d", blockIdx)
// FIXME: Maybe we should move this check to `NewTipSet`.
}
}
validRes.tipsets[i], err = types.NewTipSet(res.Chain[i].Blocks) validRes.tipsets[i], err = types.NewTipSet(res.Chain[i].Blocks)
if err != nil { if err != nil {
return nil, xerrors.Errorf("invalid tipset blocks at height (head - %d): %w", i, err) return nil, xerrors.Errorf("invalid tipset blocks at height (head - %d): %w", i, err)
@ -209,31 +228,28 @@ func (c *client) processResponse(req *Request, res *Response) (*validatedRespons
// If the headers were also returned check that the compression // If the headers were also returned check that the compression
// indexes are valid before `toFullTipSets()` is called by the // indexes are valid before `toFullTipSets()` is called by the
// consumer. // consumer.
for tipsetIdx := 0; tipsetIdx < resLength; tipsetIdx++ { err := c.validateCompressedIndices(res.Chain)
msgs := res.Chain[tipsetIdx].Messages if err != nil {
blocksNum := len(res.Chain[tipsetIdx].Blocks) return nil, err
if len(msgs.BlsIncludes) != blocksNum { }
return nil, xerrors.Errorf("BlsIncludes (%d) does not match number of blocks (%d)", } else {
len(msgs.BlsIncludes), blocksNum) // If we didn't request the headers they should have been provided
} // by the caller.
if len(msgs.SecpkIncludes) != blocksNum { if len(tipsets) < len(res.Chain) {
return nil, xerrors.Errorf("SecpkIncludes (%d) does not match number of blocks (%d)", return nil, xerrors.Errorf("not enought tipsets provided for message response validation, needed %d, have %d", len(res.Chain), len(tipsets))
len(msgs.SecpkIncludes), blocksNum) }
} chain := make([]*BSTipSet, 0, resLength)
for blockIdx := 0; blockIdx < blocksNum; blockIdx++ { for i, resChain := range res.Chain {
for _, mi := range msgs.BlsIncludes[blockIdx] { next := &BSTipSet{
if int(mi) >= len(msgs.Bls) { Blocks: tipsets[i].Blocks(),
return nil, xerrors.Errorf("index in BlsIncludes (%d) exceeds number of messages (%d)", Messages: resChain.Messages,
mi, len(msgs.Bls))
}
}
for _, mi := range msgs.SecpkIncludes[blockIdx] {
if int(mi) >= len(msgs.Secpk) {
return nil, xerrors.Errorf("index in SecpkIncludes (%d) exceeds number of messages (%d)",
mi, len(msgs.Secpk))
}
}
} }
chain = append(chain, next)
}
err := c.validateCompressedIndices(chain)
if err != nil {
return nil, err
} }
} }
} }
@ -241,6 +257,42 @@ func (c *client) processResponse(req *Request, res *Response) (*validatedRespons
return validRes, nil return validRes, nil
} }
func (c *client) validateCompressedIndices(chain []*BSTipSet) error {
resLength := len(chain)
for tipsetIdx := 0; tipsetIdx < resLength; tipsetIdx++ {
msgs := chain[tipsetIdx].Messages
blocksNum := len(chain[tipsetIdx].Blocks)
if len(msgs.BlsIncludes) != blocksNum {
return xerrors.Errorf("BlsIncludes (%d) does not match number of blocks (%d)",
len(msgs.BlsIncludes), blocksNum)
}
if len(msgs.SecpkIncludes) != blocksNum {
return xerrors.Errorf("SecpkIncludes (%d) does not match number of blocks (%d)",
len(msgs.SecpkIncludes), blocksNum)
}
for blockIdx := 0; blockIdx < blocksNum; blockIdx++ {
for _, mi := range msgs.BlsIncludes[blockIdx] {
if int(mi) >= len(msgs.Bls) {
return xerrors.Errorf("index in BlsIncludes (%d) exceeds number of messages (%d)",
mi, len(msgs.Bls))
}
}
for _, mi := range msgs.SecpkIncludes[blockIdx] {
if int(mi) >= len(msgs.Secpk) {
return xerrors.Errorf("index in SecpkIncludes (%d) exceeds number of messages (%d)",
mi, len(msgs.Secpk))
}
}
}
}
return nil
}
// GetBlocks implements Client.GetBlocks(). Refer to the godocs there. // GetBlocks implements Client.GetBlocks(). Refer to the godocs there.
func (c *client) GetBlocks(ctx context.Context, tsk types.TipSetKey, count int) ([]*types.TipSet, error) { func (c *client) GetBlocks(ctx context.Context, tsk types.TipSetKey, count int) ([]*types.TipSet, error) {
ctx, span := trace.StartSpan(ctx, "bsync.GetBlocks") ctx, span := trace.StartSpan(ctx, "bsync.GetBlocks")
@ -258,7 +310,7 @@ func (c *client) GetBlocks(ctx context.Context, tsk types.TipSetKey, count int)
Options: Headers, Options: Headers,
} }
validRes, err := c.doRequest(ctx, req, nil) validRes, err := c.doRequest(ctx, req, nil, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -276,7 +328,7 @@ func (c *client) GetFullTipSet(ctx context.Context, peer peer.ID, tsk types.TipS
Options: Headers | Messages, Options: Headers | Messages,
} }
validRes, err := c.doRequest(ctx, req, &peer) validRes, err := c.doRequest(ctx, req, &peer, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -287,7 +339,10 @@ func (c *client) GetFullTipSet(ctx context.Context, peer peer.ID, tsk types.TipS
} }
// GetChainMessages implements Client.GetChainMessages(). Refer to the godocs there. // GetChainMessages implements Client.GetChainMessages(). Refer to the godocs there.
func (c *client) GetChainMessages(ctx context.Context, head *types.TipSet, length uint64) ([]*CompactedMessages, error) { func (c *client) GetChainMessages(ctx context.Context, tipsets []*types.TipSet) ([]*CompactedMessages, error) {
head := tipsets[0]
length := uint64(len(tipsets))
ctx, span := trace.StartSpan(ctx, "GetChainMessages") ctx, span := trace.StartSpan(ctx, "GetChainMessages")
if span.IsRecordingEvents() { if span.IsRecordingEvents() {
span.AddAttributes( span.AddAttributes(
@ -303,7 +358,7 @@ func (c *client) GetChainMessages(ctx context.Context, head *types.TipSet, lengt
Options: Messages, Options: Messages,
} }
validRes, err := c.doRequest(ctx, req, nil) validRes, err := c.doRequest(ctx, req, nil, tipsets)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -357,6 +412,12 @@ func (c *client) sendRequestToPeer(ctx context.Context, peer peer.ID, req *Reque
return nil, xerrors.Errorf("failed to open stream to peer: %w", err) return nil, xerrors.Errorf("failed to open stream to peer: %w", err)
} }
defer func() {
// Note: this will become just stream.Close once we've completed the go-libp2p migration to
// go-libp2p-core 0.7.0
go helpers.FullClose(stream) //nolint:errcheck
}()
// Write request. // Write request.
_ = stream.SetWriteDeadline(time.Now().Add(WriteReqDeadline)) _ = stream.SetWriteDeadline(time.Now().Add(WriteReqDeadline))
if err := cborutil.WriteCborRPC(stream, req); err != nil { if err := cborutil.WriteCborRPC(stream, req); err != nil {

View File

@ -32,10 +32,9 @@ type Client interface {
// or less. // or less.
GetBlocks(ctx context.Context, tsk types.TipSetKey, count int) ([]*types.TipSet, error) GetBlocks(ctx context.Context, tsk types.TipSetKey, count int) ([]*types.TipSet, error)
// GetChainMessages fetches messages from the network, from the provided // GetChainMessages fetches messages from the network, starting from the first provided tipset
// tipset *backwards*, returning the messages from as many tipsets as the // and returning messages from as many tipsets as requested or less.
// count parameter, or less. GetChainMessages(ctx context.Context, tipsets []*types.TipSet) ([]*CompactedMessages, error)
GetChainMessages(ctx context.Context, head *types.TipSet, length uint64) ([]*CompactedMessages, error)
// GetFullTipSet fetches a full tipset from a given peer. If successful, // GetFullTipSet fetches a full tipset from a given peer. If successful,
// the fetched object contains block headers and all messages in full form. // the fetched object contains block headers and all messages in full form.

View File

@ -40,7 +40,7 @@ const (
WriteReqDeadline = 5 * time.Second WriteReqDeadline = 5 * time.Second
ReadResDeadline = WriteReqDeadline ReadResDeadline = WriteReqDeadline
ReadResMinSpeed = 50 << 10 ReadResMinSpeed = 50 << 10
ShufflePeersPrefix = 5 ShufflePeersPrefix = 16
WriteResDeadline = 60 * time.Second WriteResDeadline = 60 * time.Second
) )
@ -139,6 +139,8 @@ func (res *Response) statusToError() error {
// FIXME: Rename. // FIXME: Rename.
type BSTipSet struct { type BSTipSet struct {
// List of blocks belonging to a single tipset to which the
// `CompactedMessages` are linked.
Blocks []*types.BlockHeader Blocks []*types.BlockHeader
Messages *CompactedMessages Messages *CompactedMessages
} }

View File

@ -15,6 +15,7 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/helpers"
inet "github.com/libp2p/go-libp2p-core/network" inet "github.com/libp2p/go-libp2p-core/network"
) )
@ -39,7 +40,9 @@ func (s *server) HandleStream(stream inet.Stream) {
ctx, span := trace.StartSpan(context.Background(), "chainxchg.HandleStream") ctx, span := trace.StartSpan(context.Background(), "chainxchg.HandleStream")
defer span.End() defer span.End()
defer stream.Close() //nolint:errcheck // Note: this will become just stream.Close once we've completed the go-libp2p migration to
// go-libp2p-core 0.7.0
defer helpers.FullClose(stream) //nolint:errcheck
var req Request var req Request
if err := cborutil.ReadCborRPC(bufio.NewReader(stream), &req); err != nil { if err := cborutil.ReadCborRPC(bufio.NewReader(stream), &req); err != nil {

View File

@ -14,7 +14,6 @@ import (
"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/go-state-types/crypto"
saminer "github.com/filecoin-project/specs-actors/actors/builtin/miner"
block "github.com/ipfs/go-block-format" block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-blockservice" "github.com/ipfs/go-blockservice"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@ -28,6 +27,7 @@ import (
"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/policy"
"github.com/filecoin-project/lotus/chain/beacon" "github.com/filecoin-project/lotus/chain/beacon"
genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis" genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/stmgr"
@ -121,9 +121,8 @@ var DefaultRemainderAccountActor = genesis.Actor{
} }
func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) { func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
saminer.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{ // TODO: we really shouldn't modify a global variable here.
abi.RegisteredSealProof_StackedDrg2KiBV1: {}, policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
}
mr := repo.NewMemory(nil) mr := repo.NewMemory(nil)
lr, err := mr.Lock(repo.StorageMiner) lr, err := mr.Lock(repo.StorageMiner)
@ -489,13 +488,16 @@ func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, vrfticke
// ResyncBankerNonce is used for dealing with messages made when // ResyncBankerNonce is used for dealing with messages made when
// simulating forks // simulating forks
func (cg *ChainGen) ResyncBankerNonce(ts *types.TipSet) error { func (cg *ChainGen) ResyncBankerNonce(ts *types.TipSet) error {
var act types.Actor st, err := cg.sm.ParentState(ts)
err := cg.sm.WithParentState(ts, cg.sm.WithActor(cg.banker, stmgr.GetActor(&act))) if err != nil {
return err
}
act, err := st.GetActor(cg.banker)
if err != nil { if err != nil {
return err return err
} }
cg.bankerNonce = act.Nonce cg.bankerNonce = act.Nonce
return nil return nil
} }

View File

@ -4,21 +4,16 @@ import (
"testing" "testing"
"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/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/lotus/chain/actors/policy"
_ "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"
) )
func init() { func init() {
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{ policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
abi.RegisteredSealProof_StackedDrg2KiBV1: {}, policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
} policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
power.ConsensusMinerMinPower = big.NewInt(2048)
verifreg.MinVerifiedDealSize = big.NewInt(256)
} }
func testGeneration(t testing.TB, n int, msgs int, sectors int) { func testGeneration(t testing.TB, n int, msgs int, sectors int) {

View File

@ -6,8 +6,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/filecoin-project/go-state-types/network"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
@ -19,13 +17,14 @@ import (
"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/go-state-types/crypto"
"github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/account" account0 "github.com/filecoin-project/specs-actors/actors/builtin/account"
"github.com/filecoin-project/specs-actors/actors/builtin/multisig" multisig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg" verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/util/adt" adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -116,7 +115,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
return nil, nil, xerrors.Errorf("putting empty object: %w", err) return nil, nil, xerrors.Errorf("putting empty object: %w", err)
} }
state, err := state.NewStateTree(cst) state, err := state.NewStateTree(cst, builtin.Version0)
if err != nil { if err != nil {
return nil, nil, xerrors.Errorf("making new state tree: %w", err) return nil, nil, xerrors.Errorf("making new state tree: %w", err)
} }
@ -127,7 +126,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
if err != nil { if err != nil {
return nil, nil, xerrors.Errorf("setup init actor: %w", err) return nil, nil, xerrors.Errorf("setup init actor: %w", err)
} }
if err := state.SetActor(builtin.SystemActorAddr, sysact); err != nil { if err := state.SetActor(builtin0.SystemActorAddr, sysact); err != nil {
return nil, nil, xerrors.Errorf("set init actor: %w", err) return nil, nil, xerrors.Errorf("set init actor: %w", err)
} }
@ -137,7 +136,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
if err != nil { if err != nil {
return nil, nil, xerrors.Errorf("setup init actor: %w", err) return nil, nil, xerrors.Errorf("setup init actor: %w", err)
} }
if err := state.SetActor(builtin.InitActorAddr, initact); err != nil { if err := state.SetActor(builtin0.InitActorAddr, initact); err != nil {
return nil, nil, xerrors.Errorf("set init actor: %w", err) return nil, nil, xerrors.Errorf("set init actor: %w", err)
} }
@ -148,7 +147,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
return nil, nil, xerrors.Errorf("setup init actor: %w", err) return nil, nil, xerrors.Errorf("setup init actor: %w", err)
} }
err = state.SetActor(builtin.RewardActorAddr, rewact) err = state.SetActor(builtin0.RewardActorAddr, rewact)
if err != nil { if err != nil {
return nil, nil, xerrors.Errorf("set network account actor: %w", err) return nil, nil, xerrors.Errorf("set network account actor: %w", err)
} }
@ -158,7 +157,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
if err != nil { if err != nil {
return nil, nil, xerrors.Errorf("setup cron actor: %w", err) return nil, nil, xerrors.Errorf("setup cron actor: %w", err)
} }
if err := state.SetActor(builtin.CronActorAddr, cronact); err != nil { if err := state.SetActor(builtin0.CronActorAddr, cronact); err != nil {
return nil, nil, xerrors.Errorf("set cron actor: %w", err) return nil, nil, xerrors.Errorf("set cron actor: %w", err)
} }
@ -167,7 +166,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
if err != nil { if err != nil {
return nil, nil, xerrors.Errorf("setup storage market actor: %w", err) return nil, nil, xerrors.Errorf("setup storage market actor: %w", err)
} }
if err := state.SetActor(builtin.StoragePowerActorAddr, spact); err != nil { if err := state.SetActor(builtin0.StoragePowerActorAddr, spact); err != nil {
return nil, nil, xerrors.Errorf("set storage market actor: %w", err) return nil, nil, xerrors.Errorf("set storage market actor: %w", err)
} }
@ -176,7 +175,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
if err != nil { if err != nil {
return nil, nil, xerrors.Errorf("setup storage market actor: %w", err) return nil, nil, xerrors.Errorf("setup storage market actor: %w", err)
} }
if err := state.SetActor(builtin.StorageMarketActorAddr, marketact); err != nil { if err := state.SetActor(builtin0.StorageMarketActorAddr, marketact); err != nil {
return nil, nil, xerrors.Errorf("set market actor: %w", err) return nil, nil, xerrors.Errorf("set market actor: %w", err)
} }
@ -185,20 +184,20 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
if err != nil { if err != nil {
return nil, nil, xerrors.Errorf("setup storage market actor: %w", err) return nil, nil, xerrors.Errorf("setup storage market actor: %w", err)
} }
if err := state.SetActor(builtin.VerifiedRegistryActorAddr, verifact); err != nil { if err := state.SetActor(builtin0.VerifiedRegistryActorAddr, verifact); err != nil {
return nil, nil, xerrors.Errorf("set market actor: %w", err) return nil, nil, xerrors.Errorf("set market actor: %w", err)
} }
burntRoot, err := cst.Put(ctx, &account.State{ burntRoot, err := cst.Put(ctx, &account0.State{
Address: builtin.BurntFundsActorAddr, Address: builtin0.BurntFundsActorAddr,
}) })
if err != nil { if err != nil {
return nil, nil, xerrors.Errorf("failed to setup burnt funds actor state: %w", err) return nil, nil, xerrors.Errorf("failed to setup burnt funds actor state: %w", err)
} }
// Setup burnt-funds // Setup burnt-funds
err = state.SetActor(builtin.BurntFundsActorAddr, &types.Actor{ err = state.SetActor(builtin0.BurntFundsActorAddr, &types.Actor{
Code: builtin.AccountActorCodeID, Code: builtin0.AccountActorCodeID,
Balance: types.NewInt(0), Balance: types.NewInt(0),
Head: burntRoot, Head: burntRoot,
}) })
@ -263,13 +262,13 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
return nil, nil, err return nil, nil, err
} }
verifierState, err := cst.Put(ctx, &account.State{Address: verifierAd}) verifierState, err := cst.Put(ctx, &account0.State{Address: verifierAd})
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
err = state.SetActor(verifierId, &types.Actor{ err = state.SetActor(verifierId, &types.Actor{
Code: builtin.AccountActorCodeID, Code: builtin0.AccountActorCodeID,
Balance: types.NewInt(0), Balance: types.NewInt(0),
Head: verifierState, Head: verifierState,
}) })
@ -316,7 +315,7 @@ func createAccountActor(ctx context.Context, cst cbor.IpldStore, state *state.St
if err := json.Unmarshal(info.Meta, &ainfo); err != nil { if err := json.Unmarshal(info.Meta, &ainfo); err != nil {
return xerrors.Errorf("unmarshaling account meta: %w", err) return xerrors.Errorf("unmarshaling account meta: %w", err)
} }
st, err := cst.Put(ctx, &account.State{Address: ainfo.Owner}) st, err := cst.Put(ctx, &account0.State{Address: ainfo.Owner})
if err != nil { if err != nil {
return err return err
} }
@ -327,7 +326,7 @@ func createAccountActor(ctx context.Context, cst cbor.IpldStore, state *state.St
} }
err = state.SetActor(ida, &types.Actor{ err = state.SetActor(ida, &types.Actor{
Code: builtin.AccountActorCodeID, Code: builtin0.AccountActorCodeID,
Balance: info.Balance, Balance: info.Balance,
Head: st, Head: st,
}) })
@ -345,7 +344,7 @@ func createMultisigAccount(ctx context.Context, bs bstore.Blockstore, cst cbor.I
if err := json.Unmarshal(info.Meta, &ainfo); err != nil { if err := json.Unmarshal(info.Meta, &ainfo); err != nil {
return xerrors.Errorf("unmarshaling account meta: %w", err) return xerrors.Errorf("unmarshaling account meta: %w", err)
} }
pending, err := adt.MakeEmptyMap(adt.WrapStore(ctx, cst)).Root() pending, err := adt0.MakeEmptyMap(adt0.WrapStore(ctx, cst)).Root()
if err != nil { if err != nil {
return xerrors.Errorf("failed to create empty map: %v", err) return xerrors.Errorf("failed to create empty map: %v", err)
} }
@ -365,12 +364,12 @@ func createMultisigAccount(ctx context.Context, bs bstore.Blockstore, cst cbor.I
continue continue
} }
st, err := cst.Put(ctx, &account.State{Address: e}) st, err := cst.Put(ctx, &account0.State{Address: e})
if err != nil { if err != nil {
return err return err
} }
err = state.SetActor(idAddress, &types.Actor{ err = state.SetActor(idAddress, &types.Actor{
Code: builtin.AccountActorCodeID, Code: builtin0.AccountActorCodeID,
Balance: types.NewInt(0), Balance: types.NewInt(0),
Head: st, Head: st,
}) })
@ -380,7 +379,7 @@ func createMultisigAccount(ctx context.Context, bs bstore.Blockstore, cst cbor.I
signers = append(signers, idAddress) signers = append(signers, idAddress)
} }
st, err := cst.Put(ctx, &multisig.State{ st, err := cst.Put(ctx, &multisig0.State{
Signers: signers, Signers: signers,
NumApprovalsThreshold: uint64(ainfo.Threshold), NumApprovalsThreshold: uint64(ainfo.Threshold),
StartEpoch: abi.ChainEpoch(ainfo.VestingStart), StartEpoch: abi.ChainEpoch(ainfo.VestingStart),
@ -392,7 +391,7 @@ func createMultisigAccount(ctx context.Context, bs bstore.Blockstore, cst cbor.I
return err return err
} }
err = state.SetActor(ida, &types.Actor{ err = state.SetActor(ida, &types.Actor{
Code: builtin.MultisigActorCodeID, Code: builtin0.MultisigActorCodeID,
Balance: info.Balance, Balance: info.Balance,
Head: st, Head: st,
}) })
@ -406,10 +405,6 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
verifNeeds := make(map[address.Address]abi.PaddedPieceSize) verifNeeds := make(map[address.Address]abi.PaddedPieceSize)
var sum abi.PaddedPieceSize var sum abi.PaddedPieceSize
nwv := func(context.Context, abi.ChainEpoch) network.Version {
return build.NewestNetworkVersion
}
vmopt := vm.VMOpts{ vmopt := vm.VMOpts{
StateBase: stateroot, StateBase: stateroot,
Epoch: 0, Epoch: 0,
@ -417,10 +412,10 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
Bstore: cs.Blockstore(), Bstore: cs.Blockstore(),
Syscalls: mkFakedSigSyscalls(cs.VMSys()), Syscalls: mkFakedSigSyscalls(cs.VMSys()),
CircSupplyCalc: nil, CircSupplyCalc: nil,
NtwkVersion: nwv, NtwkVersion: genesisNetworkVersion,
BaseFee: types.NewInt(0), BaseFee: types.NewInt(0),
} }
vm, err := vm.NewVM(&vmopt) vm, err := vm.NewVM(ctx, &vmopt)
if err != nil { if err != nil {
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err) return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
} }
@ -447,7 +442,7 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
return cid.Undef, err return cid.Undef, err
} }
_, err = doExecValue(ctx, vm, builtin.VerifiedRegistryActorAddr, verifregRoot, types.NewInt(0), builtin.MethodsVerifiedRegistry.AddVerifier, mustEnc(&verifreg.AddVerifierParams{ _, err = doExecValue(ctx, vm, builtin0.VerifiedRegistryActorAddr, verifregRoot, types.NewInt(0), builtin0.MethodsVerifiedRegistry.AddVerifier, mustEnc(&verifreg0.AddVerifierParams{
Address: verifier, Address: verifier,
Allowance: abi.NewStoragePower(int64(sum)), // eh, close enough Allowance: abi.NewStoragePower(int64(sum)), // eh, close enough
@ -458,7 +453,7 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
} }
for c, amt := range verifNeeds { for c, amt := range verifNeeds {
_, err := doExecValue(ctx, vm, builtin.VerifiedRegistryActorAddr, verifier, types.NewInt(0), builtin.MethodsVerifiedRegistry.AddVerifiedClient, mustEnc(&verifreg.AddVerifiedClientParams{ _, err := doExecValue(ctx, vm, builtin0.VerifiedRegistryActorAddr, verifier, types.NewInt(0), builtin0.MethodsVerifiedRegistry.AddVerifiedClient, mustEnc(&verifreg0.AddVerifiedClientParams{
Address: c, Address: c,
Allowance: abi.NewStoragePower(int64(amt)), Allowance: abi.NewStoragePower(int64(amt)),
})) }))
@ -500,8 +495,8 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys vm.SyscallB
return nil, xerrors.Errorf("setup miners failed: %w", err) return nil, xerrors.Errorf("setup miners failed: %w", err)
} }
store := adt.WrapStore(ctx, cbor.NewCborStore(bs)) store := adt0.WrapStore(ctx, cbor.NewCborStore(bs))
emptyroot, err := adt.MakeEmptyArray(store).Root() emptyroot, err := adt0.MakeEmptyArray(store).Root()
if err != nil { if err != nil {
return nil, xerrors.Errorf("amt build failed: %w", err) return nil, xerrors.Errorf("amt build failed: %w", err)
} }
@ -549,7 +544,7 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys vm.SyscallB
} }
b := &types.BlockHeader{ b := &types.BlockHeader{
Miner: builtin.SystemActorAddr, Miner: builtin0.SystemActorAddr,
Ticket: genesisticket, Ticket: genesisticket,
Parents: []cid.Cid{filecoinGenesisCid}, Parents: []cid.Cid{filecoinGenesisCid},
Height: 0, Height: 0,

View File

@ -6,11 +6,13 @@ import (
"fmt" "fmt"
"math/rand" "math/rand"
"github.com/filecoin-project/lotus/build" market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
@ -23,12 +25,12 @@ import (
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/power" reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/filecoin-project/specs-actors/actors/runtime" "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
@ -65,10 +67,6 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
return big.Zero(), nil return big.Zero(), nil
} }
nwv := func(context.Context, abi.ChainEpoch) network.Version {
return build.NewestNetworkVersion
}
vmopt := &vm.VMOpts{ vmopt := &vm.VMOpts{
StateBase: sroot, StateBase: sroot,
Epoch: 0, Epoch: 0,
@ -76,11 +74,11 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
Bstore: cs.Blockstore(), Bstore: cs.Blockstore(),
Syscalls: mkFakedSigSyscalls(cs.VMSys()), Syscalls: mkFakedSigSyscalls(cs.VMSys()),
CircSupplyCalc: csc, CircSupplyCalc: csc,
NtwkVersion: nwv, NtwkVersion: genesisNetworkVersion,
BaseFee: types.NewInt(0), BaseFee: types.NewInt(0),
} }
vm, err := vm.NewVM(vmopt) vm, err := vm.NewVM(ctx, vmopt)
if err != nil { if err != nil {
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err) return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
} }
@ -108,7 +106,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
} }
{ {
constructorParams := &power.CreateMinerParams{ constructorParams := &power0.CreateMinerParams{
Owner: m.Worker, Owner: m.Worker,
Worker: m.Worker, Worker: m.Worker,
Peer: []byte(m.PeerId), Peer: []byte(m.PeerId),
@ -116,12 +114,12 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
} }
params := mustEnc(constructorParams) params := mustEnc(constructorParams)
rval, err := doExecValue(ctx, vm, builtin.StoragePowerActorAddr, m.Owner, m.PowerBalance, builtin.MethodsPower.CreateMiner, params) rval, err := doExecValue(ctx, vm, power.Address, m.Owner, m.PowerBalance, builtin.MethodsPower.CreateMiner, params)
if err != nil { if err != nil {
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err) return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
} }
var ma power.CreateMinerReturn var ma power0.CreateMinerReturn
if err := ma.UnmarshalCBOR(bytes.NewReader(rval)); err != nil { if err := ma.UnmarshalCBOR(bytes.NewReader(rval)); err != nil {
return cid.Undef, xerrors.Errorf("unmarshaling CreateMinerReturn: %w", err) return cid.Undef, xerrors.Errorf("unmarshaling CreateMinerReturn: %w", err)
} }
@ -132,9 +130,10 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
} }
minerInfos[i].maddr = ma.IDAddress minerInfos[i].maddr = ma.IDAddress
err = vm.MutateState(ctx, minerInfos[i].maddr, func(cst cbor.IpldStore, st *miner.State) error { // TODO: ActorUpgrade
maxPeriods := miner.MaxSectorExpirationExtension / miner.WPoStProvingPeriod err = vm.MutateState(ctx, minerInfos[i].maddr, func(cst cbor.IpldStore, st *miner0.State) error {
minerInfos[i].presealExp = (maxPeriods-1)*miner.WPoStProvingPeriod + st.ProvingPeriodStart - 1 maxPeriods := miner0.MaxSectorExpirationExtension / miner0.WPoStProvingPeriod
minerInfos[i].presealExp = (maxPeriods-1)*miner0.WPoStProvingPeriod + st.ProvingPeriodStart - 1
return nil return nil
}) })
@ -147,7 +146,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
if m.MarketBalance.GreaterThan(big.Zero()) { if m.MarketBalance.GreaterThan(big.Zero()) {
params := mustEnc(&minerInfos[i].maddr) params := mustEnc(&minerInfos[i].maddr)
_, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, m.MarketBalance, builtin.MethodsMarket.AddBalance, params) _, err := doExecValue(ctx, vm, market.Address, m.Worker, m.MarketBalance, builtin.MethodsMarket.AddBalance, params)
if err != nil { if err != nil {
return cid.Undef, xerrors.Errorf("failed to create genesis miner (add balance): %w", err) return cid.Undef, xerrors.Errorf("failed to create genesis miner (add balance): %w", err)
} }
@ -159,7 +158,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
publish := func(params *market.PublishStorageDealsParams) error { publish := func(params *market.PublishStorageDealsParams) error {
fmt.Printf("publishing %d storage deals on miner %s with worker %s\n", len(params.Deals), params.Deals[0].Proposal.Provider, m.Worker) fmt.Printf("publishing %d storage deals on miner %s with worker %s\n", len(params.Deals), params.Deals[0].Proposal.Provider, m.Worker)
ret, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, big.Zero(), builtin.MethodsMarket.PublishStorageDeals, mustEnc(params)) ret, err := doExecValue(ctx, vm, market.Address, m.Worker, big.Zero(), builtin.MethodsMarket.PublishStorageDeals, mustEnc(params))
if err != nil { if err != nil {
return xerrors.Errorf("failed to create genesis miner (publish deals): %w", err) return xerrors.Errorf("failed to create genesis miner (publish deals): %w", err)
} }
@ -210,13 +209,13 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
return cid.Undef, xerrors.Errorf("getting deal weight: %w", err) return cid.Undef, xerrors.Errorf("getting deal weight: %w", err)
} }
sectorWeight := miner.QAPowerForWeight(m.SectorSize, minerInfos[i].presealExp, dweight.DealWeight, dweight.VerifiedDealWeight) sectorWeight := miner0.QAPowerForWeight(m.SectorSize, minerInfos[i].presealExp, dweight.DealWeight, dweight.VerifiedDealWeight)
qaPow = types.BigAdd(qaPow, sectorWeight) qaPow = types.BigAdd(qaPow, sectorWeight)
} }
} }
err = vm.MutateState(ctx, builtin.StoragePowerActorAddr, func(cst cbor.IpldStore, st *power.State) error { err = vm.MutateState(ctx, power.Address, func(cst cbor.IpldStore, st *power0.State) error {
st.TotalQualityAdjPower = qaPow st.TotalQualityAdjPower = qaPow
st.TotalRawBytePower = rawPow st.TotalRawBytePower = rawPow
@ -228,8 +227,8 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
return cid.Undef, xerrors.Errorf("mutating state: %w", err) return cid.Undef, xerrors.Errorf("mutating state: %w", err)
} }
err = vm.MutateState(ctx, builtin.RewardActorAddr, func(sct cbor.IpldStore, st *reward.State) error { err = vm.MutateState(ctx, reward.Address, func(sct cbor.IpldStore, st *reward0.State) error {
*st = *reward.ConstructState(qaPow) *st = *reward0.ConstructState(qaPow)
return nil return nil
}) })
if err != nil { if err != nil {
@ -255,10 +254,10 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
return cid.Undef, xerrors.Errorf("getting deal weight: %w", err) return cid.Undef, xerrors.Errorf("getting deal weight: %w", err)
} }
sectorWeight := miner.QAPowerForWeight(m.SectorSize, minerInfos[i].presealExp, dweight.DealWeight, dweight.VerifiedDealWeight) sectorWeight := miner0.QAPowerForWeight(m.SectorSize, minerInfos[i].presealExp, dweight.DealWeight, dweight.VerifiedDealWeight)
// we've added fake power for this sector above, remove it now // we've added fake power for this sector above, remove it now
err = vm.MutateState(ctx, builtin.StoragePowerActorAddr, func(cst cbor.IpldStore, st *power.State) error { err = vm.MutateState(ctx, power.Address, func(cst cbor.IpldStore, st *power0.State) error {
st.TotalQualityAdjPower = types.BigSub(st.TotalQualityAdjPower, sectorWeight) //nolint:scopelint st.TotalQualityAdjPower = types.BigSub(st.TotalQualityAdjPower, sectorWeight) //nolint:scopelint
st.TotalRawBytePower = types.BigSub(st.TotalRawBytePower, types.NewInt(uint64(m.SectorSize))) st.TotalRawBytePower = types.BigSub(st.TotalRawBytePower, types.NewInt(uint64(m.SectorSize)))
return nil return nil
@ -277,9 +276,9 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
return cid.Undef, xerrors.Errorf("getting current total power: %w", err) return cid.Undef, xerrors.Errorf("getting current total power: %w", err)
} }
pcd := miner.PreCommitDepositForPower(epochReward.ThisEpochRewardSmoothed, tpow.QualityAdjPowerSmoothed, sectorWeight) pcd := miner0.PreCommitDepositForPower(epochReward.ThisEpochRewardSmoothed, tpow.QualityAdjPowerSmoothed, sectorWeight)
pledge := miner.InitialPledgeForPower( pledge := miner0.InitialPledgeForPower(
sectorWeight, sectorWeight,
epochReward.ThisEpochBaselinePower, epochReward.ThisEpochBaselinePower,
tpow.PledgeCollateral, tpow.PledgeCollateral,
@ -301,7 +300,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
Sectors: []abi.SectorNumber{preseal.SectorID}, Sectors: []abi.SectorNumber{preseal.SectorID},
} }
_, err = doExecValue(ctx, vm, minerInfos[i].maddr, builtin.StoragePowerActorAddr, big.Zero(), builtin.MethodsMiner.ConfirmSectorProofsValid, mustEnc(confirmParams)) _, err = doExecValue(ctx, vm, minerInfos[i].maddr, power.Address, big.Zero(), builtin.MethodsMiner.ConfirmSectorProofsValid, mustEnc(confirmParams))
if err != nil { if err != nil {
return cid.Undef, xerrors.Errorf("failed to confirm presealed sectors: %w", err) return cid.Undef, xerrors.Errorf("failed to confirm presealed sectors: %w", err)
} }
@ -310,7 +309,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
} }
// Sanity-check total network power // Sanity-check total network power
err = vm.MutateState(ctx, builtin.StoragePowerActorAddr, func(cst cbor.IpldStore, st *power.State) error { err = vm.MutateState(ctx, power.Address, func(cst cbor.IpldStore, st *power0.State) error {
if !st.TotalRawBytePower.Equals(rawPow) { if !st.TotalRawBytePower.Equals(rawPow) {
return xerrors.Errorf("st.TotalRawBytePower doesn't match previously calculated rawPow") return xerrors.Errorf("st.TotalRawBytePower doesn't match previously calculated rawPow")
} }
@ -349,12 +348,12 @@ func (fr *fakeRand) GetBeaconRandomness(ctx context.Context, personalization cry
return out, nil return out, nil
} }
func currentTotalPower(ctx context.Context, vm *vm.VM, maddr address.Address) (*power.CurrentTotalPowerReturn, error) { func currentTotalPower(ctx context.Context, vm *vm.VM, maddr address.Address) (*power0.CurrentTotalPowerReturn, error) {
pwret, err := doExecValue(ctx, vm, builtin.StoragePowerActorAddr, maddr, big.Zero(), builtin.MethodsPower.CurrentTotalPower, nil) pwret, err := doExecValue(ctx, vm, power.Address, maddr, big.Zero(), builtin.MethodsPower.CurrentTotalPower, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var pwr power.CurrentTotalPowerReturn var pwr power0.CurrentTotalPowerReturn
if err := pwr.UnmarshalCBOR(bytes.NewReader(pwret)); err != nil { if err := pwr.UnmarshalCBOR(bytes.NewReader(pwret)); err != nil {
return nil, err return nil, err
} }
@ -362,38 +361,38 @@ func currentTotalPower(ctx context.Context, vm *vm.VM, maddr address.Address) (*
return &pwr, nil return &pwr, nil
} }
func dealWeight(ctx context.Context, vm *vm.VM, maddr address.Address, dealIDs []abi.DealID, sectorStart, sectorExpiry abi.ChainEpoch) (market.VerifyDealsForActivationReturn, error) { func dealWeight(ctx context.Context, vm *vm.VM, maddr address.Address, dealIDs []abi.DealID, sectorStart, sectorExpiry abi.ChainEpoch) (market0.VerifyDealsForActivationReturn, error) {
params := &market.VerifyDealsForActivationParams{ params := &market.VerifyDealsForActivationParams{
DealIDs: dealIDs, DealIDs: dealIDs,
SectorStart: sectorStart, SectorStart: sectorStart,
SectorExpiry: sectorExpiry, SectorExpiry: sectorExpiry,
} }
var dealWeights market.VerifyDealsForActivationReturn var dealWeights market0.VerifyDealsForActivationReturn
ret, err := doExecValue(ctx, vm, ret, err := doExecValue(ctx, vm,
builtin.StorageMarketActorAddr, market.Address,
maddr, maddr,
abi.NewTokenAmount(0), abi.NewTokenAmount(0),
builtin.MethodsMarket.VerifyDealsForActivation, builtin.MethodsMarket.VerifyDealsForActivation,
mustEnc(params), mustEnc(params),
) )
if err != nil { if err != nil {
return market.VerifyDealsForActivationReturn{}, err return market0.VerifyDealsForActivationReturn{}, err
} }
if err := dealWeights.UnmarshalCBOR(bytes.NewReader(ret)); err != nil { if err := dealWeights.UnmarshalCBOR(bytes.NewReader(ret)); err != nil {
return market.VerifyDealsForActivationReturn{}, err return market0.VerifyDealsForActivationReturn{}, err
} }
return dealWeights, nil return dealWeights, nil
} }
func currentEpochBlockReward(ctx context.Context, vm *vm.VM, maddr address.Address) (*reward.ThisEpochRewardReturn, error) { func currentEpochBlockReward(ctx context.Context, vm *vm.VM, maddr address.Address) (*reward0.ThisEpochRewardReturn, error) {
rwret, err := doExecValue(ctx, vm, builtin.RewardActorAddr, maddr, big.Zero(), builtin.MethodsReward.ThisEpochReward, nil) rwret, err := doExecValue(ctx, vm, reward.Address, maddr, big.Zero(), builtin.MethodsReward.ThisEpochReward, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var epochReward reward.ThisEpochRewardReturn var epochReward reward0.ThisEpochRewardReturn
if err := epochReward.UnmarshalCBOR(bytes.NewReader(rwret)); err != nil { if err := epochReward.UnmarshalCBOR(bytes.NewReader(rwret)); err != nil {
return nil, err return nil, err
} }

View File

@ -6,7 +6,7 @@ import (
"github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/reward" reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
@ -17,7 +17,7 @@ import (
func SetupRewardActor(bs bstore.Blockstore, qaPower big.Int) (*types.Actor, error) { func SetupRewardActor(bs bstore.Blockstore, qaPower big.Int) (*types.Actor, error) {
cst := cbor.NewCborStore(bs) cst := cbor.NewCborStore(bs)
st := reward.ConstructState(qaPower) st := reward0.ConstructState(qaPower)
hcid, err := cst.Put(context.TODO(), st) hcid, err := cst.Put(context.TODO(), st)
if err != nil { if err != nil {

View File

@ -6,7 +6,7 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/specs-actors/actors/builtin/power" power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -30,7 +30,7 @@ func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) {
return nil, err return nil, err
} }
sms := power.ConstructState(emptyMap, emptyMultiMap) sms := power0.ConstructState(emptyMap, emptyMultiMap)
stcid, err := store.Put(store.Context(), sms) stcid, err := store.Put(store.Context(), sms)
if err != nil { if err != nil {

View File

@ -7,7 +7,7 @@ import (
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg" verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -34,7 +34,7 @@ func SetupVerifiedRegistryActor(bs bstore.Blockstore) (*types.Actor, error) {
return nil, err return nil, err
} }
sms := verifreg.ConstructState(h, RootVerifierID) sms := verifreg0.ConstructState(h, RootVerifierID)
stcid, err := store.Put(store.Context(), sms) stcid, err := store.Put(store.Context(), sms)
if err != nil { if err != nil {

View File

@ -3,6 +3,9 @@ package genesis
import ( import (
"context" "context"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/build"
"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"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
@ -46,3 +49,14 @@ func doExecValue(ctx context.Context, vm *vm.VM, to, from address.Address, value
return ret.Return, nil return ret.Return, nil
} }
var GenesisNetworkVersion = func() network.Version { // TODO: Get from build/
if build.UseNewestNetwork() { // TODO: Get from build/
return build.NewestNetworkVersion // TODO: Get from build/
} // TODO: Get from build/
return network.Version1 // TODO: Get from build/
}() // TODO: Get from build/
func genesisNetworkVersion(context.Context, abi.ChainEpoch) network.Version { // TODO: Get from build/
return GenesisNetworkVersion // TODO: Get from build/
} // TODO: Get from build/

View File

@ -105,6 +105,10 @@ func checkFault(t ds.Datastore, key ds.Key, bh *types.BlockHeader, faultType str
return err return err
} }
if other == bh.Cid() {
return nil
}
return xerrors.Errorf("produced block would trigger '%s' consensus fault; miner: %s; bh: %s, other: %s", faultType, bh.Miner, bh.Cid(), other) return xerrors.Errorf("produced block would trigger '%s' consensus fault; miner: %s; bh: %s, other: %s", faultType, bh.Miner, bh.Cid(), other)
} }

View File

@ -15,6 +15,7 @@ import (
"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/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"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"
@ -151,7 +152,7 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
} }
smsg, err := fm.api.MpoolPushMessage(ctx, &types.Message{ smsg, err := fm.api.MpoolPushMessage(ctx, &types.Message{
To: builtin.StorageMarketActorAddr, To: market.Address,
From: wallet, From: wallet,
Value: toAdd, Value: toAdd,
Method: builtin.MethodsMarket.AddBalance, Method: builtin.MethodsMarket.AddBalance,

View File

@ -17,6 +17,7 @@ import (
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
@ -47,7 +48,7 @@ func (fapi *fakeAPI) MpoolPushMessage(ctx context.Context, msg *types.Message, s
func addFundsMsg(toAdd abi.TokenAmount, addr address.Address, wallet address.Address) *types.Message { func addFundsMsg(toAdd abi.TokenAmount, addr address.Address, wallet address.Address) *types.Message {
params, _ := actors.SerializeParams(&addr) params, _ := actors.SerializeParams(&addr)
return &types.Message{ return &types.Message{
To: builtin.StorageMarketActorAddr, To: market.Address,
From: wallet, From: wallet,
Value: toAdd, Value: toAdd,
Method: builtin.MethodsMarket.AddBalance, Method: builtin.MethodsMarket.AddBalance,

View File

@ -76,8 +76,6 @@ var (
ErrRBFTooLowPremium = errors.New("replace by fee has too low GasPremium") ErrRBFTooLowPremium = errors.New("replace by fee has too low GasPremium")
ErrTooManyPendingMessages = errors.New("too many pending messages for actor") ErrTooManyPendingMessages = errors.New("too many pending messages for actor")
ErrNonceGap = errors.New("unfulfilled nonce gap") ErrNonceGap = errors.New("unfulfilled nonce gap")
ErrTryAgain = errors.New("state inconsistency while pushing message; please try again")
) )
const ( const (
@ -804,98 +802,6 @@ func (mp *MessagePool) getStateBalance(addr address.Address, ts *types.TipSet) (
return act.Balance, nil return act.Balance, nil
} }
func (mp *MessagePool) PushWithNonce(ctx context.Context, addr address.Address, cb func(address.Address, uint64) (*types.SignedMessage, error)) (*types.SignedMessage, error) {
// serialize push access to reduce lock contention
mp.addSema <- struct{}{}
defer func() {
<-mp.addSema
}()
mp.curTsLk.Lock()
mp.lk.Lock()
curTs := mp.curTs
fromKey := addr
if fromKey.Protocol() == address.ID {
var err error
fromKey, err = mp.api.StateAccountKey(ctx, fromKey, mp.curTs)
if err != nil {
mp.lk.Unlock()
mp.curTsLk.Unlock()
return nil, xerrors.Errorf("resolving sender key: %w", err)
}
}
nonce, err := mp.getNonceLocked(fromKey, mp.curTs)
if err != nil {
mp.lk.Unlock()
mp.curTsLk.Unlock()
return nil, xerrors.Errorf("get nonce locked failed: %w", err)
}
// release the locks for signing
mp.lk.Unlock()
mp.curTsLk.Unlock()
msg, err := cb(fromKey, nonce)
if err != nil {
return nil, err
}
err = mp.checkMessage(msg)
if err != nil {
return nil, err
}
msgb, err := msg.Serialize()
if err != nil {
return nil, err
}
// reacquire the locks and check state for consistency
mp.curTsLk.Lock()
defer mp.curTsLk.Unlock()
if mp.curTs != curTs {
return nil, ErrTryAgain
}
mp.lk.Lock()
defer mp.lk.Unlock()
nonce2, err := mp.getNonceLocked(fromKey, mp.curTs)
if err != nil {
return nil, xerrors.Errorf("get nonce locked failed: %w", err)
}
if nonce2 != nonce {
return nil, ErrTryAgain
}
publish, err := mp.verifyMsgBeforeAdd(msg, curTs, true)
if err != nil {
return nil, err
}
if err := mp.checkBalance(msg, curTs); err != nil {
return nil, err
}
if err := mp.addLocked(msg, false, false); err != nil {
return nil, xerrors.Errorf("add locked failed: %w", err)
}
if err := mp.addLocal(msg, msgb); err != nil {
log.Errorf("addLocal failed: %+v", err)
}
if publish {
err = mp.api.PubSubPublish(build.MessagesTopic(mp.netName), msgb)
}
return msg, err
}
// this method is provided for the gateway to push messages. // this method is provided for the gateway to push messages.
// differences from Push: // differences from Push:
// - strict checks are enabled // - strict checks are enabled

View File

@ -47,13 +47,15 @@ func (mpp *mpoolProvider) PubSubPublish(k string, v []byte) error {
} }
func (mpp *mpoolProvider) GetActorAfter(addr address.Address, ts *types.TipSet) (*types.Actor, error) { func (mpp *mpoolProvider) GetActorAfter(addr address.Address, ts *types.TipSet) (*types.Actor, error) {
var act types.Actor
stcid, _, err := mpp.sm.TipSetState(context.TODO(), ts) stcid, _, err := mpp.sm.TipSetState(context.TODO(), ts)
if err != nil { if err != nil {
return nil, xerrors.Errorf("computing tipset state for GetActor: %w", err) return nil, xerrors.Errorf("computing tipset state for GetActor: %w", err)
} }
st, err := mpp.sm.StateTree(stcid)
return &act, mpp.sm.WithStateTree(stcid, mpp.sm.WithActor(addr, stmgr.GetActor(&act))) if err != nil {
return nil, xerrors.Errorf("failed to load state tree: %w", err)
}
return st.GetActor(addr)
} }
func (mpp *mpoolProvider) StateAccountKey(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) { func (mpp *mpoolProvider) StateAccountKey(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {

View File

@ -1216,6 +1216,9 @@ func makeZipfPremiumDistribution(rng *rand.Rand) func() uint64 {
} }
func TestCompetitiveMessageSelectionExp(t *testing.T) { func TestCompetitiveMessageSelectionExp(t *testing.T) {
if testing.Short() {
t.Skip("skipping in short mode")
}
var capacityBoost, rewardBoost, tqReward float64 var capacityBoost, rewardBoost, tqReward float64
seeds := []int64{1947, 1976, 2020, 2100, 10000, 143324, 432432, 131, 32, 45} seeds := []int64{1947, 1976, 2020, 2100, 10000, 143324, 432432, 131, 32, 45}
for _, seed := range seeds { for _, seed := range seeds {

View File

@ -0,0 +1,124 @@
package messagesigner
import (
"bytes"
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/namespace"
logging "github.com/ipfs/go-log/v2"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
)
const dsKeyActorNonce = "ActorNonce"
var log = logging.Logger("messagesigner")
type mpoolAPI interface {
GetNonce(address.Address) (uint64, error)
}
// MessageSigner keeps track of nonces per address, and increments the nonce
// when signing a message
type MessageSigner struct {
wallet *wallet.Wallet
mpool mpoolAPI
ds datastore.Batching
}
func NewMessageSigner(wallet *wallet.Wallet, mpool *messagepool.MessagePool, ds dtypes.MetadataDS) *MessageSigner {
return newMessageSigner(wallet, mpool, ds)
}
func newMessageSigner(wallet *wallet.Wallet, mpool mpoolAPI, ds dtypes.MetadataDS) *MessageSigner {
ds = namespace.Wrap(ds, datastore.NewKey("/message-signer/"))
return &MessageSigner{
wallet: wallet,
mpool: mpool,
ds: ds,
}
}
// SignMessage increments the nonce for the message From address, and signs
// the message
func (ms *MessageSigner) SignMessage(ctx context.Context, msg *types.Message) (*types.SignedMessage, error) {
nonce, err := ms.nextNonce(msg.From)
if err != nil {
return nil, xerrors.Errorf("failed to create nonce: %w", err)
}
msg.Nonce = nonce
sig, err := ms.wallet.Sign(ctx, msg.From, msg.Cid().Bytes())
if err != nil {
return nil, xerrors.Errorf("failed to sign message: %w", err)
}
return &types.SignedMessage{
Message: *msg,
Signature: *sig,
}, nil
}
// nextNonce increments the nonce.
// If there is no nonce in the datastore, gets the nonce from the message pool.
func (ms *MessageSigner) nextNonce(addr address.Address) (uint64, error) {
// Nonces used to be created by the mempool and we need to support nodes
// that have mempool nonces, so first check the mempool for a nonce for
// this address. Note that the mempool returns the actor state's nonce
// by default.
nonce, err := ms.mpool.GetNonce(addr)
if err != nil {
return 0, xerrors.Errorf("failed to get nonce from mempool: %w", err)
}
// Get the nonce for this address from the datastore
addrNonceKey := datastore.KeyWithNamespaces([]string{dsKeyActorNonce, addr.String()})
dsNonceBytes, err := ms.ds.Get(addrNonceKey)
switch {
case xerrors.Is(err, datastore.ErrNotFound):
// If a nonce for this address hasn't yet been created in the
// datastore, just use the nonce from the mempool
case err != nil:
return 0, xerrors.Errorf("failed to get nonce from datastore: %w", err)
default:
// There is a nonce in the datastore, so unmarshall and increment it
maj, val, err := cbg.CborReadHeader(bytes.NewReader(dsNonceBytes))
if err != nil {
return 0, xerrors.Errorf("failed to parse nonce from datastore: %w", err)
}
if maj != cbg.MajUnsignedInt {
return 0, xerrors.Errorf("bad cbor type parsing nonce from datastore")
}
dsNonce := val + 1
// The message pool nonce should be <= than the datastore nonce
if nonce <= dsNonce {
nonce = dsNonce
} else {
log.Warnf("mempool nonce was larger than datastore nonce (%d > %d)", nonce, dsNonce)
}
}
// Write the nonce for this address to the datastore
buf := bytes.Buffer{}
_, err = buf.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, nonce))
if err != nil {
return 0, xerrors.Errorf("failed to marshall nonce: %w", err)
}
err = ms.ds.Put(addrNonceKey, buf.Bytes())
if err != nil {
return 0, xerrors.Errorf("failed to write nonce to datastore: %w", err)
}
return nonce, nil
}

View File

@ -0,0 +1,158 @@
package messagesigner
import (
"context"
"sync"
"testing"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/stretchr/testify/require"
ds_sync "github.com/ipfs/go-datastore/sync"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-datastore"
)
type mockMpool struct {
lk sync.RWMutex
nonces map[address.Address]uint64
}
func newMockMpool() *mockMpool {
return &mockMpool{nonces: make(map[address.Address]uint64)}
}
func (mp *mockMpool) setNonce(addr address.Address, nonce uint64) {
mp.lk.Lock()
defer mp.lk.Unlock()
mp.nonces[addr] = nonce
}
func (mp *mockMpool) GetNonce(addr address.Address) (uint64, error) {
mp.lk.RLock()
defer mp.lk.RUnlock()
return mp.nonces[addr], nil
}
func TestMessageSignerSignMessage(t *testing.T) {
ctx := context.Background()
w, _ := wallet.NewWallet(wallet.NewMemKeyStore())
from1, err := w.GenerateKey(crypto.SigTypeSecp256k1)
require.NoError(t, err)
from2, err := w.GenerateKey(crypto.SigTypeSecp256k1)
require.NoError(t, err)
to1, err := w.GenerateKey(crypto.SigTypeSecp256k1)
require.NoError(t, err)
to2, err := w.GenerateKey(crypto.SigTypeSecp256k1)
require.NoError(t, err)
type msgSpec struct {
msg *types.Message
mpoolNonce [1]uint64
expNonce uint64
}
tests := []struct {
name string
msgs []msgSpec
}{{
// No nonce yet in datastore
name: "no nonce yet",
msgs: []msgSpec{{
msg: &types.Message{
To: to1,
From: from1,
},
expNonce: 0,
}},
}, {
// Get nonce value of zero from mpool
name: "mpool nonce zero",
msgs: []msgSpec{{
msg: &types.Message{
To: to1,
From: from1,
},
mpoolNonce: [1]uint64{0},
expNonce: 0,
}},
}, {
// Get non-zero nonce value from mpool
name: "mpool nonce set",
msgs: []msgSpec{{
msg: &types.Message{
To: to1,
From: from1,
},
mpoolNonce: [1]uint64{5},
expNonce: 5,
}, {
msg: &types.Message{
To: to1,
From: from1,
},
// Should adjust datastore nonce because mpool nonce is higher
mpoolNonce: [1]uint64{10},
expNonce: 10,
}},
}, {
// Nonce should increment independently for each address
name: "nonce increments per address",
msgs: []msgSpec{{
msg: &types.Message{
To: to1,
From: from1,
},
expNonce: 0,
}, {
msg: &types.Message{
To: to1,
From: from1,
},
expNonce: 1,
}, {
msg: &types.Message{
To: to2,
From: from2,
},
mpoolNonce: [1]uint64{5},
expNonce: 5,
}, {
msg: &types.Message{
To: to2,
From: from2,
},
expNonce: 6,
}, {
msg: &types.Message{
To: to1,
From: from1,
},
expNonce: 2,
}},
}}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
mpool := newMockMpool()
ds := ds_sync.MutexWrap(datastore.NewMapDatastore())
ms := newMessageSigner(w, mpool, ds)
for _, m := range tt.msgs {
if len(m.mpoolNonce) == 1 {
mpool.setNonce(m.msg.From, m.mpoolNonce[0])
}
smsg, err := ms.SignMessage(ctx, m.msg)
require.NoError(t, err)
require.Equal(t, m.expNonce, smsg.Message.Nonce)
}
})
}
}

View File

@ -1,14 +1,10 @@
package state package state
import ( import (
"bytes"
"context" "context"
"fmt" "fmt"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
@ -16,6 +12,12 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/builtin"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
@ -23,8 +25,10 @@ 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
Store cbor.IpldStore version builtin.Version // TODO
info cid.Cid
Store cbor.IpldStore
snaps *stateSnaps snaps *stateSnaps
} }
@ -116,26 +120,57 @@ func (ss *stateSnaps) deleteActor(addr address.Address) {
ss.layers[len(ss.layers)-1].actors[addr] = streeOp{Delete: true} ss.layers[len(ss.layers)-1].actors[addr] = streeOp{Delete: true}
} }
func NewStateTree(cst cbor.IpldStore) (*StateTree, error) { func NewStateTree(cst cbor.IpldStore, version builtin.Version) (*StateTree, error) {
var info cid.Cid
switch version {
case builtin.Version0:
// info is undefined
default:
return nil, xerrors.Errorf("unsupported state tree version: %d", version)
}
root, err := adt.NewMap(adt.WrapStore(context.TODO(), cst), version)
if err != nil {
return nil, err
}
return &StateTree{ return &StateTree{
root: adt.MakeEmptyMap(adt.WrapStore(context.TODO(), cst)), root: root,
Store: cst, info: info,
snaps: newStateSnaps(), version: version,
Store: cst,
snaps: newStateSnaps(),
}, nil }, nil
} }
func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) { func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
nd, err := adt.AsMap(adt.WrapStore(context.TODO(), cst), c) var root types.StateRoot
// Try loading as a new-style state-tree (version/actors tuple).
if err := cst.Get(context.TODO(), c, &root); err != nil {
// We failed to decode as the new version, must be an old version.
root.Actors = c
root.Version = builtin.Version0
}
// If that fails, load as an old-style state-tree (direct hampt, version 0.
nd, err := adt.AsMap(adt.WrapStore(context.TODO(), cst), root.Actors, builtin.Version(root.Version))
if err != nil { if err != nil {
log.Errorf("loading hamt node %s failed: %s", c, err) log.Errorf("loading hamt node %s failed: %s", c, err)
return nil, err return nil, err
} }
switch root.Version {
case builtin.Version0:
// supported
default:
return nil, xerrors.Errorf("unsupported state tree version: %d", root.Version)
}
return &StateTree{ return &StateTree{
root: nd, root: nd,
Store: cst, info: root.Info,
snaps: newStateSnaps(), version: builtin.Version(root.Version),
Store: cst,
snaps: newStateSnaps(),
}, nil }, nil
} }
@ -161,17 +196,17 @@ func (st *StateTree) LookupID(addr address.Address) (address.Address, error) {
return resa, nil return resa, nil
} }
act, err := st.GetActor(builtin.InitActorAddr) 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)
} }
var ias init_.State ias, err := init_.Load(&AdtStore{st.Store}, act)
if err := st.Store.Get(context.TODO(), act.Head, &ias); err != nil { if err != nil {
return address.Undef, xerrors.Errorf("loading init actor state: %w", err) return address.Undef, xerrors.Errorf("loading init actor state: %w", err)
} }
a, found, err := ias.ResolveAddress(&AdtStore{st.Store}, addr) a, found, err := ias.ResolveAddress(addr)
if err == nil && !found { if err == nil && !found {
err = types.ErrActorNotFound err = types.ErrActorNotFound
} }
@ -265,7 +300,16 @@ func (st *StateTree) Flush(ctx context.Context) (cid.Cid, error) {
} }
} }
return st.root.Root() root, err := st.root.Root()
if err != nil {
return cid.Undef, xerrors.Errorf("failed to flush state-tree hamt: %w", err)
}
// If we're version 0, return a raw tree.
if st.version == builtin.Version0 {
return root, nil
}
// Otherwise, return a versioned tree.
return st.Store.Put(ctx, &types.StateRoot{Version: uint64(st.version), Actors: root, Info: st.info})
} }
func (st *StateTree) Snapshot(ctx context.Context) error { func (st *StateTree) Snapshot(ctx context.Context) error {
@ -283,19 +327,19 @@ func (st *StateTree) ClearSnapshot() {
func (st *StateTree) RegisterNewAddress(addr address.Address) (address.Address, error) { func (st *StateTree) RegisterNewAddress(addr address.Address) (address.Address, error) {
var out address.Address var out address.Address
err := st.MutateActor(builtin.InitActorAddr, func(initact *types.Actor) error { err := st.MutateActor(init_.Address, func(initact *types.Actor) error {
var ias init_.State ias, err := init_.Load(&AdtStore{st.Store}, initact)
if err := st.Store.Get(context.TODO(), initact.Head, &ias); err != nil { if err != nil {
return err return err
} }
oaddr, err := ias.MapAddressToNewID(&AdtStore{st.Store}, addr) oaddr, err := ias.MapAddressToNewID(addr)
if err != nil { if err != nil {
return err return err
} }
out = oaddr out = oaddr
ncid, err := st.Store.Put(context.TODO(), &ias) ncid, err := st.Store.Put(context.TODO(), ias)
if err != nil { if err != nil {
return err return err
} }
@ -341,6 +385,7 @@ func (st *StateTree) MutateActor(addr address.Address, f func(*types.Actor) erro
func (st *StateTree) ForEach(f func(address.Address, *types.Actor) error) error { func (st *StateTree) ForEach(f func(address.Address, *types.Actor) error) error {
var act types.Actor var act types.Actor
return st.root.ForEach(&act, func(k string) error { return st.root.ForEach(&act, func(k string) error {
act := act // copy
addr, err := address.NewFromBytes([]byte(k)) addr, err := address.NewFromBytes([]byte(k))
if err != nil { if err != nil {
return xerrors.Errorf("invalid address (%x) found in state tree key: %w", []byte(k), err) return xerrors.Errorf("invalid address (%x) found in state tree key: %w", []byte(k), err)
@ -349,3 +394,49 @@ func (st *StateTree) ForEach(f func(address.Address, *types.Actor) error) error
return f(addr, &act) return f(addr, &act)
}) })
} }
// Version returns the version of the StateTree data structure in use.
func (st *StateTree) Version() builtin.Version {
return st.version
}
func Diff(oldTree, newTree *StateTree) (map[string]types.Actor, error) {
out := map[string]types.Actor{}
var (
ncval, ocval cbg.Deferred
buf = bytes.NewReader(nil)
)
if err := newTree.root.ForEach(&ncval, func(k string) error {
var act types.Actor
addr, err := address.NewFromBytes([]byte(k))
if err != nil {
return xerrors.Errorf("address in state tree was not valid: %w", err)
}
found, err := oldTree.root.Get(abi.AddrKey(addr), &ocval)
if err != nil {
return err
}
if found && bytes.Equal(ocval.Raw, ncval.Raw) {
return nil // not changed
}
buf.Reset(ncval.Raw)
err = act.UnmarshalCBOR(buf)
buf.Reset(nil)
if err != nil {
return err
}
out[addr.String()] = act
return nil
}); err != nil {
return nil, err
}
return out, nil
}

View File

@ -5,17 +5,20 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/filecoin-project/specs-actors/actors/builtin"
address "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
address "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/build"
builtin2 "github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
) )
func BenchmarkStateTreeSet(b *testing.B) { func BenchmarkStateTreeSet(b *testing.B) {
cst := cbor.NewMemCborStore() cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst) st, err := NewStateTree(cst, builtin2.VersionForNetwork(build.NewestNetworkVersion))
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
@ -42,7 +45,7 @@ func BenchmarkStateTreeSet(b *testing.B) {
func BenchmarkStateTreeSetFlush(b *testing.B) { func BenchmarkStateTreeSetFlush(b *testing.B) {
cst := cbor.NewMemCborStore() cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst) st, err := NewStateTree(cst, builtin2.VersionForNetwork(build.NewestNetworkVersion))
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
@ -72,7 +75,7 @@ func BenchmarkStateTreeSetFlush(b *testing.B) {
func BenchmarkStateTree10kGetActor(b *testing.B) { func BenchmarkStateTree10kGetActor(b *testing.B) {
cst := cbor.NewMemCborStore() cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst) st, err := NewStateTree(cst, builtin2.VersionForNetwork(build.NewestNetworkVersion))
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
@ -114,7 +117,7 @@ func BenchmarkStateTree10kGetActor(b *testing.B) {
func TestSetCache(t *testing.T) { func TestSetCache(t *testing.T) {
cst := cbor.NewMemCborStore() cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst) st, err := NewStateTree(cst, builtin2.VersionForNetwork(build.NewestNetworkVersion))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -151,7 +154,7 @@ func TestSetCache(t *testing.T) {
func TestSnapshots(t *testing.T) { func TestSnapshots(t *testing.T) {
ctx := context.Background() ctx := context.Background()
cst := cbor.NewMemCborStore() cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst) st, err := NewStateTree(cst, builtin2.VersionForNetwork(build.NewestNetworkVersion))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -234,7 +237,7 @@ func assertNotHas(t *testing.T, st *StateTree, addr address.Address) {
func TestStateTreeConsistency(t *testing.T) { func TestStateTreeConsistency(t *testing.T) {
cst := cbor.NewMemCborStore() cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst) st, err := NewStateTree(cst, builtin2.VersionForNetwork(build.NewestNetworkVersion))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -33,7 +33,7 @@ func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate
BaseFee: types.NewInt(0), BaseFee: types.NewInt(0),
} }
vmi, err := vm.NewVM(vmopt) vmi, err := vm.NewVM(ctx, vmopt)
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to set up vm: %w", err) return nil, xerrors.Errorf("failed to set up vm: %w", err)
} }
@ -134,7 +134,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
NtwkVersion: sm.GetNtwkVersion, NtwkVersion: sm.GetNtwkVersion,
BaseFee: ts.Blocks()[0].ParentBaseFee, BaseFee: ts.Blocks()[0].ParentBaseFee,
} }
vmi, err := vm.NewVM(vmopt) vmi, err := vm.NewVM(ctx, vmopt)
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to set up vm: %w", err) return nil, xerrors.Errorf("failed to set up vm: %w", err)
} }

View File

@ -1,43 +1,59 @@
package stmgr package stmgr
import ( import (
"bytes"
"context" "context"
"encoding/binary"
"math"
multisig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/specs-actors/actors/migration/nv3"
"github.com/ipfs/go-cid"
"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"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/util/adt"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"golang.org/x/xerrors" "golang.org/x/xerrors"
) )
var ForksAtHeight = map[abi.ChainEpoch]func(context.Context, *StateManager, types.StateTree, *types.TipSet) error{ var ForksAtHeight = map[abi.ChainEpoch]func(context.Context, *StateManager, ExecCallback, cid.Cid, *types.TipSet) (cid.Cid, error){
build.UpgradeBreezeHeight: UpgradeFaucetBurnRecovery, build.UpgradeBreezeHeight: UpgradeFaucetBurnRecovery,
build.UpgradeIgnitionHeight: UpgradeIgnition,
build.UpgradeLiftoffHeight: UpgradeLiftoff,
} }
func (sm *StateManager) handleStateForks(ctx context.Context, st types.StateTree, height abi.ChainEpoch, ts *types.TipSet) (err error) { func (sm *StateManager) handleStateForks(ctx context.Context, root cid.Cid, height abi.ChainEpoch, cb ExecCallback, ts *types.TipSet) (cid.Cid, error) {
retCid := root
var err error
f, ok := ForksAtHeight[height] f, ok := ForksAtHeight[height]
if ok { if ok {
err := f(ctx, sm, st, ts) retCid, err = f(ctx, sm, cb, root, ts)
if err != nil { if err != nil {
return err return cid.Undef, err
} }
} }
return nil return retCid, nil
} }
type forEachTree interface { func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address, amt abi.TokenAmount) error {
ForEach(func(address.Address, *types.Actor) error) error
}
func doTransfer(tree types.StateTree, from, to address.Address, amt abi.TokenAmount) 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)
@ -63,10 +79,43 @@ func doTransfer(tree types.StateTree, from, to address.Address, amt abi.TokenAmo
return xerrors.Errorf("failed to persist to actor: %w", err) return xerrors.Errorf("failed to persist to actor: %w", err)
} }
if cb != nil {
// record the transfer in execution traces
fakeMsg := &types.Message{
From: from,
To: to,
Value: amt,
Nonce: math.MaxUint64,
}
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: nil,
},
Duration: 0,
GasCosts: vm.ZeroGasOutputs(),
}); err != nil {
return xerrors.Errorf("recording transfer: %w", err)
}
}
return nil return nil
} }
func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types.StateTree, ts *types.TipSet) error { func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, ts *types.TipSet) (cid.Cid, error) {
// Some initial parameters // Some initial parameters
FundsForMiners := types.FromFil(1_000_000) FundsForMiners := types.FromFil(1_000_000)
LookbackEpoch := abi.ChainEpoch(32000) LookbackEpoch := abi.ChainEpoch(32000)
@ -93,25 +142,22 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
// Grab lookback state for account checks // Grab lookback state for account checks
lbts, err := sm.ChainStore().GetTipsetByHeight(ctx, LookbackEpoch, ts, false) lbts, err := sm.ChainStore().GetTipsetByHeight(ctx, LookbackEpoch, ts, false)
if err != nil { if err != nil {
return xerrors.Errorf("failed to get tipset at lookback height: %w", err) return cid.Undef, xerrors.Errorf("failed to get tipset at lookback height: %w", err)
} }
var lbtree *state.StateTree lbtree, err := sm.ParentState(lbts)
if err = sm.WithStateTree(lbts.ParentState(), func(state *state.StateTree) error { if err != nil {
lbtree = state return cid.Undef, xerrors.Errorf("loading state tree failed: %w", err)
return nil
}); err != nil {
return xerrors.Errorf("loading state tree failed: %w", err)
} }
ReserveAddress, err := address.NewFromString("t090") ReserveAddress, err := address.NewFromString("t090")
if err != nil { if err != nil {
return xerrors.Errorf("failed to parse reserve address: %w", err) return cid.Undef, xerrors.Errorf("failed to parse reserve address: %w", err)
} }
fetree, ok := tree.(forEachTree) tree, err := sm.StateTree(root)
if !ok { if err != nil {
return xerrors.Errorf("fork transition state tree doesnt support ForEach (%T)", tree) return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
} }
type transfer struct { type transfer struct {
@ -123,9 +169,9 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
var transfers []transfer var transfers []transfer
// Take all excess funds away, put them into the reserve account // Take all excess funds away, put them into the reserve account
err = fetree.ForEach(func(addr address.Address, act *types.Actor) error { err = tree.ForEach(func(addr address.Address, act *types.Actor) error {
switch act.Code { switch act.Code {
case builtin.AccountActorCodeID, builtin.MultisigActorCodeID, builtin.PaymentChannelActorCodeID: case builtin0.AccountActorCodeID, builtin0.MultisigActorCodeID, builtin0.PaymentChannelActorCodeID:
sysAcc, err := isSystemAccount(addr) sysAcc, err := isSystemAccount(addr)
if err != nil { if err != nil {
return xerrors.Errorf("checking system account: %w", err) return xerrors.Errorf("checking system account: %w", err)
@ -138,9 +184,9 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
Amt: act.Balance, Amt: act.Balance,
}) })
} }
case builtin.StorageMinerActorCodeID: case builtin0.StorageMinerActorCodeID:
var st miner.State var st miner0.State
if err := sm.WithActorState(ctx, &st)(act); err != nil { if err := sm.ChainStore().Store(ctx).Get(ctx, act.Head, &st); err != nil {
return xerrors.Errorf("failed to load miner state: %w", err) return xerrors.Errorf("failed to load miner state: %w", err)
} }
@ -165,33 +211,33 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
return nil return nil
}) })
if err != nil { if err != nil {
return xerrors.Errorf("foreach over state tree failed: %w", err) return cid.Undef, xerrors.Errorf("foreach over state tree failed: %w", err)
} }
// Execute transfers from previous step // Execute transfers from previous step
for _, t := range transfers { for _, t := range transfers {
if err := doTransfer(tree, t.From, t.To, t.Amt); err != nil { if err := doTransfer(cb, tree, t.From, t.To, t.Amt); err != nil {
return 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)
} }
} }
// pull up power table to give miners back some funds proportional to their power // pull up power table to give miners back some funds proportional to their power
var ps power.State var ps power0.State
powAct, err := tree.GetActor(builtin.StoragePowerActorAddr) powAct, err := tree.GetActor(builtin0.StoragePowerActorAddr)
if err != nil { if err != nil {
return xerrors.Errorf("failed to load power actor: %w", err) return cid.Undef, xerrors.Errorf("failed to load power actor: %w", err)
} }
cst := cbor.NewCborStore(sm.ChainStore().Blockstore()) cst := cbor.NewCborStore(sm.ChainStore().Blockstore())
if err := cst.Get(ctx, powAct.Head, &ps); err != nil { if err := cst.Get(ctx, powAct.Head, &ps); err != nil {
return xerrors.Errorf("failed to get power actor state: %w", err) return cid.Undef, xerrors.Errorf("failed to get power actor state: %w", err)
} }
totalPower := ps.TotalBytesCommitted totalPower := ps.TotalBytesCommitted
var transfersBack []transfer var transfersBack []transfer
// Now, we return some funds to places where they are needed // Now, we return some funds to places where they are needed
err = fetree.ForEach(func(addr address.Address, act *types.Actor) error { err = tree.ForEach(func(addr address.Address, act *types.Actor) error {
lbact, err := lbtree.GetActor(addr) lbact, err := lbtree.GetActor(addr)
if err != nil { if err != nil {
if !xerrors.Is(err, types.ErrActorNotFound) { if !xerrors.Is(err, types.ErrActorNotFound) {
@ -205,7 +251,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
} }
switch act.Code { switch act.Code {
case builtin.AccountActorCodeID, builtin.MultisigActorCodeID, builtin.PaymentChannelActorCodeID: case builtin0.AccountActorCodeID, builtin0.MultisigActorCodeID, builtin0.PaymentChannelActorCodeID:
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{
@ -214,18 +260,18 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
Amt: nbalance, Amt: nbalance,
}) })
} }
case builtin.StorageMinerActorCodeID: case builtin0.StorageMinerActorCodeID:
var st miner.State var st miner0.State
if err := sm.WithActorState(ctx, &st)(act); err != nil { if err := sm.ChainStore().Store(ctx).Get(ctx, act.Head, &st); err != nil {
return xerrors.Errorf("failed to load miner state: %w", err) return xerrors.Errorf("failed to load miner state: %w", err)
} }
var minfo miner.MinerInfo var minfo miner0.MinerInfo
if err := cst.Get(ctx, st.Info, &minfo); err != nil { if err := cst.Get(ctx, st.Info, &minfo); err != nil {
return xerrors.Errorf("failed to get miner info: %w", err) return xerrors.Errorf("failed to get miner info: %w", err)
} }
sectorsArr, err := adt.AsArray(sm.ChainStore().Store(ctx), st.Sectors) sectorsArr, err := adt0.AsArray(sm.ChainStore().Store(ctx), st.Sectors)
if err != nil { if err != nil {
return xerrors.Errorf("failed to load sectors array: %w", err) return xerrors.Errorf("failed to load sectors array: %w", err)
} }
@ -244,12 +290,12 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
// Now make sure to give each miner who had power at the lookback some FIL // Now make sure to give each miner who had power at the lookback some FIL
lbact, err := lbtree.GetActor(addr) lbact, err := lbtree.GetActor(addr)
if err == nil { if err == nil {
var lbst miner.State var lbst miner0.State
if err := sm.WithActorState(ctx, &lbst)(lbact); err != nil { if err := sm.ChainStore().Store(ctx).Get(ctx, lbact.Head, &lbst); err != nil {
return xerrors.Errorf("failed to load miner state: %w", err) return xerrors.Errorf("failed to load miner state: %w", err)
} }
lbsectors, err := adt.AsArray(sm.ChainStore().Store(ctx), lbst.Sectors) lbsectors, err := adt0.AsArray(sm.ChainStore().Store(ctx), lbst.Sectors)
if err != nil { if err != nil {
return xerrors.Errorf("failed to load lb sectors array: %w", err) return xerrors.Errorf("failed to load lb sectors array: %w", err)
} }
@ -269,53 +315,310 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
return nil return nil
}) })
if err != nil { if err != nil {
return xerrors.Errorf("foreach over state tree failed: %w", err) return cid.Undef, xerrors.Errorf("foreach over state tree failed: %w", err)
} }
for _, t := range transfersBack { for _, t := range transfersBack {
if err := doTransfer(tree, t.From, t.To, t.Amt); err != nil { if err := doTransfer(cb, tree, t.From, t.To, t.Amt); err != nil {
return 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)
} }
} }
// transfer all burnt funds back to the reserve account // transfer all burnt funds back to the reserve account
burntAct, err := tree.GetActor(builtin.BurntFundsActorAddr) burntAct, err := tree.GetActor(builtin0.BurntFundsActorAddr)
if err != nil { if err != nil {
return 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(tree, builtin.BurntFundsActorAddr, ReserveAddress, burntAct.Balance); err != nil { if err := doTransfer(cb, tree, builtin0.BurntFundsActorAddr, ReserveAddress, burntAct.Balance); err != nil {
return xerrors.Errorf("failed to unburn funds: %w", err) return cid.Undef, xerrors.Errorf("failed to unburn funds: %w", err)
} }
// Top up the reimbursement service // Top up the reimbursement service
reimbAddr, err := address.NewFromString("t0111") reimbAddr, err := address.NewFromString("t0111")
if err != nil { if err != nil {
return xerrors.Errorf("failed to parse reimbursement service address") return cid.Undef, xerrors.Errorf("failed to parse reimbursement service address")
} }
reimb, err := tree.GetActor(reimbAddr) reimb, err := tree.GetActor(reimbAddr)
if err != nil { if err != nil {
return xerrors.Errorf("failed to load reimbursement account actor: %w", err) return cid.Undef, xerrors.Errorf("failed to load reimbursement account actor: %w", err)
} }
difference := types.BigSub(DesiredReimbursementBalance, reimb.Balance) difference := types.BigSub(DesiredReimbursementBalance, reimb.Balance)
if err := doTransfer(tree, ReserveAddress, reimbAddr, difference); err != nil { if err := doTransfer(cb, tree, ReserveAddress, reimbAddr, difference); err != nil {
return xerrors.Errorf("failed to top up reimbursement account: %w", err) return cid.Undef, xerrors.Errorf("failed to top up reimbursement account: %w", err)
} }
// Now, a final sanity check to make sure the balances all check out // Now, a final sanity check to make sure the balances all check out
total := abi.NewTokenAmount(0) total := abi.NewTokenAmount(0)
err = fetree.ForEach(func(addr address.Address, act *types.Actor) error { err = tree.ForEach(func(addr address.Address, act *types.Actor) error {
total = types.BigAdd(total, act.Balance) total = types.BigAdd(total, act.Balance)
return nil return nil
}) })
if err != nil { if err != nil {
return xerrors.Errorf("checking final state balance failed: %w", err) return cid.Undef, xerrors.Errorf("checking final state balance failed: %w", err)
} }
exp := types.FromFil(build.FilBase) exp := types.FromFil(build.FilBase)
if !exp.Equals(total) { if !exp.Equals(total) {
return 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)
}
return tree.Flush(ctx)
}
func UpgradeIgnition(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, ts *types.TipSet) (cid.Cid, error) {
store := sm.cs.Store(ctx)
nst, err := nv3.MigrateStateTree(ctx, store, root, build.UpgradeIgnitionHeight)
if err != nil {
return cid.Undef, xerrors.Errorf("migrating actors state: %w", err)
}
tree, err := sm.StateTree(nst)
if err != nil {
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
}
err = setNetworkName(ctx, store, tree, "ignition")
if err != nil {
return cid.Undef, xerrors.Errorf("setting network name: %w", err)
}
split1, err := address.NewFromString("t0115")
if err != nil {
return cid.Undef, xerrors.Errorf("first split address: %w", err)
}
split2, err := address.NewFromString("t0116")
if err != nil {
return cid.Undef, xerrors.Errorf("second split address: %w", err)
}
err = resetGenesisMsigs(ctx, sm, store, tree)
if err != nil {
return cid.Undef, xerrors.Errorf("resetting genesis msig start epochs: %w", err)
}
err = splitGenesisMultisig(ctx, cb, split1, store, tree, 50)
if err != nil {
return cid.Undef, xerrors.Errorf("splitting first msig: %w", err)
}
err = splitGenesisMultisig(ctx, cb, split2, store, tree, 50)
if err != nil {
return cid.Undef, xerrors.Errorf("splitting second msig: %w", err)
}
err = nv3.CheckStateTree(ctx, store, nst, build.UpgradeIgnitionHeight, builtin0.TotalFilecoin)
if err != nil {
return cid.Undef, xerrors.Errorf("sanity check after ignition upgrade failed: %w", err)
}
return tree.Flush(ctx)
}
func UpgradeLiftoff(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, ts *types.TipSet) (cid.Cid, error) {
tree, err := sm.StateTree(root)
if err != nil {
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
}
err = setNetworkName(ctx, sm.cs.Store(ctx), tree, "mainnet")
if err != nil {
return cid.Undef, xerrors.Errorf("setting network name: %w", err)
}
return tree.Flush(ctx)
}
func setNetworkName(ctx context.Context, store adt0.Store, tree *state.StateTree, name string) error {
ia, err := tree.GetActor(builtin0.InitActorAddr)
if err != nil {
return xerrors.Errorf("getting init actor: %w", err)
}
var initState init0.State
if err := store.Get(ctx, ia.Head, &initState); err != nil {
return xerrors.Errorf("reading init state: %w", err)
}
initState.NetworkName = name
ia.Head, err = store.Put(ctx, &initState)
if err != nil {
return xerrors.Errorf("writing new init state: %w", err)
}
if err := tree.SetActor(builtin0.InitActorAddr, ia); err != nil {
return xerrors.Errorf("setting init actor: %w", err)
}
return nil
}
func splitGenesisMultisig(ctx context.Context, cb ExecCallback, addr address.Address, store adt0.Store, tree *state.StateTree, portions uint64) error {
if portions < 1 {
return xerrors.Errorf("cannot split into 0 portions")
}
mact, err := tree.GetActor(addr)
if err != nil {
return xerrors.Errorf("getting msig actor: %w", err)
}
mst, err := multisig.Load(store, mact)
if err != nil {
return xerrors.Errorf("getting msig state: %w", err)
}
signers, err := mst.Signers()
if err != nil {
return xerrors.Errorf("getting msig signers: %w", err)
}
thresh, err := mst.Threshold()
if err != nil {
return xerrors.Errorf("getting msig threshold: %w", err)
}
ibal, err := mst.InitialBalance()
if err != nil {
return xerrors.Errorf("getting msig initial balance: %w", err)
}
se, err := mst.StartEpoch()
if err != nil {
return xerrors.Errorf("getting msig start epoch: %w", err)
}
ud, err := mst.UnlockDuration()
if err != nil {
return xerrors.Errorf("getting msig unlock duration: %w", err)
}
pending, err := adt0.MakeEmptyMap(store).Root()
if err != nil {
return xerrors.Errorf("failed to create empty map: %w", err)
}
newIbal := big.Div(ibal, types.NewInt(portions))
newState := &multisig0.State{
Signers: signers,
NumApprovalsThreshold: thresh,
NextTxnID: 0,
InitialBalance: newIbal,
StartEpoch: se,
UnlockDuration: ud,
PendingTxns: pending,
}
scid, err := store.Put(ctx, newState)
if err != nil {
return xerrors.Errorf("storing new state: %w", err)
}
newActor := types.Actor{
Code: builtin0.MultisigActorCodeID,
Head: scid,
Nonce: 0,
Balance: big.Zero(),
}
i := uint64(0)
for i < portions {
keyAddr, err := makeKeyAddr(addr, i)
if err != nil {
return xerrors.Errorf("creating key address: %w", err)
}
idAddr, err := tree.RegisterNewAddress(keyAddr)
if err != nil {
return xerrors.Errorf("registering new address: %w", err)
}
err = tree.SetActor(idAddr, &newActor)
if err != nil {
return xerrors.Errorf("setting new msig actor state: %w", err)
}
if err := doTransfer(cb, tree, addr, idAddr, newIbal); err != nil {
return xerrors.Errorf("transferring split msig balance: %w", err)
}
i++
}
return nil
}
func makeKeyAddr(splitAddr address.Address, count uint64) (address.Address, error) {
var b bytes.Buffer
if err := splitAddr.MarshalCBOR(&b); err != nil {
return address.Undef, xerrors.Errorf("marshalling split address: %w", err)
}
if err := binary.Write(&b, binary.BigEndian, count); err != nil {
return address.Undef, xerrors.Errorf("writing count into a buffer: %w", err)
}
if err := binary.Write(&b, binary.BigEndian, []byte("Ignition upgrade")); err != nil {
return address.Undef, xerrors.Errorf("writing fork name into a buffer: %w", err)
}
addr, err := address.NewActorAddress(b.Bytes())
if err != nil {
return address.Undef, xerrors.Errorf("create actor address: %w", err)
}
return addr, nil
}
func resetGenesisMsigs(ctx context.Context, sm *StateManager, store adt0.Store, tree *state.StateTree) error {
gb, err := sm.cs.GetGenesis()
if err != nil {
return xerrors.Errorf("getting genesis block: %w", err)
}
gts, err := types.NewTipSet([]*types.BlockHeader{gb})
if err != nil {
return xerrors.Errorf("getting genesis tipset: %w", err)
}
cst := cbor.NewCborStore(sm.cs.Blockstore())
genesisTree, err := state.LoadStateTree(cst, gts.ParentState())
if err != nil {
return xerrors.Errorf("loading state tree: %w", err)
}
err = genesisTree.ForEach(func(addr address.Address, genesisActor *types.Actor) error {
if genesisActor.Code == builtin0.MultisigActorCodeID {
currActor, err := tree.GetActor(addr)
if err != nil {
return xerrors.Errorf("loading actor: %w", err)
}
var currState multisig0.State
if err := store.Get(ctx, currActor.Head, &currState); err != nil {
return xerrors.Errorf("reading multisig state: %w", err)
}
currState.StartEpoch = build.UpgradeLiftoffHeight
currActor.Head, err = store.Put(ctx, &currState)
if err != nil {
return xerrors.Errorf("writing new multisig state: %w", err)
}
if err := tree.SetActor(addr, currActor); err != nil {
return xerrors.Errorf("setting multisig actor: %w", err)
}
}
return nil
})
if err != nil {
return xerrors.Errorf("iterating over genesis actors: %w", err)
} }
return nil return nil

View File

@ -8,17 +8,15 @@ 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/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init" init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/runtime" "github.com/filecoin-project/specs-actors/actors/runtime"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/actors/aerrors"
lotusinit "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"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/stmgr" "github.com/filecoin-project/lotus/chain/stmgr"
. "github.com/filecoin-project/lotus/chain/stmgr" . "github.com/filecoin-project/lotus/chain/stmgr"
@ -27,17 +25,16 @@ import (
_ "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"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
) )
func init() { func init() {
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{ policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
abi.RegisteredSealProof_StackedDrg2KiBV1: {}, policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
} policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
power.ConsensusMinerMinPower = big.NewInt(2048)
verifreg.MinVerifiedDealSize = big.NewInt(256)
} }
const testForkHeight = 40 const testForkHeight = 40
@ -118,38 +115,43 @@ func TestForkHeightTriggers(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
stmgr.ForksAtHeight[testForkHeight] = func(ctx context.Context, sm *StateManager, st types.StateTree, ts *types.TipSet) error { stmgr.ForksAtHeight[testForkHeight] = func(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, ts *types.TipSet) (cid.Cid, error) {
cst := cbor.NewCborStore(sm.ChainStore().Blockstore()) cst := cbor.NewCborStore(sm.ChainStore().Blockstore())
st, err := sm.StateTree(root)
if err != nil {
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
}
act, err := st.GetActor(taddr) act, err := st.GetActor(taddr)
if err != nil { if err != nil {
return err return cid.Undef, err
} }
var tas testActorState var tas testActorState
if err := cst.Get(ctx, act.Head, &tas); err != nil { if err := cst.Get(ctx, act.Head, &tas); err != nil {
return xerrors.Errorf("in fork handler, failed to run get: %w", err) return cid.Undef, xerrors.Errorf("in fork handler, failed to run get: %w", err)
} }
tas.HasUpgraded = 55 tas.HasUpgraded = 55
ns, err := cst.Put(ctx, &tas) ns, err := cst.Put(ctx, &tas)
if err != nil { if err != nil {
return err return cid.Undef, err
} }
act.Head = ns act.Head = ns
if err := st.SetActor(taddr, act); err != nil { if err := st.SetActor(taddr, act); err != nil {
return err return cid.Undef, err
} }
return nil return st.Flush(ctx)
} }
inv.Register(builtin.PaymentChannelActorCodeID, &testActor{}, &testActorState{}) inv.Register(builtin.PaymentChannelActorCodeID, &testActor{}, &testActorState{})
sm.SetVMConstructor(func(vmopt *vm.VMOpts) (*vm.VM, error) { sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (*vm.VM, error) {
nvm, err := vm.NewVM(vmopt) nvm, err := vm.NewVM(ctx, vmopt)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -168,7 +170,7 @@ func TestForkHeightTriggers(t *testing.T) {
m := &types.Message{ m := &types.Message{
From: cg.Banker(), From: cg.Banker(),
To: builtin.InitActorAddr, To: lotusinit.Address,
Method: builtin.MethodsInit.Exec, Method: builtin.MethodsInit.Exec,
Params: enc, Params: enc,
GasLimit: types.TestGasLimit, GasLimit: types.TestGasLimit,

View File

@ -2,7 +2,6 @@ package stmgr
import ( import (
"context" "context"
"reflect"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -12,144 +11,56 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/util/adt"
) )
type StateTreeCB func(state *state.StateTree) error func (sm *StateManager) ParentStateTsk(tsk types.TipSetKey) (*state.StateTree, error) {
func (sm *StateManager) WithParentStateTsk(tsk types.TipSetKey, cb StateTreeCB) error {
ts, err := sm.cs.GetTipSetFromKey(tsk) ts, err := sm.cs.GetTipSetFromKey(tsk)
if err != nil { if err != nil {
return xerrors.Errorf("loading tipset %s: %w", tsk, err) return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
} }
return sm.ParentState(ts)
}
func (sm *StateManager) ParentState(ts *types.TipSet) (*state.StateTree, error) {
cst := cbor.NewCborStore(sm.cs.Blockstore()) cst := cbor.NewCborStore(sm.cs.Blockstore())
state, err := state.LoadStateTree(cst, sm.parentState(ts)) state, err := state.LoadStateTree(cst, sm.parentState(ts))
if err != nil { if err != nil {
return xerrors.Errorf("load state tree: %w", err) return nil, xerrors.Errorf("load state tree: %w", err)
} }
return cb(state) return state, nil
} }
func (sm *StateManager) WithParentState(ts *types.TipSet, cb StateTreeCB) error { func (sm *StateManager) StateTree(st cid.Cid) (*state.StateTree, error) {
cst := cbor.NewCborStore(sm.cs.Blockstore())
state, err := state.LoadStateTree(cst, sm.parentState(ts))
if err != nil {
return xerrors.Errorf("load state tree: %w", err)
}
return cb(state)
}
func (sm *StateManager) WithStateTree(st cid.Cid, cb StateTreeCB) error {
cst := cbor.NewCborStore(sm.cs.Blockstore()) cst := cbor.NewCborStore(sm.cs.Blockstore())
state, err := state.LoadStateTree(cst, st) state, err := state.LoadStateTree(cst, st)
if err != nil { if err != nil {
return xerrors.Errorf("load state tree: %w", err) return nil, xerrors.Errorf("load state tree: %w", err)
} }
return cb(state) return state, nil
} }
type ActorCB func(act *types.Actor) error func (sm *StateManager) LoadActor(_ context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, error) {
state, err := sm.ParentState(ts)
func GetActor(out *types.Actor) ActorCB { if err != nil {
return func(act *types.Actor) error { return nil, err
*out = *act
return nil
} }
return state.GetActor(addr)
} }
func (sm *StateManager) WithActor(addr address.Address, cb ActorCB) StateTreeCB { func (sm *StateManager) LoadActorTsk(_ context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error) {
return func(state *state.StateTree) error { state, err := sm.ParentStateTsk(tsk)
act, err := state.GetActor(addr) if err != nil {
if err != nil { return nil, err
return xerrors.Errorf("get actor: %w", err)
}
return cb(act)
} }
return state.GetActor(addr)
} }
// WithActorState usage: func (sm *StateManager) LoadActorRaw(_ context.Context, addr address.Address, st cid.Cid) (*types.Actor, error) {
// Option 1: WithActorState(ctx, idAddr, func(store adt.Store, st *ActorStateType) error {...}) state, err := sm.StateTree(st)
// Option 2: WithActorState(ctx, idAddr, actorStatePtr) if err != nil {
func (sm *StateManager) WithActorState(ctx context.Context, out interface{}) ActorCB { return nil, err
return func(act *types.Actor) error {
store := sm.cs.Store(ctx)
outCallback := reflect.TypeOf(out).Kind() == reflect.Func
var st reflect.Value
if outCallback {
st = reflect.New(reflect.TypeOf(out).In(1).Elem())
} else {
st = reflect.ValueOf(out)
}
if err := store.Get(ctx, act.Head, st.Interface()); err != nil {
return xerrors.Errorf("read actor head: %w", err)
}
if outCallback {
out := reflect.ValueOf(out).Call([]reflect.Value{reflect.ValueOf(store), st})
if !out[0].IsNil() && out[0].Interface().(error) != nil {
return out[0].Interface().(error)
}
}
return nil
}
}
type DeadlinesCB func(store adt.Store, deadlines *miner.Deadlines) error
func (sm *StateManager) WithDeadlines(cb DeadlinesCB) func(store adt.Store, mas *miner.State) error {
return func(store adt.Store, mas *miner.State) error {
deadlines, err := mas.LoadDeadlines(store)
if err != nil {
return err
}
return cb(store, deadlines)
}
}
type DeadlineCB func(store adt.Store, idx uint64, deadline *miner.Deadline) error
func (sm *StateManager) WithDeadline(idx uint64, cb DeadlineCB) DeadlinesCB {
return func(store adt.Store, deadlines *miner.Deadlines) error {
d, err := deadlines.LoadDeadline(store, idx)
if err != nil {
return err
}
return cb(store, idx, d)
}
}
func (sm *StateManager) WithEachDeadline(cb DeadlineCB) DeadlinesCB {
return func(store adt.Store, deadlines *miner.Deadlines) error {
return deadlines.ForEach(store, func(dlIdx uint64, dl *miner.Deadline) error {
return cb(store, dlIdx, dl)
})
}
}
type PartitionCB func(store adt.Store, idx uint64, partition *miner.Partition) error
func (sm *StateManager) WithEachPartition(cb PartitionCB) DeadlineCB {
return func(store adt.Store, idx uint64, deadline *miner.Deadline) error {
parts, err := deadline.PartitionsArray(store)
if err != nil {
return err
}
var partition miner.Partition
return parts.ForEach(&partition, func(i int64) error {
p := partition
return cb(store, uint64(i), &p)
})
} }
return state.GetActor(addr)
} }

View File

@ -5,35 +5,35 @@ import (
"fmt" "fmt"
"sync" "sync"
"github.com/filecoin-project/go-state-types/network" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"golang.org/x/xerrors"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"go.opencensus.io/trace" "go.opencensus.io/trace"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
) )
var log = logging.Logger("statemgr") var log = logging.Logger("statemgr")
@ -41,12 +41,13 @@ var log = logging.Logger("statemgr")
type StateManager struct { type StateManager struct {
cs *store.ChainStore cs *store.ChainStore
stCache map[string][]cid.Cid stCache map[string][]cid.Cid
compWait map[string]chan struct{} compWait map[string]chan struct{}
stlk sync.Mutex stlk sync.Mutex
genesisMsigLk sync.Mutex genesisMsigLk sync.Mutex
newVM func(*vm.VMOpts) (*vm.VM, error) newVM func(context.Context, *vm.VMOpts) (*vm.VM, error)
genInfo *genesisInfo preIgnitionGenInfos *genesisInfo
postIgnitionGenInfos *genesisInfo
} }
func NewStateManager(cs *store.ChainStore) *StateManager { func NewStateManager(cs *store.ChainStore) *StateManager {
@ -123,9 +124,8 @@ func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (st c
return st, rec, nil return st, rec, nil
} }
func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (cid.Cid, []*api.InvocResult, error) { func traceFunc(trace *[]*api.InvocResult) func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
var trace []*api.InvocResult return func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
st, _, err := sm.computeTipSetState(ctx, ts, func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
ir := &api.InvocResult{ ir := &api.InvocResult{
Msg: msg, Msg: msg,
MsgRct: &ret.MessageReceipt, MsgRct: &ret.MessageReceipt,
@ -135,9 +135,14 @@ func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (c
if ret.ActorErr != nil { if ret.ActorErr != nil {
ir.Error = ret.ActorErr.Error() ir.Error = ret.ActorErr.Error()
} }
trace = append(trace, ir) *trace = append(*trace, ir)
return nil return nil
}) }
}
func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (cid.Cid, []*api.InvocResult, error) {
var trace []*api.InvocResult
st, _, err := sm.computeTipSetState(ctx, ts, traceFunc(&trace))
if err != nil { if err != nil {
return cid.Undef, nil, err return cid.Undef, nil, err
} }
@ -149,38 +154,42 @@ type ExecCallback func(cid.Cid, *types.Message, *vm.ApplyRet) error
func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEpoch, pstate cid.Cid, bms []store.BlockMessages, epoch abi.ChainEpoch, r vm.Rand, cb ExecCallback, baseFee abi.TokenAmount, ts *types.TipSet) (cid.Cid, cid.Cid, error) { func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEpoch, pstate cid.Cid, bms []store.BlockMessages, epoch abi.ChainEpoch, r vm.Rand, cb ExecCallback, baseFee abi.TokenAmount, ts *types.TipSet) (cid.Cid, cid.Cid, error) {
vmopt := &vm.VMOpts{ makeVmWithBaseState := func(base cid.Cid) (*vm.VM, error) {
StateBase: pstate, vmopt := &vm.VMOpts{
Epoch: epoch, StateBase: base,
Rand: r, Epoch: epoch,
Bstore: sm.cs.Blockstore(), Rand: r,
Syscalls: sm.cs.VMSys(), Bstore: sm.cs.Blockstore(),
CircSupplyCalc: sm.GetCirculatingSupply, Syscalls: sm.cs.VMSys(),
NtwkVersion: sm.GetNtwkVersion, CircSupplyCalc: sm.GetCirculatingSupply,
BaseFee: baseFee, NtwkVersion: sm.GetNtwkVersion,
BaseFee: baseFee,
}
return sm.newVM(ctx, vmopt)
} }
vmi, err := sm.newVM(vmopt) vmi, err := makeVmWithBaseState(pstate)
if err != nil { if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err) return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err)
} }
runCron := func() error { runCron := func() error {
// TODO: this nonce-getting is a tiny bit ugly // TODO: this nonce-getting is a tiny bit ugly
ca, err := vmi.StateTree().GetActor(builtin.SystemActorAddr) ca, err := vmi.StateTree().GetActor(builtin0.SystemActorAddr)
if err != nil { if err != nil {
return err return err
} }
cronMsg := &types.Message{ cronMsg := &types.Message{
To: builtin.CronActorAddr, To: builtin0.CronActorAddr,
From: builtin.SystemActorAddr, From: builtin0.SystemActorAddr,
Nonce: ca.Nonce, Nonce: ca.Nonce,
Value: types.NewInt(0), Value: types.NewInt(0),
GasFeeCap: types.NewInt(0), GasFeeCap: types.NewInt(0),
GasPremium: types.NewInt(0), GasPremium: types.NewInt(0),
GasLimit: build.BlockGasLimit * 10000, // Make super sure this is never too little GasLimit: build.BlockGasLimit * 10000, // Make super sure this is never too little
Method: builtin.MethodsCron.EpochTick, Method: builtin0.MethodsCron.EpochTick,
Params: nil, Params: nil,
} }
ret, err := vmi.ApplyImplicitMessage(ctx, cronMsg) ret, err := vmi.ApplyImplicitMessage(ctx, cronMsg)
@ -201,19 +210,33 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
for i := parentEpoch; i < epoch; i++ { for i := parentEpoch; i < epoch; i++ {
// handle state forks // handle state forks
err = sm.handleStateForks(ctx, vmi.StateTree(), i, ts) // XXX: The state tree
newState, err := sm.handleStateForks(ctx, pstate, i, cb, ts)
if err != nil { if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("error handling state forks: %w", err) return cid.Undef, cid.Undef, xerrors.Errorf("error handling state forks: %w", err)
} }
if pstate != newState {
vmi, err = makeVmWithBaseState(newState)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err)
}
}
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(); err != nil {
return cid.Cid{}, cid.Cid{}, err return cid.Cid{}, cid.Cid{}, err
} }
newState, err = vmi.Flush(ctx)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("flushing vm: %w", err)
}
} }
vmi.SetBlockHeight(i + 1) vmi.SetBlockHeight(i + 1)
pstate = newState
} }
var receipts []cbg.CBORMarshaler var receipts []cbg.CBORMarshaler
@ -244,7 +267,6 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
processedMsgs[m.Cid()] = true processedMsgs[m.Cid()] = true
} }
var err error
params, err := actors.SerializeParams(&reward.AwardBlockRewardParams{ params, err := actors.SerializeParams(&reward.AwardBlockRewardParams{
Miner: b.Miner, Miner: b.Miner,
Penalty: penalty, Penalty: penalty,
@ -255,24 +277,24 @@ 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, err := vmi.StateTree().GetActor(builtin.SystemActorAddr) sysAct, actErr := vmi.StateTree().GetActor(builtin0.SystemActorAddr)
if err != nil { if actErr != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get system actor: %w", err) return cid.Undef, cid.Undef, xerrors.Errorf("failed to get system actor: %w", err)
} }
rwMsg := &types.Message{ rwMsg := &types.Message{
From: builtin.SystemActorAddr, From: builtin0.SystemActorAddr,
To: builtin.RewardActorAddr, To: reward.Address,
Nonce: sysAct.Nonce, Nonce: sysAct.Nonce,
Value: types.NewInt(0), Value: types.NewInt(0),
GasFeeCap: types.NewInt(0), GasFeeCap: types.NewInt(0),
GasPremium: types.NewInt(0), GasPremium: types.NewInt(0),
GasLimit: 1 << 30, GasLimit: 1 << 30,
Method: builtin.MethodsReward.AwardBlockReward, Method: builtin0.MethodsReward.AwardBlockReward,
Params: params, Params: params,
} }
ret, err := vmi.ApplyImplicitMessage(ctx, rwMsg) ret, actErr := vmi.ApplyImplicitMessage(ctx, rwMsg)
if err != nil { if actErr != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to apply reward message for miner %s: %w", b.Miner, err) return cid.Undef, cid.Undef, xerrors.Errorf("failed to apply reward message for miner %s: %w", b.Miner, err)
} }
if cb != nil { if cb != nil {
@ -290,7 +312,11 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
return cid.Cid{}, cid.Cid{}, err return cid.Cid{}, cid.Cid{}, err
} }
rectarr := adt.MakeEmptyArray(sm.cs.Store(ctx)) // XXX: Is the height correct? Or should it be epoch-1?
rectarr, err := adt.NewArray(sm.cs.Store(ctx), builtin.VersionForNetwork(sm.GetNtwkVersion(ctx, epoch)))
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to create receipts amt: %w", err)
}
for i, receipt := range receipts { for i, receipt := range receipts {
if err := rectarr.Set(uint64(i), receipt); err != nil { if err := rectarr.Set(uint64(i), receipt); err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to build receipts amt: %w", err) return cid.Undef, cid.Undef, xerrors.Errorf("failed to build receipts amt: %w", err)
@ -601,10 +627,9 @@ func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet
default: default:
} }
var act types.Actor act, err := sm.LoadActor(ctx, m.VMMessage().From, cur)
err := sm.WithParentState(cur, sm.WithActor(m.VMMessage().From, GetActor(&act)))
if err != nil { if err != nil {
return nil, nil, cid.Undef, err return nil, nil, cid.Cid{}, err
} }
// we either have no messages from the sender, or the latest message we found has a lower nonce than the one being searched for, // we either have no messages from the sender, or the latest message we found has a lower nonce than the one being searched for,
@ -689,17 +714,13 @@ func (sm *StateManager) ListAllActors(ctx context.Context, ts *types.TipSet) ([]
return nil, err return nil, err
} }
r, err := adt.AsMap(sm.cs.Store(ctx), st) stateTree, err := sm.StateTree(st)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var out []address.Address var out []address.Address
err = r.ForEach(nil, func(k string) error { err = stateTree.ForEach(func(addr address.Address, act *types.Actor) error {
addr, err := address.NewFromBytes([]byte(k))
if err != nil {
return xerrors.Errorf("address in state tree was not valid: %w", err)
}
out = append(out, addr) out = append(out, addr)
return nil return nil
}) })
@ -711,8 +732,17 @@ func (sm *StateManager) ListAllActors(ctx context.Context, ts *types.TipSet) ([]
} }
func (sm *StateManager) MarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (api.MarketBalance, error) { func (sm *StateManager) MarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (api.MarketBalance, error) {
var state market.State st, err := sm.ParentState(ts)
_, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts) if err != nil {
return api.MarketBalance{}, err
}
act, err := st.GetActor(market.Address)
if err != nil {
return api.MarketBalance{}, err
}
mstate, err := market.Load(sm.cs.Store(ctx), act)
if err != nil { if err != nil {
return api.MarketBalance{}, err return api.MarketBalance{}, err
} }
@ -724,7 +754,7 @@ func (sm *StateManager) MarketBalance(ctx context.Context, addr address.Address,
var out api.MarketBalance var out api.MarketBalance
et, err := adt.AsBalanceTable(sm.cs.Store(ctx), state.EscrowTable) et, err := mstate.EscrowTable()
if err != nil { if err != nil {
return api.MarketBalance{}, err return api.MarketBalance{}, err
} }
@ -733,7 +763,7 @@ func (sm *StateManager) MarketBalance(ctx context.Context, addr address.Address,
return api.MarketBalance{}, xerrors.Errorf("getting escrow balance: %w", err) return api.MarketBalance{}, xerrors.Errorf("getting escrow balance: %w", err)
} }
lt, err := adt.AsBalanceTable(sm.cs.Store(ctx), state.LockedTable) lt, err := mstate.LockedTable()
if err != nil { if err != nil {
return api.MarketBalance{}, err return api.MarketBalance{}, err
} }
@ -774,12 +804,12 @@ func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) err
return nil return nil
} }
func (sm *StateManager) SetVMConstructor(nvm func(*vm.VMOpts) (*vm.VM, error)) { func (sm *StateManager) SetVMConstructor(nvm func(context.Context, *vm.VMOpts) (*vm.VM, error)) {
sm.newVM = nvm sm.newVM = nvm
} }
type genesisInfo struct { type genesisInfo struct {
genesisMsigs []multisig.State genesisMsigs []msig0.State
// info about the Accounts in the genesis state // info about the Accounts in the genesis state
genesisActors []genesisActor genesisActors []genesisActor
genesisPledge abi.TokenAmount genesisPledge abi.TokenAmount
@ -827,51 +857,56 @@ func (sm *StateManager) setupGenesisActors(ctx context.Context) error {
return xerrors.Errorf("setting up genesis pledge: %w", err) return xerrors.Errorf("setting up genesis pledge: %w", err)
} }
r, err := adt.AsMap(sm.cs.Store(ctx), st)
if err != nil {
return xerrors.Errorf("getting genesis actors: %w", err)
}
totalsByEpoch := make(map[abi.ChainEpoch]abi.TokenAmount) totalsByEpoch := make(map[abi.ChainEpoch]abi.TokenAmount)
var act types.Actor err = sTree.ForEach(func(kaddr address.Address, act *types.Actor) error {
err = r.ForEach(&act, func(k string) error { if act.IsMultisigActor() {
if act.Code == builtin.MultisigActorCodeID { s, err := multisig.Load(sm.cs.Store(ctx), act)
var s multisig.State
err := sm.cs.Store(ctx).Get(ctx, act.Head, &s)
if err != nil { if err != nil {
return err return err
} }
if s.StartEpoch != 0 { se, err := s.StartEpoch()
if err != nil {
return err
}
if se != 0 {
return xerrors.New("genesis multisig doesn't start vesting at epoch 0!") return xerrors.New("genesis multisig doesn't start vesting at epoch 0!")
} }
ot, f := totalsByEpoch[s.UnlockDuration] ud, err := s.UnlockDuration()
if f { if err != nil {
totalsByEpoch[s.UnlockDuration] = big.Add(ot, s.InitialBalance) return err
} else {
totalsByEpoch[s.UnlockDuration] = s.InitialBalance
} }
} else if act.Code == builtin.AccountActorCodeID { ib, err := s.InitialBalance()
if err != nil {
return err
}
ot, f := totalsByEpoch[ud]
if f {
totalsByEpoch[ud] = big.Add(ot, ib)
} else {
totalsByEpoch[ud] = ib
}
} else if act.IsAccountActor() {
// should exclude burnt funds actor and "remainder account actor" // should exclude burnt funds actor and "remainder account actor"
// should only ever be "faucet" accounts in testnets // should only ever be "faucet" accounts in testnets
kaddr, err := address.NewFromBytes([]byte(k)) if kaddr == builtin0.BurntFundsActorAddr {
return nil
}
kid, err := sTree.LookupID(kaddr)
if err != nil { if err != nil {
return xerrors.Errorf("decoding address: %w", err) return xerrors.Errorf("resolving address: %w", err)
} }
if kaddr != builtin.BurntFundsActorAddr { gi.genesisActors = append(gi.genesisActors, genesisActor{
kid, err := sTree.LookupID(kaddr) addr: kid,
if err != nil { initBal: act.Balance,
return xerrors.Errorf("resolving address: %w", err) })
}
gi.genesisActors = append(gi.genesisActors, genesisActor{
addr: kid,
initBal: act.Balance,
})
}
} }
return nil return nil
}) })
@ -880,9 +915,10 @@ func (sm *StateManager) setupGenesisActors(ctx context.Context) error {
return xerrors.Errorf("error setting up genesis infos: %w", err) return xerrors.Errorf("error setting up genesis infos: %w", err)
} }
gi.genesisMsigs = make([]multisig.State, 0, len(totalsByEpoch)) // TODO: use network upgrade abstractions or always start at actors v0?
gi.genesisMsigs = make([]msig0.State, 0, len(totalsByEpoch))
for k, v := range totalsByEpoch { for k, v := range totalsByEpoch {
ns := multisig.State{ ns := msig0.State{
InitialBalance: v, InitialBalance: v,
UnlockDuration: k, UnlockDuration: k,
PendingTxns: cid.Undef, PendingTxns: cid.Undef,
@ -890,7 +926,7 @@ func (sm *StateManager) setupGenesisActors(ctx context.Context) error {
gi.genesisMsigs = append(gi.genesisMsigs, ns) gi.genesisMsigs = append(gi.genesisMsigs, ns)
} }
sm.genInfo = &gi sm.preIgnitionGenInfos = &gi
return nil return nil
} }
@ -898,7 +934,7 @@ func (sm *StateManager) setupGenesisActors(ctx context.Context) error {
// sets up information about the actors in the genesis state // sets up information about the actors in the genesis state
// For testnet we use a hardcoded set of multisig states, instead of what's actually in the genesis multisigs // For testnet we use a hardcoded set of multisig states, instead of what's actually in the genesis multisigs
// We also do not consider ANY account actors (including the faucet) // We also do not consider ANY account actors (including the faucet)
func (sm *StateManager) setupGenesisActorsTestnet(ctx context.Context) error { func (sm *StateManager) setupPreIgnitionGenesisActorsTestnet(ctx context.Context) error {
gi := genesisInfo{} gi := genesisInfo{}
@ -936,30 +972,30 @@ func (sm *StateManager) setupGenesisActorsTestnet(ctx context.Context) error {
totalsByEpoch := make(map[abi.ChainEpoch]abi.TokenAmount) totalsByEpoch := make(map[abi.ChainEpoch]abi.TokenAmount)
// 6 months // 6 months
sixMonths := abi.ChainEpoch(183 * builtin.EpochsInDay) sixMonths := abi.ChainEpoch(183 * builtin0.EpochsInDay)
totalsByEpoch[sixMonths] = big.NewInt(49_929_341) totalsByEpoch[sixMonths] = big.NewInt(49_929_341)
totalsByEpoch[sixMonths] = big.Add(totalsByEpoch[sixMonths], big.NewInt(32_787_700)) totalsByEpoch[sixMonths] = big.Add(totalsByEpoch[sixMonths], big.NewInt(32_787_700))
// 1 year // 1 year
oneYear := abi.ChainEpoch(365 * builtin.EpochsInDay) oneYear := abi.ChainEpoch(365 * builtin0.EpochsInDay)
totalsByEpoch[oneYear] = big.NewInt(22_421_712) totalsByEpoch[oneYear] = big.NewInt(22_421_712)
// 2 years // 2 years
twoYears := abi.ChainEpoch(2 * 365 * builtin.EpochsInDay) twoYears := abi.ChainEpoch(2 * 365 * builtin0.EpochsInDay)
totalsByEpoch[twoYears] = big.NewInt(7_223_364) totalsByEpoch[twoYears] = big.NewInt(7_223_364)
// 3 years // 3 years
threeYears := abi.ChainEpoch(3 * 365 * builtin.EpochsInDay) threeYears := abi.ChainEpoch(3 * 365 * builtin0.EpochsInDay)
totalsByEpoch[threeYears] = big.NewInt(87_637_883) totalsByEpoch[threeYears] = big.NewInt(87_637_883)
// 6 years // 6 years
sixYears := abi.ChainEpoch(6 * 365 * builtin.EpochsInDay) sixYears := abi.ChainEpoch(6 * 365 * builtin0.EpochsInDay)
totalsByEpoch[sixYears] = big.NewInt(100_000_000) totalsByEpoch[sixYears] = big.NewInt(100_000_000)
totalsByEpoch[sixYears] = big.Add(totalsByEpoch[sixYears], big.NewInt(300_000_000)) totalsByEpoch[sixYears] = big.Add(totalsByEpoch[sixYears], big.NewInt(300_000_000))
gi.genesisMsigs = make([]multisig.State, 0, len(totalsByEpoch)) gi.genesisMsigs = make([]msig0.State, 0, len(totalsByEpoch))
for k, v := range totalsByEpoch { for k, v := range totalsByEpoch {
ns := multisig.State{ ns := msig0.State{
InitialBalance: v, InitialBalance: v,
UnlockDuration: k, UnlockDuration: k,
PendingTxns: cid.Undef, PendingTxns: cid.Undef,
@ -967,7 +1003,87 @@ func (sm *StateManager) setupGenesisActorsTestnet(ctx context.Context) error {
gi.genesisMsigs = append(gi.genesisMsigs, ns) gi.genesisMsigs = append(gi.genesisMsigs, ns)
} }
sm.genInfo = &gi sm.preIgnitionGenInfos = &gi
return nil
}
// sets up information about the actors in the genesis state, post the ignition fork
func (sm *StateManager) setupPostIgnitionGenesisActors(ctx context.Context) error {
gi := genesisInfo{}
gb, err := sm.cs.GetGenesis()
if err != nil {
return xerrors.Errorf("getting genesis block: %w", err)
}
gts, err := types.NewTipSet([]*types.BlockHeader{gb})
if err != nil {
return xerrors.Errorf("getting genesis tipset: %w", err)
}
st, _, err := sm.TipSetState(ctx, gts)
if err != nil {
return xerrors.Errorf("getting genesis tipset state: %w", err)
}
cst := cbor.NewCborStore(sm.cs.Blockstore())
sTree, err := state.LoadStateTree(cst, st)
if err != nil {
return xerrors.Errorf("loading state tree: %w", err)
}
// Unnecessary, should be removed
gi.genesisMarketFunds, err = getFilMarketLocked(ctx, sTree)
if err != nil {
return xerrors.Errorf("setting up genesis market funds: %w", err)
}
// Unnecessary, should be removed
gi.genesisPledge, err = getFilPowerLocked(ctx, sTree)
if err != nil {
return xerrors.Errorf("setting up genesis pledge: %w", err)
}
totalsByEpoch := make(map[abi.ChainEpoch]abi.TokenAmount)
// 6 months
sixMonths := abi.ChainEpoch(183 * builtin0.EpochsInDay)
totalsByEpoch[sixMonths] = big.NewInt(49_929_341)
totalsByEpoch[sixMonths] = big.Add(totalsByEpoch[sixMonths], big.NewInt(32_787_700))
// 1 year
oneYear := abi.ChainEpoch(365 * builtin0.EpochsInDay)
totalsByEpoch[oneYear] = big.NewInt(22_421_712)
// 2 years
twoYears := abi.ChainEpoch(2 * 365 * builtin0.EpochsInDay)
totalsByEpoch[twoYears] = big.NewInt(7_223_364)
// 3 years
threeYears := abi.ChainEpoch(3 * 365 * builtin0.EpochsInDay)
totalsByEpoch[threeYears] = big.NewInt(87_637_883)
// 6 years
sixYears := abi.ChainEpoch(6 * 365 * builtin0.EpochsInDay)
totalsByEpoch[sixYears] = big.NewInt(100_000_000)
totalsByEpoch[sixYears] = big.Add(totalsByEpoch[sixYears], big.NewInt(300_000_000))
gi.genesisMsigs = make([]msig0.State, 0, len(totalsByEpoch))
for k, v := range totalsByEpoch {
ns := msig0.State{
// In the pre-ignition logic, we incorrectly set this value in Fil, not attoFil, an off-by-10^18 error
InitialBalance: big.Mul(v, big.NewInt(int64(build.FilecoinPrecision))),
UnlockDuration: k,
PendingTxns: cid.Undef,
// In the pre-ignition logic, the start epoch was 0. This changes in the fork logic of the Ignition upgrade itself.
StartEpoch: build.UpgradeLiftoffHeight,
}
gi.genesisMsigs = append(gi.genesisMsigs, ns)
}
sm.postIgnitionGenInfos = &gi
return nil return nil
} }
@ -977,13 +1093,23 @@ func (sm *StateManager) setupGenesisActorsTestnet(ctx context.Context) error {
// - For Accounts, it counts max(currentBalance - genesisBalance, 0). // - For Accounts, it counts max(currentBalance - genesisBalance, 0).
func (sm *StateManager) GetFilVested(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) { func (sm *StateManager) GetFilVested(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) {
vf := big.Zero() vf := big.Zero()
for _, v := range sm.genInfo.genesisMsigs { if height <= build.UpgradeIgnitionHeight {
au := big.Sub(v.InitialBalance, v.AmountLocked(height)) for _, v := range sm.preIgnitionGenInfos.genesisMsigs {
vf = big.Add(vf, au) au := big.Sub(v.InitialBalance, v.AmountLocked(height))
vf = big.Add(vf, au)
}
} else {
for _, v := range sm.postIgnitionGenInfos.genesisMsigs {
// In the pre-ignition logic, we simply called AmountLocked(height), assuming startEpoch was 0.
// The start epoch changed in the Ignition upgrade.
au := big.Sub(v.InitialBalance, v.AmountLocked(height-v.StartEpoch))
vf = big.Add(vf, au)
}
} }
// there should not be any such accounts in testnet (and also none in mainnet?) // there should not be any such accounts in testnet (and also none in mainnet?)
for _, v := range sm.genInfo.genesisActors { // continue to use preIgnitionGenInfos, nothing changed at the Ignition epoch
for _, v := range sm.preIgnitionGenInfos.genesisActors {
act, err := st.GetActor(v.addr) act, err := st.GetActor(v.addr)
if err != nil { if err != nil {
return big.Zero(), xerrors.Errorf("failed to get actor: %w", err) return big.Zero(), xerrors.Errorf("failed to get actor: %w", err)
@ -995,53 +1121,54 @@ func (sm *StateManager) GetFilVested(ctx context.Context, height abi.ChainEpoch,
} }
} }
vf = big.Add(vf, sm.genInfo.genesisPledge) // continue to use preIgnitionGenInfos, nothing changed at the Ignition epoch
vf = big.Add(vf, sm.genInfo.genesisMarketFunds) vf = big.Add(vf, sm.preIgnitionGenInfos.genesisPledge)
// continue to use preIgnitionGenInfos, nothing changed at the Ignition epoch
vf = big.Add(vf, sm.preIgnitionGenInfos.genesisMarketFunds)
return vf, nil return vf, nil
} }
func GetFilMined(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) { func GetFilMined(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) {
ractor, err := st.GetActor(builtin.RewardActorAddr) ractor, err := st.GetActor(reward.Address)
if err != nil { if err != nil {
return big.Zero(), xerrors.Errorf("failed to load reward actor state: %w", err) return big.Zero(), xerrors.Errorf("failed to load reward actor state: %w", err)
} }
var rst reward.State rst, err := reward.Load(adt.WrapStore(ctx, st.Store), ractor)
if err := st.Store.Get(ctx, ractor.Head, &rst); err != nil { if err != nil {
return big.Zero(), xerrors.Errorf("failed to load reward state: %w", err) return big.Zero(), err
} }
return rst.TotalMined, nil return rst.TotalStoragePowerReward()
} }
func getFilMarketLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) { func getFilMarketLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) {
mactor, err := st.GetActor(builtin.StorageMarketActorAddr) act, err := st.GetActor(market.Address)
if err != nil { if err != nil {
return big.Zero(), xerrors.Errorf("failed to load market actor: %w", err) return big.Zero(), xerrors.Errorf("failed to load market actor: %w", err)
} }
var mst market.State mst, err := market.Load(adt.WrapStore(ctx, st.Store), act)
if err := st.Store.Get(ctx, mactor.Head, &mst); err != nil { if err != nil {
return big.Zero(), xerrors.Errorf("failed to load market state: %w", err) return big.Zero(), xerrors.Errorf("failed to load market state: %w", err)
} }
fml := types.BigAdd(mst.TotalClientLockedCollateral, mst.TotalProviderLockedCollateral) return mst.TotalLocked()
fml = types.BigAdd(fml, mst.TotalClientStorageFee)
return fml, nil
} }
func getFilPowerLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) { func getFilPowerLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) {
pactor, err := st.GetActor(builtin.StoragePowerActorAddr) pactor, err := st.GetActor(power.Address)
if err != nil { if err != nil {
return big.Zero(), xerrors.Errorf("failed to load power actor: %w", err) return big.Zero(), xerrors.Errorf("failed to load power actor: %w", err)
} }
var pst power.State pst, err := power.Load(adt.WrapStore(ctx, st.Store), pactor)
if err := st.Store.Get(ctx, pactor.Head, &pst); err != nil { if err != nil {
return big.Zero(), xerrors.Errorf("failed to load power state: %w", err) return big.Zero(), xerrors.Errorf("failed to load power state: %w", err)
} }
return pst.TotalPledgeCollateral, nil
return pst.TotalLocked()
} }
func (sm *StateManager) GetFilLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) { func (sm *StateManager) GetFilLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) {
@ -1060,7 +1187,7 @@ func (sm *StateManager) GetFilLocked(ctx context.Context, st *state.StateTree) (
} }
func GetFilBurnt(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) { func GetFilBurnt(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) {
burnt, err := st.GetActor(builtin.BurntFundsActorAddr) burnt, err := st.GetActor(builtin0.BurntFundsActorAddr)
if err != nil { if err != nil {
return big.Zero(), xerrors.Errorf("failed to load burnt actor: %w", err) return big.Zero(), xerrors.Errorf("failed to load burnt actor: %w", err)
} }
@ -1071,10 +1198,16 @@ func GetFilBurnt(ctx context.Context, st *state.StateTree) (abi.TokenAmount, err
func (sm *StateManager) GetCirculatingSupplyDetailed(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (api.CirculatingSupply, error) { func (sm *StateManager) GetCirculatingSupplyDetailed(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.genInfo == nil { if sm.preIgnitionGenInfos == nil {
err := sm.setupGenesisActorsTestnet(ctx) err := sm.setupPreIgnitionGenesisActorsTestnet(ctx)
if err != nil { if err != nil {
return api.CirculatingSupply{}, xerrors.Errorf("failed to setup genesis information: %w", err) return api.CirculatingSupply{}, xerrors.Errorf("failed to setup pre-ignition genesis information: %w", err)
}
}
if sm.postIgnitionGenInfos == nil {
err := sm.setupPostIgnitionGenesisActors(ctx)
if err != nil {
return api.CirculatingSupply{}, xerrors.Errorf("failed to setup post-ignition genesis information: %w", err)
} }
} }
@ -1125,6 +1258,8 @@ func (sm *StateManager) GetCirculatingSupply(ctx context.Context, height abi.Cha
} }
func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoch) network.Version { func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoch) network.Version {
// TODO: move hard fork epoch checks to a schedule defined in build/
if build.UseNewestNetwork() { if build.UseNewestNetwork() {
return build.NewestNetworkVersion return build.NewestNetworkVersion
} }
@ -1137,5 +1272,45 @@ func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoc
return network.Version1 return network.Version1
} }
if height <= build.UpgradeIgnitionHeight {
return network.Version2
}
return build.NewestNetworkVersion return build.NewestNetworkVersion
} }
func (sm *StateManager) GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error) {
st, err := sm.ParentState(ts)
if err != nil {
return nil, nil, err
}
act, err := st.GetActor(addr)
if err != nil {
return nil, nil, err
}
actState, err := paych.Load(sm.cs.Store(ctx), act)
if err != nil {
return nil, nil, err
}
return act, actState, nil
}
func (sm *StateManager) GetMarketState(ctx context.Context, ts *types.TipSet) (market.State, error) {
st, err := sm.ParentState(ts)
if err != nil {
return nil, err
}
act, err := st.GetActor(market.Address)
if err != nil {
return nil, err
}
actState, err := market.Load(sm.cs.Store(ctx), act)
if err != nil {
return nil, err
}
return actState, nil
}

View File

@ -9,11 +9,7 @@ import (
"runtime" "runtime"
"strings" "strings"
saruntime "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/runtime/proof"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -21,210 +17,177 @@ import (
"github.com/filecoin-project/go-bitfield" "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/crypto"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/account" account0 "github.com/filecoin-project/specs-actors/actors/builtin/account"
"github.com/filecoin-project/specs-actors/actors/builtin/cron" cron0 "github.com/filecoin-project/specs-actors/actors/builtin/cron"
init_ "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/market" market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/multisig" msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/specs-actors/actors/builtin/paych" paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/builtin/power" power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/reward" reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg" verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/util/adt" proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/beacon" "github.com/filecoin-project/lotus/chain/beacon"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/lib/blockstore" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
) )
func GetNetworkName(ctx context.Context, sm *StateManager, st cid.Cid) (dtypes.NetworkName, error) { func GetNetworkName(ctx context.Context, sm *StateManager, st cid.Cid) (dtypes.NetworkName, error) {
var state init_.State act, err := sm.LoadActorRaw(ctx, init_.Address, st)
err := sm.WithStateTree(st, sm.WithActor(builtin.InitActorAddr, sm.WithActorState(ctx, &state))) if err != nil {
return "", err
}
ias, err := init_.Load(sm.cs.Store(ctx), act)
if err != nil { if err != nil {
return "", err return "", err
} }
return dtypes.NetworkName(state.NetworkName), nil return ias.NetworkName()
}
func (sm *StateManager) LoadActorState(ctx context.Context, addr address.Address, out interface{}, ts *types.TipSet) (*types.Actor, error) {
var a *types.Actor
if err := sm.WithParentState(ts, sm.WithActor(addr, func(act *types.Actor) error {
a = act
return sm.WithActorState(ctx, out)(act)
})); err != nil {
return nil, err
}
return a, nil
}
func (sm *StateManager) LoadActorStateRaw(ctx context.Context, addr address.Address, out interface{}, st cid.Cid) (*types.Actor, error) {
var a *types.Actor
if err := sm.WithStateTree(st, sm.WithActor(addr, func(act *types.Actor) error {
a = act
return sm.WithActorState(ctx, out)(act)
})); err != nil {
return nil, err
}
return a, nil
} }
func GetMinerWorkerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) { func GetMinerWorkerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
var mas miner.State state, err := sm.StateTree(st)
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st) if err != nil {
return address.Undef, xerrors.Errorf("(get sset) failed to load state tree: %w", err)
}
act, err := state.GetActor(maddr)
if err != nil {
return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor: %w", err)
}
mas, err := miner.Load(sm.cs.Store(ctx), act)
if err != nil { if err != nil {
return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err) return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
} }
cst := cbor.NewCborStore(sm.cs.Blockstore()) info, err := mas.Info()
state, err := state.LoadStateTree(cst, st)
if err != nil { if err != nil {
return address.Undef, xerrors.Errorf("load state tree: %w", err) return address.Undef, xerrors.Errorf("failed to load actor info: %w", err)
} }
info, err := mas.GetInfo(sm.cs.Store(ctx)) return vm.ResolveToKeyAddr(state, sm.cs.Store(ctx), info.Worker)
if err != nil {
return address.Address{}, err
}
return vm.ResolveToKeyAddr(state, cst, info.Worker)
} }
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (power.Claim, power.Claim, error) { func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (power.Claim, power.Claim, bool, error) {
return GetPowerRaw(ctx, sm, ts.ParentState(), maddr) return GetPowerRaw(ctx, sm, ts.ParentState(), maddr)
} }
func GetPowerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (power.Claim, power.Claim, error) { func GetPowerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (power.Claim, power.Claim, bool, error) {
var ps power.State act, err := sm.LoadActorRaw(ctx, power.Address, st)
_, err := sm.LoadActorStateRaw(ctx, builtin.StoragePowerActorAddr, &ps, st)
if err != nil { if err != nil {
return power.Claim{}, power.Claim{}, xerrors.Errorf("(get sset) failed to load power actor state: %w", err) return power.Claim{}, power.Claim{}, false, xerrors.Errorf("(get sset) failed to load power actor state: %w", err)
}
pas, err := power.Load(sm.cs.Store(ctx), act)
if err != nil {
return power.Claim{}, power.Claim{}, false, err
}
tpow, err := pas.TotalPower()
if err != nil {
return power.Claim{}, power.Claim{}, false, err
} }
var mpow power.Claim var mpow power.Claim
var minpow bool
if maddr != address.Undef { if maddr != address.Undef {
cm, err := adt.AsMap(sm.cs.Store(ctx), ps.Claims) var found bool
mpow, found, err = pas.MinerPower(maddr)
if err != nil || !found {
// TODO: return an error when not found?
return power.Claim{}, power.Claim{}, false, err
}
minpow, err = pas.MinerNominalPowerMeetsConsensusMinimum(maddr)
if err != nil { if err != nil {
return power.Claim{}, power.Claim{}, err return power.Claim{}, power.Claim{}, false, err
} }
var claim power.Claim
if _, err := cm.Get(abi.AddrKey(maddr), &claim); err != nil {
return power.Claim{}, power.Claim{}, err
}
mpow = claim
} }
return mpow, power.Claim{ return mpow, tpow, minpow, nil
RawBytePower: ps.TotalRawBytePower,
QualityAdjPower: ps.TotalQualityAdjPower,
}, nil
} }
func PreCommitInfo(ctx context.Context, sm *StateManager, maddr address.Address, sid abi.SectorNumber, ts *types.TipSet) (miner.SectorPreCommitOnChainInfo, error) { func PreCommitInfo(ctx context.Context, sm *StateManager, maddr address.Address, sid abi.SectorNumber, ts *types.TipSet) (*miner.SectorPreCommitOnChainInfo, error) {
var mas miner.State act, err := sm.LoadActor(ctx, maddr, ts)
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil { if err != nil {
return miner.SectorPreCommitOnChainInfo{}, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err) return nil, xerrors.Errorf("(get sset) failed to load miner actor: %w", err)
} }
i, ok, err := mas.GetPrecommittedSector(sm.cs.Store(ctx), sid) mas, err := miner.Load(sm.cs.Store(ctx), act)
if err != nil { if err != nil {
return miner.SectorPreCommitOnChainInfo{}, err return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
}
if !ok {
return miner.SectorPreCommitOnChainInfo{}, xerrors.New("precommit not found")
} }
return *i, nil return mas.GetPrecommittedSector(sid)
} }
func MinerSectorInfo(ctx context.Context, sm *StateManager, maddr address.Address, sid abi.SectorNumber, ts *types.TipSet) (*miner.SectorOnChainInfo, error) { func MinerSectorInfo(ctx context.Context, sm *StateManager, maddr address.Address, sid abi.SectorNumber, ts *types.TipSet) (*miner.SectorOnChainInfo, error) {
var mas miner.State act, err := sm.LoadActor(ctx, maddr, ts)
_, err := sm.LoadActorState(ctx, maddr, &mas, ts) if err != nil {
return nil, xerrors.Errorf("(get sset) failed to load miner actor: %w", err)
}
mas, err := miner.Load(sm.cs.Store(ctx), act)
if err != nil { if err != nil {
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err) return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
} }
sectorInfo, ok, err := mas.GetSector(sm.cs.Store(ctx), sid) return mas.GetSector(sid)
if err != nil {
return nil, err
}
if !ok {
return nil, nil
}
return sectorInfo, nil
} }
func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address, filter *bitfield.BitField, filterOut bool) ([]*api.ChainSectorInfo, error) { func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address, snos *bitfield.BitField) ([]*miner.SectorOnChainInfo, error) {
var mas miner.State act, err := sm.LoadActor(ctx, maddr, ts)
_, err := sm.LoadActorState(ctx, maddr, &mas, ts) if err != nil {
return nil, xerrors.Errorf("(get sset) failed to load miner actor: %w", err)
}
mas, err := miner.Load(sm.cs.Store(ctx), act)
if err != nil { if err != nil {
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err) return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
} }
return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.Sectors, filter, filterOut) return mas.LoadSectors(snos)
} }
func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *StateManager, st cid.Cid, maddr address.Address, rand abi.PoStRandomness) ([]proof.SectorInfo, error) { func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *StateManager, st cid.Cid, maddr address.Address, rand abi.PoStRandomness) ([]proof0.SectorInfo, error) {
var partsProving []bitfield.BitField act, err := sm.LoadActorRaw(ctx, maddr, st)
var mas *miner.State
var info *miner.MinerInfo
err := sm.WithStateTree(st, sm.WithActor(maddr, sm.WithActorState(ctx, func(store adt.Store, mst *miner.State) error {
var err error
mas = mst
info, err = mas.GetInfo(store)
if err != nil {
return xerrors.Errorf("getting miner info: %w", err)
}
deadlines, err := mas.LoadDeadlines(store)
if err != nil {
return xerrors.Errorf("loading deadlines: %w", err)
}
return deadlines.ForEach(store, func(dlIdx uint64, deadline *miner.Deadline) error {
partitions, err := deadline.PartitionsArray(store)
if err != nil {
return xerrors.Errorf("getting partition array: %w", err)
}
var partition miner.Partition
return partitions.ForEach(&partition, func(partIdx int64) error {
p, err := bitfield.SubtractBitField(partition.Sectors, partition.Faults)
if err != nil {
return xerrors.Errorf("subtract faults from partition sectors: %w", err)
}
partsProving = append(partsProving, p)
return nil
})
})
})))
if err != nil { if err != nil {
return nil, err return nil, xerrors.Errorf("failed to load miner actor: %w", err)
} }
provingSectors, err := bitfield.MultiMerge(partsProving...) mas, err := miner.Load(sm.cs.Store(ctx), act)
if err != nil { if err != nil {
return nil, xerrors.Errorf("merge partition proving sets: %w", err) return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
}
// TODO (!!): Actor Update: Make this active sectors
allSectors, err := miner.AllPartSectors(mas, miner.Partition.AllSectors)
if err != nil {
return nil, xerrors.Errorf("get all sectors: %w", err)
}
faultySectors, err := miner.AllPartSectors(mas, miner.Partition.FaultySectors)
if err != nil {
return nil, xerrors.Errorf("get faulty sectors: %w", err)
}
provingSectors, err := bitfield.SubtractBitField(allSectors, faultySectors) // TODO: This is wrong, as it can contain faaults, change to just ActiveSectors in an upgrade
if err != nil {
return nil, xerrors.Errorf("calc proving sectors: %w", err)
} }
numProvSect, err := provingSectors.Count() numProvSect, err := provingSectors.Count()
@ -237,6 +200,11 @@ func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *S
return nil, nil return nil, nil
} }
info, err := mas.Info()
if err != nil {
return nil, xerrors.Errorf("getting miner info: %w", err)
}
spt, err := ffiwrapper.SealProofTypeFromSectorSize(info.SectorSize) spt, err := ffiwrapper.SealProofTypeFromSectorSize(info.SectorSize)
if err != nil { if err != nil {
return nil, xerrors.Errorf("getting seal proof type: %w", err) return nil, xerrors.Errorf("getting seal proof type: %w", err)
@ -257,28 +225,31 @@ func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *S
return nil, xerrors.Errorf("generating winning post challenges: %w", err) return nil, xerrors.Errorf("generating winning post challenges: %w", err)
} }
sectors, err := provingSectors.All(miner.SectorsMax) iter, err := provingSectors.BitIterator()
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to enumerate all sector IDs: %w", err) return nil, xerrors.Errorf("iterating over proving sectors: %w", err)
} }
sectorAmt, err := adt.AsArray(sm.cs.Store(ctx), mas.Sectors) // Select winning sectors by _index_ in the all-sectors bitfield.
if err != nil { selectedSectors := bitfield.New()
return nil, xerrors.Errorf("failed to load sectors amt: %w", err) prev := uint64(0)
} for _, n := range ids {
sno, err := iter.Nth(n - prev)
out := make([]proof.SectorInfo, len(ids)) if err != nil {
for i, n := range ids { return nil, xerrors.Errorf("iterating over proving sectors: %w", err)
sid := sectors[n]
var sinfo miner.SectorOnChainInfo
if found, err := sectorAmt.Get(sid, &sinfo); err != nil {
return nil, xerrors.Errorf("failed to get sector %d: %w", sid, err)
} else if !found {
return nil, xerrors.Errorf("failed to find sector %d", sid)
} }
selectedSectors.Set(sno)
prev = n
}
out[i] = proof.SectorInfo{ sectors, err := mas.LoadSectors(&selectedSectors)
if err != nil {
return nil, xerrors.Errorf("loading proving sectors: %w", err)
}
out := make([]proof0.SectorInfo, len(sectors))
for i, sinfo := range sectors {
out[i] = proof0.SectorInfo{
SealProof: spt, SealProof: spt,
SectorNumber: sinfo.SectorNumber, SectorNumber: sinfo.SectorNumber,
SealedCID: sinfo.SealedCID, SealedCID: sinfo.SealedCID,
@ -289,33 +260,40 @@ func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *S
} }
func StateMinerInfo(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*miner.MinerInfo, error) { func StateMinerInfo(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*miner.MinerInfo, error) {
var mas miner.State act, err := sm.LoadActor(ctx, maddr, ts)
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, ts.ParentState())
if err != nil { if err != nil {
return nil, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err) return nil, xerrors.Errorf("failed to load miner actor: %w", err)
} }
return mas.GetInfo(sm.cs.Store(ctx)) mas, err := miner.Load(sm.cs.Store(ctx), act)
if err != nil {
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
}
mi, err := mas.Info()
if err != nil {
return nil, err
}
return &mi, err
} }
func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (bool, error) { func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (bool, error) {
var spas power.State act, err := sm.LoadActor(ctx, power.Address, ts)
_, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &spas, ts)
if err != nil { if err != nil {
return false, xerrors.Errorf("(get miner slashed) failed to load power actor state") return false, xerrors.Errorf("failed to load power actor: %w", err)
} }
store := sm.cs.Store(ctx) spas, err := power.Load(sm.cs.Store(ctx), act)
claims, err := adt.AsMap(store, spas.Claims)
if err != nil { if err != nil {
return false, err return false, xerrors.Errorf("failed to load power actor state: %w", err)
} }
ok, err := claims.Get(abi.AddrKey(maddr), nil) _, ok, err := spas.MinerPower(maddr)
if err != nil { if err != nil {
return false, err return false, xerrors.Errorf("getting miner power: %w", err)
} }
if !ok { if !ok {
return true, nil return true, nil
} }
@ -324,108 +302,61 @@ func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, ma
} }
func GetStorageDeal(ctx context.Context, sm *StateManager, dealID abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) { func GetStorageDeal(ctx context.Context, sm *StateManager, dealID abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) {
var state market.State act, err := sm.LoadActor(ctx, market.Address, ts)
if _, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts); err != nil { if err != nil {
return nil, err return nil, xerrors.Errorf("failed to load market actor: %w", err)
} }
store := sm.ChainStore().Store(ctx)
da, err := adt.AsArray(store, state.Proposals) state, err := market.Load(sm.cs.Store(ctx), act)
if err != nil {
return nil, xerrors.Errorf("failed to load market actor state: %w", err)
}
proposals, err := state.Proposals()
if err != nil { if err != nil {
return nil, err return nil, err
} }
var dp market.DealProposal proposal, found, err := proposals.Get(dealID)
if found, err := da.Get(uint64(dealID), &dp); err != nil {
if err != nil {
return nil, err return nil, err
} else if !found { } else if !found {
return nil, xerrors.Errorf("deal %d not found", dealID) return nil, xerrors.Errorf("deal %d not found", dealID)
} }
sa, err := market.AsDealStateArray(store, state.States) states, err := state.States()
if err != nil { if err != nil {
return nil, err return nil, err
} }
st, found, err := sa.Get(dealID) st, found, err := states.Get(dealID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if !found { if !found {
st = &market.DealState{ st = market.EmptyDealState()
SectorStartEpoch: -1,
LastUpdatedEpoch: -1,
SlashEpoch: -1,
}
} }
return &api.MarketDeal{ return &api.MarketDeal{
Proposal: dp, Proposal: *proposal,
State: *st, State: *st,
}, nil }, nil
} }
func ListMinerActors(ctx context.Context, sm *StateManager, ts *types.TipSet) ([]address.Address, error) { func ListMinerActors(ctx context.Context, sm *StateManager, ts *types.TipSet) ([]address.Address, error) {
var state power.State act, err := sm.LoadActor(ctx, power.Address, ts)
if _, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &state, ts); err != nil {
return nil, err
}
m, err := adt.AsMap(sm.cs.Store(ctx), state.Claims)
if err != nil { if err != nil {
return nil, err return nil, xerrors.Errorf("failed to load power actor: %w", err)
} }
var miners []address.Address powState, err := power.Load(sm.cs.Store(ctx), act)
err = m.ForEach(nil, func(k string) error {
a, err := address.NewFromBytes([]byte(k))
if err != nil {
return err
}
miners = append(miners, a)
return nil
})
if err != nil { if err != nil {
return nil, err return nil, xerrors.Errorf("failed to load power actor state: %w", err)
} }
return miners, nil return powState.ListAllMiners()
}
func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.Cid, filter *bitfield.BitField, filterOut bool) ([]*api.ChainSectorInfo, error) {
a, err := adt.AsArray(store.ActorStore(ctx, bs), ssc)
if err != nil {
return nil, err
}
var sset []*api.ChainSectorInfo
var v cbg.Deferred
if err := a.ForEach(&v, func(i int64) error {
if filter != nil {
set, err := filter.IsSet(uint64(i))
if err != nil {
return xerrors.Errorf("filter check error: %w", err)
}
if set == filterOut {
return nil
}
}
var oci miner.SectorOnChainInfo
if err := cbor.DecodeInto(v.Raw, &oci); err != nil {
return err
}
sset = append(sset, &api.ChainSectorInfo{
Info: oci,
ID: abi.SectorNumber(i),
})
return nil
}); err != nil {
return nil, err
}
return sset, nil
} }
func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, msgs []*types.Message, ts *types.TipSet) (cid.Cid, []*api.InvocResult, error) { func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, msgs []*types.Message, ts *types.TipSet) (cid.Cid, []*api.InvocResult, error) {
@ -438,6 +369,16 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
return cid.Undef, nil, err return cid.Undef, nil, err
} }
for i := ts.Height(); i < height; i++ {
// handle state forks
base, err = sm.handleStateForks(ctx, base, i, traceFunc(&trace), ts)
if err != nil {
return cid.Undef, nil, xerrors.Errorf("error handling state forks: %w", err)
}
// TODO: should we also run cron here?
}
r := store.NewChainRand(sm.cs, ts.Cids()) r := store.NewChainRand(sm.cs, ts.Cids())
vmopt := &vm.VMOpts{ vmopt := &vm.VMOpts{
StateBase: base, StateBase: base,
@ -449,21 +390,11 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
NtwkVersion: sm.GetNtwkVersion, NtwkVersion: sm.GetNtwkVersion,
BaseFee: ts.Blocks()[0].ParentBaseFee, BaseFee: ts.Blocks()[0].ParentBaseFee,
} }
vmi, err := vm.NewVM(vmopt) vmi, err := vm.NewVM(ctx, vmopt)
if err != nil { if err != nil {
return cid.Undef, nil, err return cid.Undef, nil, err
} }
for i := ts.Height(); i < height; i++ {
// handle state forks
err = sm.handleStateForks(ctx, vmi.StateTree(), i, ts)
if err != nil {
return cid.Undef, nil, xerrors.Errorf("error handling state forks: %w", err)
}
// TODO: should we also run cron here?
}
for i, msg := range msgs { for i, msg := range msgs {
// TODO: Use the signed message length for secp messages // TODO: Use the signed message length for secp messages
ret, err := vmi.ApplyMessage(ctx, msg) ret, err := vmi.ApplyMessage(ctx, msg)
@ -537,9 +468,14 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule
return nil, err return nil, err
} }
var mas miner.State act, err := sm.LoadActorRaw(ctx, maddr, lbst)
if _, err := sm.LoadActorStateRaw(ctx, maddr, &mas, lbst); err != nil { if err != nil {
return nil, err return nil, xerrors.Errorf("failed to load miner actor: %w", err)
}
mas, err := miner.Load(sm.cs.Store(ctx), act)
if err != nil {
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
} }
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
@ -561,12 +497,12 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule
return nil, nil return nil, nil
} }
mpow, tpow, err := GetPowerRaw(ctx, sm, lbst, maddr) mpow, tpow, hmp, err := GetPowerRaw(ctx, sm, lbst, maddr)
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to get power: %w", err) return nil, xerrors.Errorf("failed to get power: %w", err)
} }
info, err := mas.GetInfo(sm.cs.Store(ctx)) info, err := mas.Info()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -576,11 +512,6 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule
return nil, xerrors.Errorf("resolving worker address: %w", err) return nil, xerrors.Errorf("resolving worker address: %w", err)
} }
hmp, err := MinerHasMinPower(ctx, sm, maddr, lbts)
if err != nil {
return nil, xerrors.Errorf("determining if miner has min power failed: %w", err)
}
return &api.MiningBaseInfo{ return &api.MiningBaseInfo{
MinerPower: mpow.QualityAdjPower, MinerPower: mpow.QualityAdjPower,
NetworkPower: tpow.QualityAdjPower, NetworkPower: tpow.QualityAdjPower,
@ -605,24 +536,24 @@ var MethodsMap = map[cid.Cid]map[abi.MethodNum]MethodMeta{}
func init() { func init() {
cidToMethods := map[cid.Cid][2]interface{}{ cidToMethods := map[cid.Cid][2]interface{}{
// builtin.SystemActorCodeID: {builtin.MethodsSystem, system.Actor{} }- apparently it doesn't have methods // builtin.SystemActorCodeID: {builtin.MethodsSystem, system.Actor{} }- apparently it doesn't have methods
builtin.InitActorCodeID: {builtin.MethodsInit, init_.Actor{}}, builtin0.InitActorCodeID: {builtin0.MethodsInit, init0.Actor{}},
builtin.CronActorCodeID: {builtin.MethodsCron, cron.Actor{}}, builtin0.CronActorCodeID: {builtin0.MethodsCron, cron0.Actor{}},
builtin.AccountActorCodeID: {builtin.MethodsAccount, account.Actor{}}, builtin0.AccountActorCodeID: {builtin0.MethodsAccount, account0.Actor{}},
builtin.StoragePowerActorCodeID: {builtin.MethodsPower, power.Actor{}}, builtin0.StoragePowerActorCodeID: {builtin0.MethodsPower, power0.Actor{}},
builtin.StorageMinerActorCodeID: {builtin.MethodsMiner, miner.Actor{}}, builtin0.StorageMinerActorCodeID: {builtin0.MethodsMiner, miner0.Actor{}},
builtin.StorageMarketActorCodeID: {builtin.MethodsMarket, market.Actor{}}, builtin0.StorageMarketActorCodeID: {builtin0.MethodsMarket, market0.Actor{}},
builtin.PaymentChannelActorCodeID: {builtin.MethodsPaych, paych.Actor{}}, builtin0.PaymentChannelActorCodeID: {builtin0.MethodsPaych, paych0.Actor{}},
builtin.MultisigActorCodeID: {builtin.MethodsMultisig, multisig.Actor{}}, builtin0.MultisigActorCodeID: {builtin0.MethodsMultisig, msig0.Actor{}},
builtin.RewardActorCodeID: {builtin.MethodsReward, reward.Actor{}}, builtin0.RewardActorCodeID: {builtin0.MethodsReward, reward0.Actor{}},
builtin.VerifiedRegistryActorCodeID: {builtin.MethodsVerifiedRegistry, verifreg.Actor{}}, builtin0.VerifiedRegistryActorCodeID: {builtin0.MethodsVerifiedRegistry, verifreg0.Actor{}},
} }
for c, m := range cidToMethods { for c, m := range cidToMethods {
exports := m[1].(saruntime.Invokee).Exports() exports := m[1].(vm.Invokee).Exports()
methods := make(map[abi.MethodNum]MethodMeta, len(exports)) methods := make(map[abi.MethodNum]MethodMeta, len(exports))
// Explicitly add send, it's special. // Explicitly add send, it's special.
methods[builtin.MethodSend] = MethodMeta{ methods[builtin0.MethodSend] = MethodMeta{
Name: "Send", Name: "Send",
Params: reflect.TypeOf(new(abi.EmptyValue)), Params: reflect.TypeOf(new(abi.EmptyValue)),
Ret: reflect.TypeOf(new(abi.EmptyValue)), Ret: reflect.TypeOf(new(abi.EmptyValue)),
@ -662,9 +593,9 @@ func init() {
} }
switch abi.MethodNum(number) { switch abi.MethodNum(number) {
case builtin.MethodSend: case builtin0.MethodSend:
panic("method 0 is reserved for Send") panic("method 0 is reserved for Send")
case builtin.MethodConstructor: case builtin0.MethodConstructor:
if fnName != "Constructor" { if fnName != "Constructor" {
panic("method 1 is reserved for Constructor") panic("method 1 is reserved for Constructor")
} }
@ -681,9 +612,9 @@ func init() {
} }
func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, method abi.MethodNum, ts *types.TipSet) (cbg.CBORUnmarshaler, error) { func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, method abi.MethodNum, ts *types.TipSet) (cbg.CBORUnmarshaler, error) {
var act types.Actor act, err := sm.LoadActor(ctx, to, ts)
if err := sm.WithParentState(ts, sm.WithActor(to, GetActor(&act))); err != nil { if err != nil {
return nil, xerrors.Errorf("getting actor: %w", err) return nil, xerrors.Errorf("(get sset) failed to load miner actor: %w", err)
} }
m, found := MethodsMap[act.Code][method] m, found := MethodsMap[act.Code][method]
@ -694,13 +625,17 @@ func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, me
} }
func MinerHasMinPower(ctx context.Context, sm *StateManager, addr address.Address, ts *types.TipSet) (bool, error) { func MinerHasMinPower(ctx context.Context, sm *StateManager, addr address.Address, ts *types.TipSet) (bool, error) {
var ps power.State pact, err := sm.LoadActor(ctx, power.Address, ts)
_, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &ps, ts)
if err != nil { if err != nil {
return false, xerrors.Errorf("loading power actor state: %w", err) return false, xerrors.Errorf("loading power actor state: %w", err)
} }
return ps.MinerNominalPowerMeetsConsensusMinimum(sm.ChainStore().Store(ctx), addr) ps, err := power.Load(sm.cs.Store(ctx), pact)
if err != nil {
return false, err
}
return ps.MinerNominalPowerMeetsConsensusMinimum(addr)
} }
func CheckTotalFIL(ctx context.Context, sm *StateManager, ts *types.TipSet) (abi.TokenAmount, error) { func CheckTotalFIL(ctx context.Context, sm *StateManager, ts *types.TipSet) (abi.TokenAmount, error) {

View File

@ -10,14 +10,18 @@ import (
"strconv" "strconv"
"sync" "sync"
"golang.org/x/sync/errgroup"
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
"github.com/minio/blake2b-simd" "github.com/minio/blake2b-simd"
"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/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/journal"
bstore "github.com/filecoin-project/lotus/lib/blockstore" bstore "github.com/filecoin-project/lotus/lib/blockstore"
@ -282,6 +286,16 @@ func (cs *ChainStore) MarkBlockAsValidated(ctx context.Context, blkid cid.Cid) e
return nil return nil
} }
func (cs *ChainStore) UnmarkBlockAsValidated(ctx context.Context, blkid cid.Cid) error {
key := blockValidationCacheKeyPrefix.Instance(blkid.String())
if err := cs.ds.Delete(key); err != nil {
return xerrors.Errorf("removing from valid block cache: %w", err)
}
return nil
}
func (cs *ChainStore) SetGenesis(b *types.BlockHeader) error { func (cs *ChainStore) SetGenesis(b *types.BlockHeader) error {
ts, err := types.NewTipSet([]*types.BlockHeader{b}) ts, err := types.NewTipSet([]*types.BlockHeader{b})
if err != nil { if err != nil {
@ -465,14 +479,25 @@ func (cs *ChainStore) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error) {
return v.(*types.TipSet), nil return v.(*types.TipSet), nil
} }
var blks []*types.BlockHeader // Fetch tipset block headers from blockstore in parallel
for _, c := range tsk.Cids() { var eg errgroup.Group
b, err := cs.GetBlock(c) cids := tsk.Cids()
if err != nil { blks := make([]*types.BlockHeader, len(cids))
return nil, xerrors.Errorf("get block %s: %w", c, err) for i, c := range cids {
} i, c := i, c
eg.Go(func() error {
b, err := cs.GetBlock(c)
if err != nil {
return xerrors.Errorf("get block %s: %w", c, err)
}
blks = append(blks, b) blks[i] = b
return nil
})
}
err := eg.Wait()
if err != nil {
return nil, err
} }
ts, err := types.NewTipSet(blks) ts, err := types.NewTipSet(blks)
@ -1183,6 +1208,7 @@ func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRo
} }
blocksToWalk := ts.Cids() blocksToWalk := ts.Cids()
currentMinHeight := ts.Height()
walkChain := func(blk cid.Cid) error { walkChain := func(blk cid.Cid) error {
if !seen.Visit(blk) { if !seen.Visit(blk) {
@ -1203,6 +1229,13 @@ func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRo
return xerrors.Errorf("unmarshaling block header (cid=%s): %w", blk, err) return xerrors.Errorf("unmarshaling block header (cid=%s): %w", blk, err)
} }
if currentMinHeight > b.Height {
currentMinHeight = b.Height
if currentMinHeight%builtin.EpochsInDay == 0 {
log.Infow("export", "height", currentMinHeight)
}
}
var cids []cid.Cid var cids []cid.Cid
if !skipOldMsgs || b.Height > ts.Height()-inclRecentRoots { if !skipOldMsgs || b.Height > ts.Height()-inclRecentRoots {
mcids, err := recurseLinks(cs.bs, walked, b.Messages, []cid.Cid{b.Messages}) mcids, err := recurseLinks(cs.bs, walked, b.Messages, []cid.Cid{b.Messages})
@ -1251,6 +1284,9 @@ func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRo
return nil return nil
} }
log.Infow("export started")
exportStart := build.Clock.Now()
for len(blocksToWalk) > 0 { for len(blocksToWalk) > 0 {
next := blocksToWalk[0] next := blocksToWalk[0]
blocksToWalk = blocksToWalk[1:] blocksToWalk = blocksToWalk[1:]
@ -1259,6 +1295,8 @@ func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRo
} }
} }
log.Infow("export finished", "duration", build.Clock.Now().Sub(exportStart).Seconds())
return nil return nil
} }
@ -1301,7 +1339,7 @@ func (cs *ChainStore) GetLatestBeaconEntry(ts *types.TipSet) (*types.BeaconEntry
}, nil }, nil
} }
return nil, xerrors.Errorf("found NO beacon entries in the 20 blocks prior to given tipset") return nil, xerrors.Errorf("found NO beacon entries in the 20 latest tipsets")
} }
type chainRand struct { type chainRand struct {

View File

@ -8,12 +8,9 @@ import (
datastore "github.com/ipfs/go-datastore" datastore "github.com/ipfs/go-datastore"
"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/crypto" "github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"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/store" "github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -22,11 +19,9 @@ import (
) )
func init() { func init() {
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{ policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
abi.RegisteredSealProof_StackedDrg2KiBV1: {}, policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
} policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
power.ConsensusMinerMinPower = big.NewInt(2048)
verifreg.MinVerifiedDealSize = big.NewInt(256)
} }
func BenchmarkGetRandomness(b *testing.B) { func BenchmarkGetRandomness(b *testing.B) {

View File

@ -4,12 +4,12 @@ import (
"context" "context"
"math/big" "math/big"
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
big2 "github.com/filecoin-project/go-state-types/big" big2 "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"golang.org/x/xerrors" "golang.org/x/xerrors"
) )
@ -34,16 +34,22 @@ func (cs *ChainStore) Weight(ctx context.Context, ts *types.TipSet) (types.BigIn
return types.NewInt(0), xerrors.Errorf("load state tree: %w", err) return types.NewInt(0), xerrors.Errorf("load state tree: %w", err)
} }
act, err := state.GetActor(builtin.StoragePowerActorAddr) act, err := state.GetActor(power.Address)
if err != nil { if err != nil {
return types.NewInt(0), xerrors.Errorf("get power actor: %w", err) return types.NewInt(0), xerrors.Errorf("get power actor: %w", err)
} }
var st power.State powState, err := power.Load(cs.Store(ctx), act)
if err := cst.Get(ctx, act.Head, &st); err != nil { if err != nil {
return types.NewInt(0), xerrors.Errorf("get power actor head (%s, height=%d): %w", act.Head, ts.Height(), err) return types.NewInt(0), xerrors.Errorf("failed to load power actor state: %w", err)
} }
tpow = st.TotalQualityAdjPower // TODO: REVIEW: Is this correct?
claim, err := powState.TotalPower()
if err != nil {
return types.NewInt(0), xerrors.Errorf("failed to get total power: %w", err)
}
tpow = claim.QualityAdjPower // TODO: REVIEW: Is this correct?
} }
log2P := int64(0) log2P := int64(0)

View File

@ -1,7 +1,6 @@
package sub package sub
import ( import (
"bytes"
"context" "context"
"errors" "errors"
"fmt" "fmt"
@ -11,7 +10,6 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
address "github.com/filecoin-project/go-address" address "github.com/filecoin-project/go-address"
miner "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
blocks "github.com/ipfs/go-block-format" blocks "github.com/ipfs/go-block-format"
@ -28,6 +26,7 @@ import (
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/stmgr"
@ -432,6 +431,7 @@ func (bv *BlockValidator) checkPowerAndGetWorkerKey(ctx context.Context, bh *typ
if err != nil { if err != nil {
return address.Undef, err return address.Undef, err
} }
buf := bufbstore.NewBufferedBstore(bv.chain.Blockstore()) buf := bufbstore.NewBufferedBstore(bv.chain.Blockstore())
cst := cbor.NewCborStore(buf) cst := cbor.NewCborStore(buf)
state, err := state.LoadStateTree(cst, st) state, err := state.LoadStateTree(cst, st)
@ -443,19 +443,12 @@ func (bv *BlockValidator) checkPowerAndGetWorkerKey(ctx context.Context, bh *typ
return address.Undef, err return address.Undef, err
} }
blk, err := bv.chain.Blockstore().Get(act.Head) mst, err := miner.Load(bv.chain.Store(ctx), act)
if err != nil {
return address.Undef, err
}
aso := blk.RawData()
var mst miner.State
err = mst.UnmarshalCBOR(bytes.NewReader(aso))
if err != nil { if err != nil {
return address.Undef, err return address.Undef, err
} }
info, err := mst.GetInfo(adt.WrapStore(ctx, cst)) info, err := mst.Info()
if err != nil { if err != nil {
return address.Undef, err return address.Undef, err
} }

View File

@ -7,7 +7,6 @@ import (
"fmt" "fmt"
"os" "os"
"sort" "sort"
"strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -18,6 +17,7 @@ import (
"github.com/Gurpartap/async" "github.com/Gurpartap/async"
"github.com/hashicorp/go-multierror" "github.com/hashicorp/go-multierror"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"
@ -33,13 +33,12 @@ import (
"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"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
blst "github.com/supranational/blst/bindings/go" blst "github.com/supranational/blst/bindings/go"
"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/power"
"github.com/filecoin-project/lotus/chain/beacon" "github.com/filecoin-project/lotus/chain/beacon"
"github.com/filecoin-project/lotus/chain/exchange" "github.com/filecoin-project/lotus/chain/exchange"
"github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/gen"
@ -63,20 +62,12 @@ var (
// where the Syncer publishes candidate chain heads to be synced. // where the Syncer publishes candidate chain heads to be synced.
LocalIncoming = "incoming" LocalIncoming = "incoming"
log = logging.Logger("chain") log = logging.Logger("chain")
defaultMessageFetchWindowSize = 200
)
func init() { concurrentSyncRequests = exchange.ShufflePeersPrefix
if s := os.Getenv("LOTUS_BSYNC_MSG_WINDOW"); s != "" { syncRequestBatchSize = 8
val, err := strconv.Atoi(s) syncRequestRetries = 5
if err != nil { )
log.Errorf("failed to parse LOTUS_BSYNC_MSG_WINDOW: %s", err)
return
}
defaultMessageFetchWindowSize = val
}
}
// Syncer is in charge of running the chain synchronization logic. As such, it // Syncer is in charge of running the chain synchronization logic. As such, it
// is tasked with these functions, amongst others: // is tasked with these functions, amongst others:
@ -132,8 +123,6 @@ type Syncer struct {
verifier ffiwrapper.Verifier verifier ffiwrapper.Verifier
windowSize int
tickerCtxCancel context.CancelFunc tickerCtxCancel context.CancelFunc
checkptLk sync.Mutex checkptLk sync.Mutex
@ -175,7 +164,6 @@ func NewSyncer(ds dtypes.MetadataDS, sm *stmgr.StateManager, exchange exchange.C
receiptTracker: newBlockReceiptTracker(), receiptTracker: newBlockReceiptTracker(),
connmgr: connmgr, connmgr: connmgr,
verifier: verifier, verifier: verifier,
windowSize: defaultMessageFetchWindowSize,
incoming: pubsub.New(50), incoming: pubsub.New(50),
} }
@ -387,21 +375,28 @@ func (syncer *Syncer) InformNewBlock(from peer.ID, blk *types.FullBlock) bool {
return syncer.InformNewHead(from, fts) return syncer.InformNewHead(from, fts)
} }
func copyBlockstore(from, to bstore.Blockstore) error { func copyBlockstore(ctx context.Context, from, to bstore.Blockstore) error {
cids, err := from.AllKeysChan(context.TODO()) ctx, span := trace.StartSpan(ctx, "copyBlockstore")
defer span.End()
cids, err := from.AllKeysChan(ctx)
if err != nil { if err != nil {
return err return err
} }
// TODO: should probably expose better methods on the blockstore for this operation
var blks []blocks.Block
for c := range cids { for c := range cids {
b, err := from.Get(c) b, err := from.Get(c)
if err != nil { if err != nil {
return err return err
} }
if err := to.Put(b); err != nil { blks = append(blks, b)
return err }
}
if err := to.PutMany(blks); err != nil {
return err
} }
return nil return nil
@ -602,7 +597,7 @@ func isPermanent(err error) bool {
return !errors.Is(err, ErrTemporal) return !errors.Is(err, ErrTemporal)
} }
func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet) error { func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet, useCache bool) error {
ctx, span := trace.StartSpan(ctx, "validateTipSet") ctx, span := trace.StartSpan(ctx, "validateTipSet")
defer span.End() defer span.End()
@ -618,7 +613,7 @@ func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet)
b := b // rebind to a scoped variable b := b // rebind to a scoped variable
futures = append(futures, async.Err(func() error { futures = append(futures, async.Err(func() error {
if err := syncer.ValidateBlock(ctx, b); err != nil { if err := syncer.ValidateBlock(ctx, b, useCache); err != nil {
if isPermanent(err) { if isPermanent(err) {
syncer.bad.Add(b.Cid(), NewBadBlockReason([]cid.Cid{b.Cid()}, err.Error())) syncer.bad.Add(b.Cid(), NewBadBlockReason([]cid.Cid{b.Cid()}, err.Error()))
} }
@ -640,26 +635,25 @@ func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet)
} }
func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, baseTs *types.TipSet) error { func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, baseTs *types.TipSet) error {
var spast power.State act, err := syncer.sm.LoadActor(ctx, power.Address, baseTs)
_, err := syncer.sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &spast, baseTs)
if err != nil { if err != nil {
return err return xerrors.Errorf("failed to load power actor: %w", err)
} }
cm, err := adt.AsMap(syncer.store.Store(ctx), spast.Claims) powState, err := power.Load(syncer.store.Store(ctx), act)
if err != nil { if err != nil {
return err return xerrors.Errorf("failed to load power actor state: %w", err)
} }
var claim power.Claim _, exist, err := powState.MinerPower(maddr)
exist, err := cm.Get(abi.AddrKey(maddr), &claim)
if err != nil { if err != nil {
return err return xerrors.Errorf("failed to look up miner's claim: %w", err)
} }
if !exist { if !exist {
return xerrors.New("miner isn't valid") return xerrors.New("miner isn't valid")
} }
return nil return nil
} }
@ -686,7 +680,7 @@ func blockSanityChecks(h *types.BlockHeader) error {
} }
// ValidateBlock should match up with 'Semantical Validation' in validation.md in the spec // ValidateBlock should match up with 'Semantical Validation' in validation.md in the spec
func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (err error) { func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock, useCache bool) (err error) {
defer func() { defer func() {
// b.Cid() could panic for empty blocks that are used in tests. // b.Cid() could panic for empty blocks that are used in tests.
if rerr := recover(); rerr != nil { if rerr := recover(); rerr != nil {
@ -695,13 +689,15 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
} }
}() }()
isValidated, err := syncer.store.IsBlockValidated(ctx, b.Cid()) if useCache {
if err != nil { isValidated, err := syncer.store.IsBlockValidated(ctx, b.Cid())
return xerrors.Errorf("check block validation cache %s: %w", b.Cid(), err) if err != nil {
} return xerrors.Errorf("check block validation cache %s: %w", b.Cid(), err)
}
if isValidated { if isValidated {
return nil return nil
}
} }
validationStart := build.Clock.Now() validationStart := build.Clock.Now()
@ -788,31 +784,35 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
b.Header.ParentWeight, pweight) b.Header.ParentWeight, pweight)
} }
// Stuff that needs stateroot / worker address stateRootCheck := async.Err(func() error {
stateroot, precp, err := syncer.sm.TipSetState(ctx, baseTs) stateroot, precp, err := syncer.sm.TipSetState(ctx, baseTs)
if err != nil {
return xerrors.Errorf("get tipsetstate(%d, %s) failed: %w", h.Height, h.Parents, err)
}
if stateroot != h.ParentStateRoot {
msgs, err := syncer.store.MessagesForTipset(baseTs)
if err != nil { if err != nil {
log.Error("failed to load messages for tipset during tipset state mismatch error: ", err) return xerrors.Errorf("get tipsetstate(%d, %s) failed: %w", h.Height, h.Parents, err)
} else {
log.Warn("Messages for tipset with mismatching state:")
for i, m := range msgs {
mm := m.VMMessage()
log.Warnf("Message[%d]: from=%s to=%s method=%d params=%x", i, mm.From, mm.To, mm.Method, mm.Params)
}
} }
return xerrors.Errorf("parent state root did not match computed state (%s != %s)", stateroot, h.ParentStateRoot) if stateroot != h.ParentStateRoot {
} msgs, err := syncer.store.MessagesForTipset(baseTs)
if err != nil {
log.Error("failed to load messages for tipset during tipset state mismatch error: ", err)
} else {
log.Warn("Messages for tipset with mismatching state:")
for i, m := range msgs {
mm := m.VMMessage()
log.Warnf("Message[%d]: from=%s to=%s method=%d params=%x", i, mm.From, mm.To, mm.Method, mm.Params)
}
}
if precp != h.ParentMessageReceipts { return xerrors.Errorf("parent state root did not match computed state (%s != %s)", stateroot, h.ParentStateRoot)
return xerrors.Errorf("parent receipts root did not match computed value (%s != %s)", precp, h.ParentMessageReceipts) }
}
if precp != h.ParentMessageReceipts {
return xerrors.Errorf("parent receipts root did not match computed value (%s != %s)", precp, h.ParentMessageReceipts)
}
return nil
})
// Stuff that needs worker address
waddr, err := stmgr.GetMinerWorkerRaw(ctx, syncer.sm, lbst, h.Miner) waddr, err := stmgr.GetMinerWorkerRaw(ctx, syncer.sm, lbst, h.Miner)
if err != nil { if err != nil {
return xerrors.Errorf("GetMinerWorkerRaw failed: %w", err) return xerrors.Errorf("GetMinerWorkerRaw failed: %w", err)
@ -859,7 +859,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
return xerrors.Errorf("received block was from slashed or invalid miner") return xerrors.Errorf("received block was from slashed or invalid miner")
} }
mpow, tpow, err := stmgr.GetPowerRaw(ctx, syncer.sm, lbst, h.Miner) mpow, tpow, _, err := stmgr.GetPowerRaw(ctx, syncer.sm, lbst, h.Miner)
if err != nil { if err != nil {
return xerrors.Errorf("failed getting power: %w", err) return xerrors.Errorf("failed getting power: %w", err)
} }
@ -933,6 +933,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
winnerCheck, winnerCheck,
msgsCheck, msgsCheck,
baseFeeCheck, baseFeeCheck,
stateRootCheck,
} }
var merr error var merr error
@ -960,8 +961,10 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
return mulErr return mulErr
} }
if err := syncer.store.MarkBlockAsValidated(ctx, b.Cid()); err != nil { if useCache {
return xerrors.Errorf("caching block validation %s: %w", b.Cid(), err) if err := syncer.store.MarkBlockAsValidated(ctx, b.Cid()); err != nil {
return xerrors.Errorf("caching block validation %s: %w", b.Cid(), err)
}
} }
return nil return nil
@ -1463,7 +1466,7 @@ func (syncer *Syncer) syncMessagesAndCheckState(ctx context.Context, headers []*
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()))
if err := syncer.ValidateTipSet(ctx, fts); err != nil { if err := syncer.ValidateTipSet(ctx, fts, true); err != nil {
log.Errorf("failed to validate tipset: %+v", err) log.Errorf("failed to validate tipset: %+v", err)
return xerrors.Errorf("message processing failed: %w", err) return xerrors.Errorf("message processing failed: %w", err)
} }
@ -1483,8 +1486,6 @@ func (syncer *Syncer) iterFullTipsets(ctx context.Context, headers []*types.TipS
span.AddAttributes(trace.Int64Attribute("num_headers", int64(len(headers)))) span.AddAttributes(trace.Int64Attribute("num_headers", int64(len(headers))))
windowSize := syncer.windowSize
mainLoop:
for i := len(headers) - 1; i >= 0; { for i := len(headers) - 1; i >= 0; {
fts, err := syncer.store.TryFillTipSet(headers[i]) fts, err := syncer.store.TryFillTipSet(headers[i])
if err != nil { if err != nil {
@ -1498,35 +1499,20 @@ mainLoop:
continue continue
} }
batchSize := windowSize batchSize := concurrentSyncRequests * syncRequestBatchSize
if i < batchSize { if i < batchSize {
batchSize = i batchSize = i + 1
} }
nextI := (i + 1) - batchSize // want to fetch batchSize values, 'i' points to last one we want to fetch, so its 'inclusive' of our request, thus we need to add one to our request start index
ss.SetStage(api.StageFetchingMessages) ss.SetStage(api.StageFetchingMessages)
var bstout []*exchange.CompactedMessages startOffset := i + 1 - batchSize
for len(bstout) < batchSize { bstout, batchErr := syncer.fetchMessages(ctx, headers[startOffset:startOffset+batchSize], startOffset)
next := headers[nextI]
nreq := batchSize - len(bstout)
bstips, err := syncer.Exchange.GetChainMessages(ctx, next, uint64(nreq))
if err != nil {
// TODO check errors for temporary nature
if windowSize > 1 {
windowSize /= 2
log.Infof("error fetching messages: %s; reducing window size to %d and trying again", err, windowSize)
continue mainLoop
}
return xerrors.Errorf("message processing failed: %w", err)
}
bstout = append(bstout, bstips...)
nextI += len(bstips)
}
ss.SetStage(api.StageMessages) ss.SetStage(api.StageMessages)
if batchErr != nil {
return xerrors.Errorf("failed to fetch messages: %w", err)
}
for bsi := 0; bsi < len(bstout); bsi++ { for bsi := 0; bsi < len(bstout); bsi++ {
// temp storage so we don't persist data we dont want to // temp storage so we don't persist data we dont want to
bs := bstore.NewTemporary() bs := bstore.NewTemporary()
@ -1546,36 +1532,91 @@ mainLoop:
return err return err
} }
if err := persistMessages(bs, bstip); err != nil { if err := persistMessages(ctx, bs, bstip); err != nil {
return err return err
} }
if err := copyBlockstore(bs, syncer.store.Blockstore()); err != nil { if err := copyBlockstore(ctx, bs, syncer.store.Blockstore()); err != nil {
return xerrors.Errorf("message processing failed: %w", err) return xerrors.Errorf("message processing failed: %w", err)
} }
} }
if i >= windowSize {
newWindowSize := windowSize + 10
if newWindowSize > int(exchange.MaxRequestLength) {
newWindowSize = int(exchange.MaxRequestLength)
}
if newWindowSize > windowSize {
windowSize = newWindowSize
log.Infof("successfully fetched %d messages; increasing window size to %d", len(bstout), windowSize)
}
}
i -= batchSize i -= batchSize
} }
// remember our window size
syncer.windowSize = windowSize
return nil return nil
} }
func persistMessages(bs bstore.Blockstore, bst *exchange.CompactedMessages) error { func (syncer *Syncer) fetchMessages(ctx context.Context, headers []*types.TipSet, startOffset int) ([]*exchange.CompactedMessages, error) {
batchSize := len(headers)
batch := make([]*exchange.CompactedMessages, batchSize)
var wg sync.WaitGroup
var mx sync.Mutex
var batchErr error
start := build.Clock.Now()
for j := 0; j < batchSize; j += syncRequestBatchSize {
wg.Add(1)
go func(j int) {
defer wg.Done()
nreq := syncRequestBatchSize
if j+nreq > batchSize {
nreq = batchSize - j
}
failed := false
for offset := 0; !failed && offset < nreq; {
nextI := j + offset
lastI := j + nreq
var requestErr error
var requestResult []*exchange.CompactedMessages
for retry := 0; requestResult == nil && retry < syncRequestRetries; retry++ {
if retry > 0 {
log.Infof("fetching messages at %d (retry %d)", startOffset+nextI, retry)
} else {
log.Infof("fetching messages at %d", startOffset+nextI)
}
result, err := syncer.Exchange.GetChainMessages(ctx, headers[nextI:lastI])
if err != nil {
requestErr = multierror.Append(requestErr, err)
} else {
requestResult = result
}
}
mx.Lock()
if requestResult != nil {
copy(batch[j+offset:], requestResult)
offset += len(requestResult)
} else {
log.Errorf("error fetching messages at %d: %s", nextI, requestErr)
batchErr = multierror.Append(batchErr, requestErr)
failed = true
}
mx.Unlock()
}
}(j)
}
wg.Wait()
if batchErr != nil {
return nil, batchErr
}
log.Infof("fetching messages for %d tipsets at %d done; took %s", batchSize, startOffset, build.Clock.Since(start))
return batch, nil
}
func persistMessages(ctx context.Context, bs bstore.Blockstore, bst *exchange.CompactedMessages) error {
_, span := trace.StartSpan(ctx, "persistMessages")
defer span.End()
for _, m := range bst.Bls { for _, m := range bst.Bls {
//log.Infof("putting BLS message: %s", m.Cid()) //log.Infof("putting BLS message: %s", m.Cid())
if _, err := store.PutMessage(bs, m); err != nil { if _, err := store.PutMessage(bs, m); err != nil {
@ -1707,7 +1748,7 @@ func (syncer *Syncer) getLatestBeaconEntry(_ context.Context, ts *types.TipSet)
cur = next cur = next
} }
return nil, xerrors.Errorf("found NO beacon entries in the 20 blocks prior to given tipset") return nil, xerrors.Errorf("found NO beacon entries in the 20 latest tipsets")
} }
func (syncer *Syncer) IsEpochBeyondCurrMax(epoch abi.ChainEpoch) bool { func (syncer *Syncer) IsEpochBeyondCurrMax(epoch abi.ChainEpoch) bool {

View File

@ -19,13 +19,10 @@ 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/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"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/gen/slashfilter" "github.com/filecoin-project/lotus/chain/gen/slashfilter"
"github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/store"
@ -43,11 +40,9 @@ func init() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
miner.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{ policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
abi.RegisteredSealProof_StackedDrg2KiBV1: {}, policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
} policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
power.ConsensusMinerMinPower = big.NewInt(2048)
verifreg.MinVerifiedDealSize = big.NewInt(256)
} }
const source = 0 const source = 0
@ -737,7 +732,7 @@ func TestSyncInputs(t *testing.T) {
err := s.ValidateBlock(context.TODO(), &types.FullBlock{ err := s.ValidateBlock(context.TODO(), &types.FullBlock{
Header: &types.BlockHeader{}, Header: &types.BlockHeader{},
}) }, false)
if err == nil { if err == nil {
t.Fatal("should error on empty block") t.Fatal("should error on empty block")
} }
@ -746,7 +741,7 @@ func TestSyncInputs(t *testing.T) {
h.ElectionProof = nil h.ElectionProof = nil
err = s.ValidateBlock(context.TODO(), &types.FullBlock{Header: h}) err = s.ValidateBlock(context.TODO(), &types.FullBlock{Header: h}, false)
if err == nil { if err == nil {
t.Fatal("should error on block with nil election proof") t.Fatal("should error on block with nil election proof")
} }

View File

@ -5,7 +5,7 @@ import (
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
) )
var ErrActorNotFound = errors.New("actor not found") var ErrActorNotFound = errors.New("actor not found")
@ -19,5 +19,17 @@ type Actor struct {
} }
func (a *Actor) IsAccountActor() bool { func (a *Actor) IsAccountActor() bool {
return a.Code == builtin.AccountActorCodeID return a.Code == builtin0.AccountActorCodeID
}
func (a *Actor) IsStorageMinerActor() bool {
return a.Code == builtin0.StorageMinerActorCodeID
}
func (a *Actor) IsMultisigActor() bool {
return a.Code == builtin0.MultisigActorCodeID
}
func (a *Actor) IsPaymentChannelActor() bool {
return a.Code == builtin0.PaymentChannelActorCodeID
} }

View File

@ -1634,3 +1634,131 @@ func (t *BeaconEntry) UnmarshalCBOR(r io.Reader) error {
} }
return nil return nil
} }
var lengthBufStateRoot = []byte{131}
func (t *StateRoot) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write(lengthBufStateRoot); err != nil {
return err
}
scratch := make([]byte, 9)
// t.Version (uint64) (uint64)
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Version)); err != nil {
return err
}
// t.Actors (cid.Cid) (struct)
if err := cbg.WriteCidBuf(scratch, w, t.Actors); err != nil {
return xerrors.Errorf("failed to write cid field t.Actors: %w", err)
}
// t.Info (cid.Cid) (struct)
if err := cbg.WriteCidBuf(scratch, w, t.Info); err != nil {
return xerrors.Errorf("failed to write cid field t.Info: %w", err)
}
return nil
}
func (t *StateRoot) UnmarshalCBOR(r io.Reader) error {
*t = StateRoot{}
br := cbg.GetPeeker(r)
scratch := make([]byte, 8)
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 3 {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.Version (uint64) (uint64)
{
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Version = uint64(extra)
}
// t.Actors (cid.Cid) (struct)
{
c, err := cbg.ReadCid(br)
if err != nil {
return xerrors.Errorf("failed to read cid field t.Actors: %w", err)
}
t.Actors = c
}
// t.Info (cid.Cid) (struct)
{
c, err := cbg.ReadCid(br)
if err != nil {
return xerrors.Errorf("failed to read cid field t.Info: %w", err)
}
t.Info = c
}
return nil
}
var lengthBufStateInfo = []byte{128}
func (t *StateInfo) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write(lengthBufStateInfo); err != nil {
return err
}
return nil
}
func (t *StateInfo) UnmarshalCBOR(r io.Reader) error {
*t = StateInfo{}
br := cbg.GetPeeker(r)
scratch := make([]byte, 8)
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 0 {
return fmt.Errorf("cbor input had wrong number of fields")
}
return nil
}

15
chain/types/state.go Normal file
View File

@ -0,0 +1,15 @@
package types
import "github.com/ipfs/go-cid"
type StateRoot struct {
// State root version. Versioned along with actors (for now).
Version uint64
// Actors tree. The structure depends on the state root version.
Actors cid.Cid
// Info. The structure depends on the state root version.
Info cid.Cid
}
// TODO: version this.
type StateInfo struct{}

View File

@ -167,12 +167,16 @@ func (ts *TipSet) Equals(ots *TipSet) bool {
return false return false
} }
if len(ts.blks) != len(ots.blks) { if ts.height != ots.height {
return false return false
} }
for i, b := range ts.blks { if len(ts.cids) != len(ots.cids) {
if b.Cid() != ots.blks[i].Cid() { return false
}
for i, cid := range ts.cids {
if cid != ots.cids[i] {
return false return false
} }
} }

View File

@ -1,9 +1,12 @@
package chain package chain
import ( import (
"crypto/rand"
"encoding/json" "encoding/json"
"testing" "testing"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
@ -35,3 +38,40 @@ func TestSignedMessageJsonRoundtrip(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestAddressType(t *testing.T) {
build.SetAddressNetwork(address.Testnet)
addr, err := makeRandomAddress()
if err != nil {
t.Fatal(err)
}
if string(addr[0]) != address.TestnetPrefix {
t.Fatalf("address should start with %s", address.TestnetPrefix)
}
build.SetAddressNetwork(address.Mainnet)
addr, err = makeRandomAddress()
if err != nil {
t.Fatal(err)
}
if string(addr[0]) != address.MainnetPrefix {
t.Fatalf("address should start with %s", address.MainnetPrefix)
}
}
func makeRandomAddress() (string, error) {
bytes := make([]byte, 32)
_, err := rand.Read(bytes)
if err != nil {
return "", err
}
addr, err := address.NewActorAddress(bytes)
if err != nil {
return "", err
}
return addr.String(), nil
}

View File

@ -6,7 +6,7 @@ import (
"math/rand" "math/rand"
"os" "os"
"github.com/filecoin-project/specs-actors/actors/builtin/power" power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -19,15 +19,15 @@ import (
"github.com/filecoin-project/lotus/chain/types/mock" "github.com/filecoin-project/lotus/chain/types/mock"
"github.com/filecoin-project/lotus/chain/vectors" "github.com/filecoin-project/lotus/chain/vectors"
"github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg" verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
_ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp" _ "github.com/filecoin-project/lotus/lib/sigs/secp"
) )
func init() { func init() {
verifreg.MinVerifiedDealSize = big.NewInt(2048) verifreg0.MinVerifiedDealSize = big.NewInt(2048)
power.ConsensusMinerMinPower = big.NewInt(2048) power0.ConsensusMinerMinPower = big.NewInt(2048)
} }
func MakeHeaderVectors() []vectors.HeaderVector { func MakeHeaderVectors() []vectors.HeaderVector {

View File

@ -6,28 +6,28 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/specs-actors/actors/builtin/account"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/aerrors" account0 "github.com/filecoin-project/specs-actors/actors/builtin/account"
"github.com/filecoin-project/specs-actors/actors/builtin" cron0 "github.com/filecoin-project/specs-actors/actors/builtin/cron"
"github.com/filecoin-project/specs-actors/actors/builtin/cron" init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init" market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/market" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/specs-actors/actors/builtin/multisig" paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/builtin/paych" power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/power" reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/filecoin-project/specs-actors/actors/builtin/reward" system0 "github.com/filecoin-project/specs-actors/actors/builtin/system"
"github.com/filecoin-project/specs-actors/actors/builtin/system" verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/filecoin-project/specs-actors/actors/runtime"
vmr "github.com/filecoin-project/specs-actors/actors/runtime" vmr "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
) )
type Invoker struct { type Invoker struct {
@ -35,7 +35,7 @@ type Invoker struct {
builtInState map[cid.Cid]reflect.Type builtInState map[cid.Cid]reflect.Type
} }
type invokeFunc func(rt runtime.Runtime, params []byte) ([]byte, aerrors.ActorError) type invokeFunc func(rt vmr.Runtime, params []byte) ([]byte, aerrors.ActorError)
type nativeCode []invokeFunc type nativeCode []invokeFunc
func NewInvoker() *Invoker { func NewInvoker() *Invoker {
@ -45,22 +45,23 @@ func NewInvoker() *Invoker {
} }
// add builtInCode using: register(cid, singleton) // add builtInCode using: register(cid, singleton)
inv.Register(builtin.SystemActorCodeID, system.Actor{}, abi.EmptyValue{}) // NETUPGRADE: register code IDs for v2, etc.
inv.Register(builtin.InitActorCodeID, init_.Actor{}, init_.State{}) inv.Register(builtin0.SystemActorCodeID, system0.Actor{}, abi.EmptyValue{})
inv.Register(builtin.RewardActorCodeID, reward.Actor{}, reward.State{}) inv.Register(builtin0.InitActorCodeID, init0.Actor{}, init0.State{})
inv.Register(builtin.CronActorCodeID, cron.Actor{}, cron.State{}) inv.Register(builtin0.RewardActorCodeID, reward0.Actor{}, reward0.State{})
inv.Register(builtin.StoragePowerActorCodeID, power.Actor{}, power.State{}) inv.Register(builtin0.CronActorCodeID, cron0.Actor{}, cron0.State{})
inv.Register(builtin.StorageMarketActorCodeID, market.Actor{}, market.State{}) inv.Register(builtin0.StoragePowerActorCodeID, power0.Actor{}, power0.State{})
inv.Register(builtin.StorageMinerActorCodeID, miner.Actor{}, miner.State{}) inv.Register(builtin0.StorageMarketActorCodeID, market0.Actor{}, market0.State{})
inv.Register(builtin.MultisigActorCodeID, multisig.Actor{}, multisig.State{}) inv.Register(builtin0.StorageMinerActorCodeID, miner0.Actor{}, miner0.State{})
inv.Register(builtin.PaymentChannelActorCodeID, paych.Actor{}, paych.State{}) inv.Register(builtin0.MultisigActorCodeID, msig0.Actor{}, msig0.State{})
inv.Register(builtin.VerifiedRegistryActorCodeID, verifreg.Actor{}, verifreg.State{}) inv.Register(builtin0.PaymentChannelActorCodeID, paych0.Actor{}, paych0.State{})
inv.Register(builtin.AccountActorCodeID, account.Actor{}, account.State{}) inv.Register(builtin0.VerifiedRegistryActorCodeID, verifreg0.Actor{}, verifreg0.State{})
inv.Register(builtin0.AccountActorCodeID, account0.Actor{}, account0.State{})
return inv return inv
} }
func (inv *Invoker) Invoke(codeCid cid.Cid, rt runtime.Runtime, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) { func (inv *Invoker) Invoke(codeCid cid.Cid, rt vmr.Runtime, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) {
code, ok := inv.builtInCode[codeCid] code, ok := inv.builtInCode[codeCid]
if !ok { if !ok {
@ -176,7 +177,7 @@ func DecodeParams(b []byte, out interface{}) error {
} }
func DumpActorState(code cid.Cid, b []byte) (interface{}, error) { func DumpActorState(code cid.Cid, b []byte) (interface{}, error) {
if code == builtin.AccountActorCodeID { // Account code special case if code == builtin0.AccountActorCodeID { // Account code special case
return nil, nil return nil, nil
} }

View File

@ -5,18 +5,16 @@ import (
"context" "context"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
gruntime "runtime"
"time" "time"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/go-state-types/network"
rtt "github.com/filecoin-project/go-state-types/rt"
"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/cbor"
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-state-types/network"
rtt "github.com/filecoin-project/go-state-types/rt"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
rt0 "github.com/filecoin-project/specs-actors/actors/runtime" rt0 "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@ -318,14 +316,6 @@ func (rt *Runtime) CurrEpoch() abi.ChainEpoch {
return rt.height return rt.height
} }
type dumbWrapperType struct {
val []byte
}
func (dwt *dumbWrapperType) Into(um cbor.Unmarshaler) error {
return um.UnmarshalCBOR(bytes.NewReader(dwt.val))
}
func (rt *Runtime) Send(to address.Address, method abi.MethodNum, m cbor.Marshaler, value abi.TokenAmount, out cbor.Er) exitcode.ExitCode { func (rt *Runtime) Send(to address.Address, method abi.MethodNum, m cbor.Marshaler, value abi.TokenAmount, out cbor.Er) exitcode.ExitCode {
if !rt.allowInternal { if !rt.allowInternal {
rt.Abortf(exitcode.SysErrorIllegalActor, "runtime.Send() is currently disallowed") rt.Abortf(exitcode.SysErrorIllegalActor, "runtime.Send() is currently disallowed")
@ -391,8 +381,8 @@ func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum,
if subrt != nil { if subrt != nil {
rt.numActorsCreated = subrt.numActorsCreated rt.numActorsCreated = subrt.numActorsCreated
rt.executionTrace.Subcalls = append(rt.executionTrace.Subcalls, subrt.executionTrace)
} }
rt.executionTrace.Subcalls = append(rt.executionTrace.Subcalls, subrt.executionTrace)
return ret, errSend return ret, errSend
} }
@ -469,8 +459,10 @@ func (rt *Runtime) stateCommit(oldh, newh cid.Cid) aerrors.ActorError {
} }
func (rt *Runtime) finilizeGasTracing() { func (rt *Runtime) finilizeGasTracing() {
if rt.lastGasCharge != nil { if enableTracing {
rt.lastGasCharge.TimeTaken = time.Since(rt.lastGasChargeTime) if rt.lastGasCharge != nil {
rt.lastGasCharge.TimeTaken = time.Since(rt.lastGasChargeTime)
}
} }
} }
@ -499,34 +491,39 @@ func (rt *Runtime) chargeGasFunc(skip int) func(GasCharge) {
} }
var enableTracing = false
func (rt *Runtime) chargeGasInternal(gas GasCharge, skip int) aerrors.ActorError { func (rt *Runtime) chargeGasInternal(gas GasCharge, skip int) aerrors.ActorError {
toUse := gas.Total() toUse := gas.Total()
var callers [10]uintptr if enableTracing {
cout := gruntime.Callers(2+skip, callers[:]) var callers [10]uintptr
now := build.Clock.Now() cout := 0 //gruntime.Callers(2+skip, callers[:])
if rt.lastGasCharge != nil {
rt.lastGasCharge.TimeTaken = now.Sub(rt.lastGasChargeTime) now := build.Clock.Now()
if rt.lastGasCharge != nil {
rt.lastGasCharge.TimeTaken = now.Sub(rt.lastGasChargeTime)
}
gasTrace := types.GasTrace{
Name: gas.Name,
Extra: gas.Extra,
TotalGas: toUse,
ComputeGas: gas.ComputeGas,
StorageGas: gas.StorageGas,
TotalVirtualGas: gas.VirtualCompute*GasComputeMulti + gas.VirtualStorage*GasStorageMulti,
VirtualComputeGas: gas.VirtualCompute,
VirtualStorageGas: gas.VirtualStorage,
Callers: callers[:cout],
}
rt.executionTrace.GasCharges = append(rt.executionTrace.GasCharges, &gasTrace)
rt.lastGasChargeTime = now
rt.lastGasCharge = &gasTrace
} }
gasTrace := types.GasTrace{
Name: gas.Name,
Extra: gas.Extra,
TotalGas: toUse,
ComputeGas: gas.ComputeGas,
StorageGas: gas.StorageGas,
TotalVirtualGas: gas.VirtualCompute*GasComputeMulti + gas.VirtualStorage*GasStorageMulti,
VirtualComputeGas: gas.VirtualCompute,
VirtualStorageGas: gas.VirtualStorage,
Callers: callers[:cout],
}
rt.executionTrace.GasCharges = append(rt.executionTrace.GasCharges, &gasTrace)
rt.lastGasChargeTime = now
rt.lastGasCharge = &gasTrace
// overflow safe // overflow safe
if rt.gasUsed > rt.gasAvailable-toUse { if rt.gasUsed > rt.gasAvailable-toUse {
rt.gasUsed = rt.gasAvailable rt.gasUsed = rt.gasAvailable

View File

@ -18,12 +18,12 @@ import (
"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"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"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"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/runtime" "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
) )
@ -192,12 +192,12 @@ func (ss *syscallShim) VerifyBlockSig(blk *types.BlockHeader) error {
} }
// use that to get the miner state // use that to get the miner state
var mas miner.State mas, err := miner.Load(adt.WrapStore(ss.ctx, ss.cst), act)
if err = ss.cst.Get(ss.ctx, act.Head, &mas); err != nil { if err != nil {
return err return err
} }
info, err := mas.GetInfo(adt.WrapStore(ss.ctx, ss.cst)) info, err := mas.Info()
if err != nil { if err != nil {
return err return err
} }

View File

@ -5,15 +5,9 @@ import (
"context" "context"
"fmt" "fmt"
"reflect" "reflect"
"sync/atomic"
"time" "time"
"github.com/filecoin-project/go-state-types/network"
bstore "github.com/filecoin-project/lotus/lib/blockstore"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/specs-actors/actors/builtin"
block "github.com/ipfs/go-block-format" block "github.com/ipfs/go-block-format"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
@ -25,15 +19,21 @@ 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/crypto" "github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/specs-actors/actors/builtin/account" "github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/actors/builtin/account"
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
"github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/blockstore" "github.com/filecoin-project/lotus/lib/blockstore"
bstore "github.com/filecoin-project/lotus/lib/blockstore"
"github.com/filecoin-project/lotus/lib/bufbstore" "github.com/filecoin-project/lotus/lib/bufbstore"
) )
@ -41,6 +41,12 @@ 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)
// stat counters
var (
StatSends uint64
StatApplied uint64
)
// ResolveToKeyAddr returns the public key type of address (`BLS`/`SECP256K1`) of an account actor identified by `addr`. // ResolveToKeyAddr returns the public key type of address (`BLS`/`SECP256K1`) of an account actor identified by `addr`.
func ResolveToKeyAddr(state types.StateTree, cst cbor.IpldStore, addr address.Address) (address.Address, error) { func ResolveToKeyAddr(state types.StateTree, cst cbor.IpldStore, addr address.Address) (address.Address, error) {
if addr.Protocol() == address.BLS || addr.Protocol() == address.SECP256K1 { if addr.Protocol() == address.BLS || addr.Protocol() == address.SECP256K1 {
@ -52,16 +58,12 @@ func ResolveToKeyAddr(state types.StateTree, cst cbor.IpldStore, addr address.Ad
return address.Undef, xerrors.Errorf("failed to find actor: %s", addr) return address.Undef, xerrors.Errorf("failed to find actor: %s", addr)
} }
if act.Code != builtin.AccountActorCodeID { aast, err := account.Load(adt.WrapStore(context.TODO(), cst), act)
return address.Undef, xerrors.Errorf("address %s was not for an account actor", addr) if err != nil {
}
var aast account.State
if err := cst.Get(context.TODO(), act.Head, &aast); err != nil {
return address.Undef, xerrors.Errorf("failed to get account actor state for %s: %w", addr, err) return address.Undef, xerrors.Errorf("failed to get account actor state for %s: %w", addr, err)
} }
return aast.Address, nil return aast.PubkeyAddress()
} }
var _ cbor.IpldBlockstore = (*gasChargingBlocks)(nil) var _ cbor.IpldBlockstore = (*gasChargingBlocks)(nil)
@ -166,11 +168,11 @@ type VMOpts struct {
Bstore bstore.Blockstore Bstore bstore.Blockstore
Syscalls SyscallBuilder Syscalls SyscallBuilder
CircSupplyCalc CircSupplyCalculator CircSupplyCalc CircSupplyCalculator
NtwkVersion NtwkVersionGetter NtwkVersion NtwkVersionGetter // TODO: stebalien: In what cases do we actually need this? It seems like even when creating new networks we want to use the 'global'/build-default version getter
BaseFee abi.TokenAmount BaseFee abi.TokenAmount
} }
func NewVM(opts *VMOpts) (*VM, error) { func NewVM(ctx context.Context, opts *VMOpts) (*VM, error) {
buf := bufbstore.NewBufferedBstore(opts.Bstore) buf := bufbstore.NewBufferedBstore(opts.Bstore)
cst := cbor.NewCborStore(buf) cst := cbor.NewCborStore(buf)
state, err := state.LoadStateTree(cst, opts.StateBase) state, err := state.LoadStateTree(cst, opts.StateBase)
@ -209,6 +211,8 @@ type ApplyRet struct {
func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime, func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
gasCharge *GasCharge, start time.Time) ([]byte, aerrors.ActorError, *Runtime) { gasCharge *GasCharge, start time.Time) ([]byte, aerrors.ActorError, *Runtime) {
defer atomic.AddUint64(&StatSends, 1)
st := vm.cstate st := vm.cstate
origin := msg.From origin := msg.From
@ -223,14 +227,21 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
} }
rt := vm.makeRuntime(ctx, msg, origin, on, gasUsed, nac) rt := vm.makeRuntime(ctx, msg, origin, on, gasUsed, nac)
rt.lastGasChargeTime = start if enableTracing {
rt.lastGasChargeTime = start
if parent != nil {
rt.lastGasChargeTime = parent.lastGasChargeTime
rt.lastGasCharge = parent.lastGasCharge
defer func() {
parent.lastGasChargeTime = rt.lastGasChargeTime
parent.lastGasCharge = rt.lastGasCharge
}()
}
}
if parent != nil { if parent != nil {
rt.lastGasChargeTime = parent.lastGasChargeTime
rt.lastGasCharge = parent.lastGasCharge
defer func() { defer func() {
parent.gasUsed = rt.gasUsed parent.gasUsed = rt.gasUsed
parent.lastGasChargeTime = rt.lastGasChargeTime
parent.lastGasCharge = rt.lastGasCharge
}() }()
} }
if gasCharge != nil { if gasCharge != nil {
@ -317,6 +328,7 @@ func checkMessage(msg *types.Message) error {
func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) { func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) {
start := build.Clock.Now() start := build.Clock.Now()
defer atomic.AddUint64(&StatApplied, 1)
ret, actorErr, rt := vm.send(ctx, msg, nil, nil, start) ret, actorErr, rt := vm.send(ctx, msg, nil, nil, start)
rt.finilizeGasTracing() rt.finilizeGasTracing()
return &ApplyRet{ return &ApplyRet{
@ -336,6 +348,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
start := build.Clock.Now() start := build.Clock.Now()
ctx, span := trace.StartSpan(ctx, "vm.ApplyMessage") ctx, span := trace.StartSpan(ctx, "vm.ApplyMessage")
defer span.End() defer span.End()
defer atomic.AddUint64(&StatApplied, 1)
msg := cmsg.VMMessage() msg := cmsg.VMMessage()
if span.IsRecordingEvents() { if span.IsRecordingEvents() {
span.AddAttributes( span.AddAttributes(
@ -390,7 +403,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
} }
// this should never happen, but is currently still exercised by some tests // this should never happen, but is currently still exercised by some tests
if !fromActor.Code.Equals(builtin.AccountActorCodeID) { if !fromActor.IsAccountActor() {
gasOutputs := ZeroGasOutputs() gasOutputs := ZeroGasOutputs()
gasOutputs.MinerPenalty = minerPenaltyAmount gasOutputs.MinerPenalty = minerPenaltyAmount
return &ApplyRet{ return &ApplyRet{
@ -499,7 +512,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
return nil, xerrors.Errorf("failed to burn base fee: %w", err) return nil, xerrors.Errorf("failed to burn base fee: %w", err)
} }
if err := vm.transferFromGasHolder(builtin.RewardActorAddr, gasHolder, gasOutputs.MinerTip); err != nil { if err := vm.transferFromGasHolder(reward.Address, gasHolder, gasOutputs.MinerTip); err != nil {
return nil, xerrors.Errorf("failed to give miner gas reward: %w", err) return nil, xerrors.Errorf("failed to give miner gas reward: %w", err)
} }
@ -551,7 +564,7 @@ func (vm *VM) Flush(ctx context.Context) (cid.Cid, error) {
return cid.Undef, xerrors.Errorf("flushing vm: %w", err) return cid.Undef, xerrors.Errorf("flushing vm: %w", err)
} }
if err := Copy(from, to, root); err != nil { if err := Copy(ctx, from, to, root); err != nil {
return cid.Undef, xerrors.Errorf("copying tree: %w", err) return cid.Undef, xerrors.Errorf("copying tree: %w", err)
} }
@ -605,9 +618,18 @@ func linksForObj(blk block.Block, cb func(cid.Cid)) error {
} }
} }
func Copy(from, to blockstore.Blockstore, root cid.Cid) error { func Copy(ctx context.Context, from, to blockstore.Blockstore, root cid.Cid) error {
ctx, span := trace.StartSpan(ctx, "vm.Copy") // nolint
defer span.End()
var numBlocks int
var totalCopySize int
var batch []block.Block var batch []block.Block
batchCp := func(blk block.Block) error { batchCp := func(blk block.Block) error {
numBlocks++
totalCopySize += len(blk.RawData())
batch = append(batch, blk) batch = append(batch, blk)
if len(batch) > 100 { if len(batch) > 100 {
if err := to.PutMany(batch); err != nil { if err := to.PutMany(batch); err != nil {
@ -628,6 +650,11 @@ func Copy(from, to blockstore.Blockstore, root cid.Cid) error {
} }
} }
span.AddAttributes(
trace.Int64Attribute("numBlocks", int64(numBlocks)),
trace.Int64Attribute("copySize", int64(totalCopySize)),
)
return nil return nil
} }

View File

@ -40,6 +40,7 @@ var chainCmd = &cli.Command{
chainHeadCmd, chainHeadCmd,
chainGetBlock, chainGetBlock,
chainReadObjCmd, chainReadObjCmd,
chainDeleteObjCmd,
chainStatObjCmd, chainStatObjCmd,
chainGetMsgCmd, chainGetMsgCmd,
chainSetHeadCmd, chainSetHeadCmd,
@ -193,6 +194,43 @@ var chainReadObjCmd = &cli.Command{
}, },
} }
var chainDeleteObjCmd = &cli.Command{
Name: "delete-obj",
Usage: "Delete an object from the chain blockstore",
Description: "WARNING: Removing wrong objects from the chain blockstore may lead to sync issues",
ArgsUsage: "[objectCid]",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "really-do-it",
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
c, err := cid.Decode(cctx.Args().First())
if err != nil {
return fmt.Errorf("failed to parse cid input: %s", err)
}
if !cctx.Bool("really-do-it") {
return xerrors.Errorf("pass the --really-do-it flag to proceed")
}
err = api.ChainDeleteObj(ctx, c)
if err != nil {
return err
}
fmt.Printf("Obj %s deleted\n", c.String())
return nil
},
}
var chainStatObjCmd = &cli.Command{ var chainStatObjCmd = &cli.Command{
Name: "stat-obj", Name: "stat-obj",
Usage: "Collect size and ipld link counts for objs", Usage: "Collect size and ipld link counts for objs",

View File

@ -31,11 +31,11 @@ import (
"github.com/filecoin-project/go-multistore" "github.com/filecoin-project/go-multistore"
"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/specs-actors/actors/builtin/market"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
lapi "github.com/filecoin-project/lotus/api" lapi "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/market"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/tablewriter" "github.com/filecoin-project/lotus/lib/tablewriter"
) )
@ -569,7 +569,7 @@ func interactiveDeal(cctx *cli.Context) error {
continue continue
} }
ask = *a.Ask ask = *a
// TODO: run more validation // TODO: run more validation
state = "confirm" state = "confirm"
@ -951,15 +951,15 @@ var clientQueryAskCmd = &cli.Command{
} }
fmt.Printf("Ask: %s\n", maddr) fmt.Printf("Ask: %s\n", maddr)
fmt.Printf("Price per GiB: %s\n", types.FIL(ask.Ask.Price)) fmt.Printf("Price per GiB: %s\n", types.FIL(ask.Price))
fmt.Printf("Verified Price per GiB: %s\n", types.FIL(ask.Ask.VerifiedPrice)) fmt.Printf("Verified Price per GiB: %s\n", types.FIL(ask.VerifiedPrice))
fmt.Printf("Max Piece size: %s\n", types.SizeStr(types.NewInt(uint64(ask.Ask.MaxPieceSize)))) fmt.Printf("Max Piece size: %s\n", types.SizeStr(types.NewInt(uint64(ask.MaxPieceSize))))
size := cctx.Int64("size") size := cctx.Int64("size")
if size == 0 { if size == 0 {
return nil return nil
} }
perEpoch := types.BigDiv(types.BigMul(ask.Ask.Price, types.NewInt(uint64(size))), types.NewInt(1<<30)) perEpoch := types.BigDiv(types.BigMul(ask.Price, types.NewInt(uint64(size))), types.NewInt(1<<30))
fmt.Printf("Price per Block: %s\n", types.FIL(perEpoch)) fmt.Printf("Price per Block: %s\n", types.FIL(perEpoch))
duration := cctx.Int64("duration") duration := cctx.Int64("duration")
@ -1051,12 +1051,8 @@ var clientListDeals = &cli.Command{
func dealFromDealInfo(ctx context.Context, full api.FullNode, head *types.TipSet, v api.DealInfo) deal { func dealFromDealInfo(ctx context.Context, full api.FullNode, head *types.TipSet, v api.DealInfo) deal {
if v.DealID == 0 { if v.DealID == 0 {
return deal{ return deal{
LocalDeal: v, LocalDeal: v,
OnChainDealState: market.DealState{ OnChainDealState: *market.EmptyDealState(),
SectorStartEpoch: -1,
LastUpdatedEpoch: -1,
SlashEpoch: -1,
},
} }
} }
@ -1427,7 +1423,7 @@ func toChannelOutput(useColor bool, otherPartyColumn string, channel lapi.DataTr
otherPartyColumn: otherParty, otherPartyColumn: otherParty,
"Root Cid": rootCid, "Root Cid": rootCid,
"Initiated?": initiated, "Initiated?": initiated,
"Transferred": channel.Transferred, "Transferred": units.BytesSize(float64(channel.Transferred)),
"Voucher": voucher, "Voucher": voucher,
"Message": channel.Message, "Message": channel.Message,
} }

View File

@ -7,6 +7,7 @@ import (
"sort" "sort"
"strconv" "strconv"
cid "github.com/ipfs/go-cid"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -43,6 +44,10 @@ var mpoolPending = &cli.Command{
Name: "local", Name: "local",
Usage: "print pending messages for addresses in local wallet only", Usage: "print pending messages for addresses in local wallet only",
}, },
&cli.BoolFlag{
Name: "cids",
Usage: "only print cids of messages in output",
},
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
@ -79,11 +84,15 @@ var mpoolPending = &cli.Command{
} }
} }
out, err := json.MarshalIndent(msg, "", " ") if cctx.Bool("cids") {
if err != nil { fmt.Println(msg.Cid())
return err } else {
out, err := json.MarshalIndent(msg, "", " ")
if err != nil {
return err
}
fmt.Println(string(out))
} }
fmt.Println(string(out))
} }
return nil return nil
@ -308,21 +317,8 @@ var mpoolReplaceCmd = &cli.Command{
Usage: "Spend up to X FIL for this message (applicable for auto mode)", Usage: "Spend up to X FIL for this message (applicable for auto mode)",
}, },
}, },
ArgsUsage: "[from] [nonce]", ArgsUsage: "<from nonce> | <message-cid>",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
if cctx.Args().Len() < 2 {
return cli.ShowCommandHelp(cctx, cctx.Command.Name)
}
from, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return err
}
nonce, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
if err != nil {
return err
}
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
@ -332,6 +328,39 @@ var mpoolReplaceCmd = &cli.Command{
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
var from address.Address
var nonce uint64
switch cctx.Args().Len() {
case 1:
mcid, err := cid.Decode(cctx.Args().First())
if err != nil {
return err
}
msg, err := api.ChainGetMessage(ctx, mcid)
if err != nil {
return fmt.Errorf("could not find referenced message: %w", err)
}
from = msg.From
nonce = msg.Nonce
case 2:
f, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return err
}
n, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
if err != nil {
return err
}
from = f
nonce = n
default:
return cli.ShowCommandHelp(cctx, cctx.Command.Name)
}
ts, err := api.ChainHead(ctx) ts, err := api.ChainHead(ctx)
if err != nil { if err != nil {
return xerrors.Errorf("getting chain head: %w", err) return xerrors.Errorf("getting chain head: %w", err)

View File

@ -2,8 +2,6 @@ package cli
import ( import (
"bytes" "bytes"
"context"
"encoding/binary"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"os" "os"
@ -11,22 +9,26 @@ import (
"strconv" "strconv"
"text/tabwriter" "text/tabwriter"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
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"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/specs-actors/actors/builtin"
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/lotus/api/apibstore" "github.com/filecoin-project/lotus/api/apibstore"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
types "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/types"
) )
var multisigCmd = &cli.Command{ var multisigCmd = &cli.Command{
@ -43,6 +45,9 @@ var multisigCmd = &cli.Command{
msigSwapProposeCmd, msigSwapProposeCmd,
msigSwapApproveCmd, msigSwapApproveCmd,
msigSwapCancelCmd, msigSwapCancelCmd,
msigLockProposeCmd,
msigLockApproveCmd,
msigLockCancelCmd,
msigVestedCmd, msigVestedCmd,
}, },
} }
@ -146,7 +151,7 @@ var msigCreateCmd = &cli.Command{
// get address of newly created miner // get address of newly created miner
var execreturn init_.ExecReturn var execreturn init0.ExecReturn
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
} }
@ -179,50 +184,73 @@ var msigInspectCmd = &cli.Command{
defer closer() defer closer()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
store := adt.WrapStore(ctx, cbor.NewCborStore(apibstore.NewAPIBlockstore(api)))
maddr, err := address.NewFromString(cctx.Args().First()) maddr, err := address.NewFromString(cctx.Args().First())
if err != nil { if err != nil {
return err return err
} }
act, err := api.StateGetActor(ctx, maddr, types.EmptyTSK)
if err != nil {
return err
}
obj, err := api.ChainReadObj(ctx, act.Head)
if err != nil {
return err
}
head, err := api.ChainHead(ctx) head, err := api.ChainHead(ctx)
if err != nil { if err != nil {
return err return err
} }
var mstate samsig.State act, err := api.StateGetActor(ctx, maddr, head.Key())
if err := mstate.UnmarshalCBOR(bytes.NewReader(obj)); err != nil { if err != nil {
return err
}
mstate, err := multisig.Load(store, act)
if err != nil {
return err
}
locked, err := mstate.LockedBalance(head.Height())
if err != nil {
return err return err
} }
locked := mstate.AmountLocked(head.Height() - mstate.StartEpoch)
fmt.Printf("Balance: %s\n", types.FIL(act.Balance)) fmt.Printf("Balance: %s\n", types.FIL(act.Balance))
fmt.Printf("Spendable: %s\n", types.FIL(types.BigSub(act.Balance, locked))) fmt.Printf("Spendable: %s\n", types.FIL(types.BigSub(act.Balance, locked)))
if cctx.Bool("vesting") { if cctx.Bool("vesting") {
fmt.Printf("InitialBalance: %s\n", types.FIL(mstate.InitialBalance)) ib, err := mstate.InitialBalance()
fmt.Printf("StartEpoch: %d\n", mstate.StartEpoch) if err != nil {
fmt.Printf("UnlockDuration: %d\n", mstate.UnlockDuration) return err
}
fmt.Printf("InitialBalance: %s\n", types.FIL(ib))
se, err := mstate.StartEpoch()
if err != nil {
return err
}
fmt.Printf("StartEpoch: %d\n", se)
ud, err := mstate.UnlockDuration()
if err != nil {
return err
}
fmt.Printf("UnlockDuration: %d\n", ud)
} }
fmt.Printf("Threshold: %d / %d\n", mstate.NumApprovalsThreshold, len(mstate.Signers)) signers, err := mstate.Signers()
if err != nil {
return err
}
threshold, err := mstate.Threshold()
if err != nil {
return err
}
fmt.Printf("Threshold: %d / %d\n", threshold, len(signers))
fmt.Println("Signers:") fmt.Println("Signers:")
for _, s := range mstate.Signers { for _, s := range signers {
fmt.Printf("\t%s\n", s) fmt.Printf("\t%s\n", s)
} }
pending, err := GetMultisigPending(ctx, api, mstate.PendingTxns) pending := make(map[int64]multisig.Transaction)
if err != nil { if err := mstate.ForEachPendingTxn(func(id int64, txn multisig.Transaction) error {
return fmt.Errorf("reading pending transactions: %w", err) pending[id] = txn
return nil
}); err != nil {
return xerrors.Errorf("reading pending transactions: %w", err)
} }
fmt.Println("Transactions: ", len(pending)) fmt.Println("Transactions: ", len(pending))
@ -239,7 +267,7 @@ var msigInspectCmd = &cli.Command{
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]
fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%d\t%x\n", txid, state(tx), len(tx.Approved), tx.To, types.FIL(tx.Value), tx.Method, tx.Params) fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%d\t%x\n", txid, "pending", len(tx.Approved), tx.To, types.FIL(tx.Value), tx.Method, tx.Params)
} }
if err := w.Flush(); err != nil { if err := w.Flush(); err != nil {
return xerrors.Errorf("flushing output: %+v", err) return xerrors.Errorf("flushing output: %+v", err)
@ -251,43 +279,6 @@ var msigInspectCmd = &cli.Command{
}, },
} }
func GetMultisigPending(ctx context.Context, lapi api.FullNode, hroot cid.Cid) (map[int64]*samsig.Transaction, error) {
bs := apibstore.NewAPIBlockstore(lapi)
store := adt.WrapStore(ctx, cbor.NewCborStore(bs))
nd, err := adt.AsMap(store, hroot)
if err != nil {
return nil, err
}
txs := make(map[int64]*samsig.Transaction)
var tx samsig.Transaction
err = nd.ForEach(&tx, func(k string) error {
txid, _ := binary.Varint([]byte(k))
cpy := tx // copy so we don't clobber on future iterations.
txs[txid] = &cpy
return nil
})
if err != nil {
return nil, xerrors.Errorf("failed to iterate transactions hamt: %w", err)
}
return txs, nil
}
func state(tx *samsig.Transaction) string {
/* // TODO(why): I strongly disagree with not having these... but i need to move forward
if tx.Complete {
return "done"
}
if tx.Canceled {
return "canceled"
}
*/
return "pending"
}
var msigProposeCmd = &cli.Command{ var msigProposeCmd = &cli.Command{
Name: "propose", Name: "propose",
Usage: "Propose a multisig transaction", Usage: "Propose a multisig transaction",
@ -365,7 +356,7 @@ var msigProposeCmd = &cli.Command{
return fmt.Errorf("failed to look up multisig %s: %w", msig, err) return fmt.Errorf("failed to look up multisig %s: %w", msig, err)
} }
if act.Code != builtin.MultisigActorCodeID { if !act.IsMultisigActor() {
return fmt.Errorf("actor %s is not a multisig actor", msig) return fmt.Errorf("actor %s is not a multisig actor", msig)
} }
@ -385,7 +376,7 @@ var msigProposeCmd = &cli.Command{
return fmt.Errorf("proposal returned exit %d", wait.Receipt.ExitCode) return fmt.Errorf("proposal returned exit %d", wait.Receipt.ExitCode)
} }
var retval samsig.ProposeReturn var retval msig0.ProposeReturn
if err := retval.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)); err != nil { if err := retval.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)); err != nil {
return fmt.Errorf("failed to unmarshal propose return value: %w", err) return fmt.Errorf("failed to unmarshal propose return value: %w", err)
} }
@ -971,6 +962,282 @@ var msigSwapCancelCmd = &cli.Command{
}, },
} }
var msigLockProposeCmd = &cli.Command{
Name: "lock-propose",
Usage: "Propose to lock up some balance",
ArgsUsage: "[multisigAddress startEpoch unlockDuration amount]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
Usage: "account to send the propose message from",
},
},
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 4 {
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, start epoch, unlock duration, and amount"))
}
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
}
start, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
if err != nil {
return err
}
duration, err := strconv.ParseUint(cctx.Args().Get(2), 10, 64)
if err != nil {
return err
}
amount, err := types.ParseFIL(cctx.Args().Get(3))
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.LockBalanceParams{
StartEpoch: abi.ChainEpoch(start),
UnlockDuration: abi.ChainEpoch(duration),
Amount: abi.NewTokenAmount(amount.Int64()),
})
if actErr != nil {
return actErr
}
msgCid, err := api.MsigPropose(ctx, msig, msig, big.Zero(), from, uint64(builtin.MethodsMultisig.LockBalance), params)
if err != nil {
return err
}
fmt.Println("sent lock proposal in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
if err != nil {
return err
}
if wait.Receipt.ExitCode != 0 {
return fmt.Errorf("lock proposal returned exit %d", wait.Receipt.ExitCode)
}
return nil
},
}
var msigLockApproveCmd = &cli.Command{
Name: "lock-approve",
Usage: "Approve a message to lock up some balance",
ArgsUsage: "[multisigAddress proposerAddress txId startEpoch unlockDuration amount]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
Usage: "account to send the approve message from",
},
},
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 6 {
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, proposer address, tx id, start epoch, unlock duration, and amount"))
}
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
}
prop, err := address.NewFromString(cctx.Args().Get(1))
if err != nil {
return err
}
txid, err := strconv.ParseUint(cctx.Args().Get(2), 10, 64)
if err != nil {
return err
}
start, err := strconv.ParseUint(cctx.Args().Get(3), 10, 64)
if err != nil {
return err
}
duration, err := strconv.ParseUint(cctx.Args().Get(4), 10, 64)
if err != nil {
return err
}
amount, err := types.ParseFIL(cctx.Args().Get(5))
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.LockBalanceParams{
StartEpoch: abi.ChainEpoch(start),
UnlockDuration: abi.ChainEpoch(duration),
Amount: abi.NewTokenAmount(amount.Int64()),
})
if actErr != nil {
return actErr
}
msgCid, err := api.MsigApprove(ctx, msig, txid, prop, msig, big.Zero(), from, uint64(builtin.MethodsMultisig.LockBalance), params)
if err != nil {
return err
}
fmt.Println("sent lock approval in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
if err != nil {
return err
}
if wait.Receipt.ExitCode != 0 {
return fmt.Errorf("lock approval returned exit %d", wait.Receipt.ExitCode)
}
return nil
},
}
var msigLockCancelCmd = &cli.Command{
Name: "lock-cancel",
Usage: "Cancel a message to lock up some balance",
ArgsUsage: "[multisigAddress txId startEpoch unlockDuration amount]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
Usage: "account to send the cancel message from",
},
},
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 6 {
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, tx id, start epoch, unlock duration, and amount"))
}
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
}
txid, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
if err != nil {
return err
}
start, err := strconv.ParseUint(cctx.Args().Get(2), 10, 64)
if err != nil {
return err
}
duration, err := strconv.ParseUint(cctx.Args().Get(3), 10, 64)
if err != nil {
return err
}
amount, err := types.ParseFIL(cctx.Args().Get(4))
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.LockBalanceParams{
StartEpoch: abi.ChainEpoch(start),
UnlockDuration: abi.ChainEpoch(duration),
Amount: abi.NewTokenAmount(amount.Int64()),
})
if actErr != nil {
return actErr
}
msgCid, err := api.MsigCancel(ctx, msig, txid, msig, big.Zero(), from, uint64(builtin.MethodsMultisig.LockBalance), params)
if err != nil {
return err
}
fmt.Println("sent lock cancellation in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
if err != nil {
return err
}
if wait.Receipt.ExitCode != 0 {
return fmt.Errorf("lock cancellation returned exit %d", wait.Receipt.ExitCode)
}
return nil
},
}
var msigVestedCmd = &cli.Command{ var msigVestedCmd = &cli.Command{
Name: "vested", Name: "vested",
Usage: "Gets the amount vested in an msig between two epochs", Usage: "Gets the amount vested in an msig between two epochs",

View File

@ -12,38 +12,31 @@ import (
"testing" "testing"
"time" "time"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/go-state-types/big"
saminer "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
"github.com/multiformats/go-multiaddr"
"github.com/filecoin-project/lotus/chain/events"
"github.com/filecoin-project/lotus/api/apibstore"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api/test"
"github.com/filecoin-project/lotus/chain/wallet"
builder "github.com/filecoin-project/lotus/node/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/multiformats/go-multiaddr"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/api/apibstore"
"github.com/filecoin-project/lotus/api/test"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/events"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
builder "github.com/filecoin-project/lotus/node/test"
) )
func init() { func init() {
power.ConsensusMinerMinPower = big.NewInt(2048) policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
saminer.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{ policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
abi.RegisteredSealProof_StackedDrg2KiBV1: {}, policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
}
verifreg.MinVerifiedDealSize = big.NewInt(256)
} }
// TestPaymentChannels does a basic test to exercise the payment channel CLI // TestPaymentChannels does a basic test to exercise the payment channel CLI
@ -88,7 +81,9 @@ func TestPaymentChannels(t *testing.T) {
// Wait for the chain to reach the settle height // Wait for the chain to reach the settle height
chState := getPaychState(ctx, t, paymentReceiver, chAddr) chState := getPaychState(ctx, t, paymentReceiver, chAddr)
waitForHeight(ctx, t, paymentReceiver, chState.SettlingAt) sa, err := chState.SettlingAt()
require.NoError(t, err)
waitForHeight(ctx, t, paymentReceiver, sa)
// receiver: paych collect <channel> // receiver: paych collect <channel>
cmd = []string{chAddr.String()} cmd = []string{chAddr.String()}
@ -540,8 +535,7 @@ func getPaychState(ctx context.Context, t *testing.T, node test.TestNode, chAddr
require.NoError(t, err) require.NoError(t, err)
store := cbor.NewCborStore(apibstore.NewAPIBlockstore(node)) store := cbor.NewCborStore(apibstore.NewAPIBlockstore(node))
var chState paych.State chState, err := paych.Load(adt.WrapStore(ctx, store), act)
err = store.Get(ctx, act.Head, &chState)
require.NoError(t, err) require.NoError(t, err)
return chState return chState

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