Merge branch 'master' into asr/spec-v1
This commit is contained in:
		
						commit
						947d1e2902
					
				
							
								
								
									
										57
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @ -1,5 +1,62 @@ | |||||||
| # Lotus changelog | # Lotus changelog | ||||||
| 
 | 
 | ||||||
|  | # 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 | # 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. | 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. | ||||||
|  | |||||||
| @ -94,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 | ||||||
|  | |||||||
| @ -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 | ||||||
|  | |||||||
| @ -12,6 +12,8 @@ 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, | ||||||
|  | |||||||
| @ -3,6 +3,8 @@ 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" | ||||||
| @ -44,3 +46,7 @@ func UseNewestNetwork() bool { | |||||||
| 	} | 	} | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func SetAddressNetwork(n address.Network) { | ||||||
|  | 	address.CurrentNetwork = n | ||||||
|  | } | ||||||
|  | |||||||
| @ -4,6 +4,9 @@ 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" | ||||||
| 
 | 
 | ||||||
| @ -22,8 +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.Version3 | const ActorUpgradeNetworkVersion = network.Version4 | ||||||
| 
 | 
 | ||||||
| // Epochs
 | // Epochs
 | ||||||
| const ForkLengthThreshold = Finality | const ForkLengthThreshold = Finality | ||||||
| @ -60,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) | ||||||
| 
 | 
 | ||||||
| @ -75,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
 | ||||||
|  | |||||||
| @ -74,7 +74,9 @@ 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, | ||||||
| @ -82,4 +84,6 @@ var ( | |||||||
| 
 | 
 | ||||||
| 	NewestNetworkVersion       = network.Version2 | 	NewestNetworkVersion       = network.Version2 | ||||||
| 	ActorUpgradeNetworkVersion = network.Version3 | 	ActorUpgradeNetworkVersion = network.Version3 | ||||||
|  | 
 | ||||||
|  | 	Devnet = true | ||||||
| ) | ) | ||||||
|  | |||||||
| @ -21,12 +21,20 @@ 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() { | ||||||
| 	policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40)) | 	policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40)) | ||||||
| 	policy.SetSupportedProofTypes( | 	policy.SetSupportedProofTypes( | ||||||
| 		abi.RegisteredSealProof_StackedDrg32GiBV1, | 		abi.RegisteredSealProof_StackedDrg32GiBV1, | ||||||
| 		abi.RegisteredSealProof_StackedDrg64GiBV1, | 		abi.RegisteredSealProof_StackedDrg64GiBV1, | ||||||
| 	) | 	) | ||||||
|  | 	Devnet = false | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const BlockDelaySecs = uint64(builtin0.EpochDurationSeconds) | const BlockDelaySecs = uint64(builtin0.EpochDurationSeconds) | ||||||
|  | |||||||
| @ -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.2" | const BuildVersion = "0.8.0" | ||||||
| 
 | 
 | ||||||
| func UserVersion() string { | func UserVersion() string { | ||||||
| 	return BuildVersion + buildType() + CurrentCommit | 	return BuildVersion + buildType() + CurrentCommit | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ import ( | |||||||
| 	"github.com/ipfs/go-cid" | 	"github.com/ipfs/go-cid" | ||||||
| 	"github.com/libp2p/go-libp2p-core/peer" | 	"github.com/libp2p/go-libp2p-core/peer" | ||||||
| 	cbg "github.com/whyrusleeping/cbor-gen" | 	cbg "github.com/whyrusleeping/cbor-gen" | ||||||
|  | 	"golang.org/x/xerrors" | ||||||
| 
 | 
 | ||||||
| 	"github.com/filecoin-project/lotus/chain/actors/adt" | 	"github.com/filecoin-project/lotus/chain/actors/adt" | ||||||
| 
 | 
 | ||||||
| @ -106,9 +107,7 @@ func (s *state0) NumLiveSectors() (uint64, error) { | |||||||
| 
 | 
 | ||||||
| // GetSectorExpiration returns the effective expiration of the given sector.
 | // GetSectorExpiration returns the effective expiration of the given sector.
 | ||||||
| //
 | //
 | ||||||
| // If the sector isn't found or has already been terminated, this method returns
 | // If the sector does not expire early, the Early expiration field is 0.
 | ||||||
| // nil and no error. If the sector does not expire early, the Early expiration
 |  | ||||||
| // field is 0.
 |  | ||||||
| func (s *state0) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, error) { | func (s *state0) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, error) { | ||||||
| 	dls, err := s.State.LoadDeadlines(s.store) | 	dls, err := s.State.LoadDeadlines(s.store) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -171,7 +170,7 @@ func (s *state0) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, e | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	if out.Early == 0 && out.OnTime == 0 { | 	if out.Early == 0 && out.OnTime == 0 { | ||||||
| 		return nil, nil | 		return nil, xerrors.Errorf("failed to find sector %d", num) | ||||||
| 	} | 	} | ||||||
| 	return &out, nil | 	return &out, nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -22,12 +22,10 @@ func SetSupportedProofTypes(types ...abi.RegisteredSealProof) { | |||||||
| // AddSupportedProofTypes sets supported proof types, across all actor versions.
 | // AddSupportedProofTypes sets supported proof types, across all actor versions.
 | ||||||
| // This should only be used for testing.
 | // This should only be used for testing.
 | ||||||
| func AddSupportedProofTypes(types ...abi.RegisteredSealProof) { | func AddSupportedProofTypes(types ...abi.RegisteredSealProof) { | ||||||
| 	newTypes := make(map[abi.RegisteredSealProof]struct{}, len(types)) |  | ||||||
| 	for _, t := range types { | 	for _, t := range types { | ||||||
| 		newTypes[t] = struct{}{} | 		// Set for all miner versions.
 | ||||||
|  | 		miner0.SupportedProofTypes[t] = struct{}{} | ||||||
| 	} | 	} | ||||||
| 	// Set for all miner versions.
 |  | ||||||
| 	miner0.SupportedProofTypes = newTypes |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // SetPreCommitChallengeDelay sets the pre-commit challenge delay across all
 | // SetPreCommitChallengeDelay sets the pre-commit challenge delay across all
 | ||||||
|  | |||||||
							
								
								
									
										36
									
								
								chain/actors/policy/policy_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								chain/actors/policy/policy_test.go
									
									
									
									
									
										Normal 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: {}, | ||||||
|  | 		}, | ||||||
|  | 	) | ||||||
|  | } | ||||||
| @ -16,7 +16,7 @@ const ( | |||||||
| // Converts a network version into an actors adt version.
 | // Converts a network version into an actors adt version.
 | ||||||
| func VersionForNetwork(version network.Version) Version { | func VersionForNetwork(version network.Version) Version { | ||||||
| 	switch version { | 	switch version { | ||||||
| 	case network.Version0, network.Version1, network.Version2: | 	case network.Version0, network.Version1, network.Version2, network.Version3: | ||||||
| 		return Version0 | 		return Version0 | ||||||
| 	default: | 	default: | ||||||
| 		panic(fmt.Sprintf("unsupported network version %d", version)) | 		panic(fmt.Sprintf("unsupported network version %d", version)) | ||||||
|  | |||||||
| @ -1,44 +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" | 	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" | 	miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" | ||||||
| 	power0 "github.com/filecoin-project/specs-actors/actors/builtin/power" | 	power0 "github.com/filecoin-project/specs-actors/actors/builtin/power" | ||||||
| 	adt0 "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/types" | 	"github.com/filecoin-project/lotus/chain/types" | ||||||
|  | 	"github.com/filecoin-project/lotus/chain/vm" | ||||||
| 	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) | ||||||
| @ -64,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) | ||||||
| @ -94,22 +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) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	lbtree, err := sm.ParentState(lbts) | 	lbtree, err := sm.ParentState(lbts) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return xerrors.Errorf("loading state tree failed: %w", err) | 		return cid.Undef, 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 { | ||||||
| @ -121,7 +169,7 @@ 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 builtin0.AccountActorCodeID, builtin0.MultisigActorCodeID, builtin0.PaymentChannelActorCodeID: | 		case builtin0.AccountActorCodeID, builtin0.MultisigActorCodeID, builtin0.PaymentChannelActorCodeID: | ||||||
| 			sysAcc, err := isSystemAccount(addr) | 			sysAcc, err := isSystemAccount(addr) | ||||||
| @ -163,13 +211,13 @@ 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) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -177,19 +225,19 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types | |||||||
| 	var ps power0.State | 	var ps power0.State | ||||||
| 	powAct, err := tree.GetActor(builtin0.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) { | ||||||
| @ -267,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(builtin0.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, builtin0.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 | ||||||
|  | |||||||
| @ -129,33 +129,38 @@ 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 := ipldcbor.NewCborStore(sm.ChainStore().Blockstore()) | 		cst := ipldcbor.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(nil, testActor{}) | 	inv.Register(nil, testActor{}) | ||||||
|  | |||||||
| @ -40,12 +40,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(context.Context, *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 { | ||||||
| @ -122,9 +123,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, | ||||||
| @ -134,9 +134,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 | ||||||
| 	} | 	} | ||||||
| @ -148,20 +153,24 @@ 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(ctx, 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 { | ||||||
| @ -201,19 +210,32 @@ 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
 | ||||||
| 		// XXX: The state tree
 | 		// XXX: The state tree
 | ||||||
| 		err = sm.handleStateForks(ctx, vmi.StateTree(), i, ts) | 		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 | ||||||
| @ -903,7 +925,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 | ||||||
| } | } | ||||||
| @ -911,7 +933,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{} | ||||||
| 
 | 
 | ||||||
| @ -980,7 +1002,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 | ||||||
| } | } | ||||||
| @ -990,13 +1092,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) | ||||||
| @ -1008,8 +1120,10 @@ 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 | ||||||
| } | } | ||||||
| @ -1083,10 +1197,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) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -1151,6 +1271,10 @@ 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 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -95,6 +95,7 @@ func GetPowerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr addres | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	var mpow power.Claim | 	var mpow power.Claim | ||||||
|  | 	var minpow bool | ||||||
| 	if maddr != address.Undef { | 	if maddr != address.Undef { | ||||||
| 		var found bool | 		var found bool | ||||||
| 		mpow, found, err = pas.MinerPower(maddr) | 		mpow, found, err = pas.MinerPower(maddr) | ||||||
| @ -102,11 +103,11 @@ func GetPowerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr addres | |||||||
| 			// TODO: return an error when not found?
 | 			// TODO: return an error when not found?
 | ||||||
| 			return power.Claim{}, power.Claim{}, false, err | 			return power.Claim{}, power.Claim{}, false, err | ||||||
| 		} | 		} | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	minpow, err := pas.MinerNominalPowerMeetsConsensusMinimum(maddr) | 		minpow, err = pas.MinerNominalPowerMeetsConsensusMinimum(maddr) | ||||||
| 	if err != nil { | 		if err != nil { | ||||||
| 		return power.Claim{}, power.Claim{}, false, err | 			return power.Claim{}, power.Claim{}, false, err | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return mpow, tpow, minpow, nil | 	return mpow, tpow, minpow, nil | ||||||
| @ -361,6 +362,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, | ||||||
| @ -377,16 +388,6 @@ 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
 |  | ||||||
| 		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) | ||||||
|  | |||||||
| @ -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" | ||||||
| @ -465,14 +469,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 +1198,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 +1219,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 +1274,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 +1285,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 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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 | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -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 | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										37
									
								
								cli/state.go
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								cli/state.go
									
									
									
									
									
								
							| @ -17,6 +17,7 @@ import ( | |||||||
| 	"github.com/multiformats/go-multiaddr" | 	"github.com/multiformats/go-multiaddr" | ||||||
| 
 | 
 | ||||||
| 	"github.com/ipfs/go-cid" | 	"github.com/ipfs/go-cid" | ||||||
|  | 	cbor "github.com/ipfs/go-ipld-cbor" | ||||||
| 	"github.com/libp2p/go-libp2p-core/peer" | 	"github.com/libp2p/go-libp2p-core/peer" | ||||||
| 	"github.com/multiformats/go-multihash" | 	"github.com/multiformats/go-multihash" | ||||||
| 	"github.com/urfave/cli/v2" | 	"github.com/urfave/cli/v2" | ||||||
| @ -30,7 +31,9 @@ import ( | |||||||
| 	"github.com/filecoin-project/specs-actors/actors/builtin" | 	"github.com/filecoin-project/specs-actors/actors/builtin" | ||||||
| 
 | 
 | ||||||
| 	"github.com/filecoin-project/lotus/api" | 	"github.com/filecoin-project/lotus/api" | ||||||
|  | 	"github.com/filecoin-project/lotus/api/apibstore" | ||||||
| 	"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/stmgr" | 	"github.com/filecoin-project/lotus/chain/stmgr" | ||||||
| 	"github.com/filecoin-project/lotus/chain/types" | 	"github.com/filecoin-project/lotus/chain/types" | ||||||
| ) | ) | ||||||
| @ -815,6 +818,10 @@ var stateComputeStateCmd = &cli.Command{ | |||||||
| 			Name:  "html", | 			Name:  "html", | ||||||
| 			Usage: "generate html report", | 			Usage: "generate html report", | ||||||
| 		}, | 		}, | ||||||
|  | 		&cli.BoolFlag{ | ||||||
|  | 			Name:  "json", | ||||||
|  | 			Usage: "generate json output", | ||||||
|  | 		}, | ||||||
| 	}, | 	}, | ||||||
| 	Action: func(cctx *cli.Context) error { | 	Action: func(cctx *cli.Context) error { | ||||||
| 		api, closer, err := GetFullNodeAPI(cctx) | 		api, closer, err := GetFullNodeAPI(cctx) | ||||||
| @ -831,14 +838,14 @@ var stateComputeStateCmd = &cli.Command{ | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		h := abi.ChainEpoch(cctx.Uint64("vm-height")) | 		h := abi.ChainEpoch(cctx.Uint64("vm-height")) | ||||||
| 		if h == 0 { | 		if ts == nil { | ||||||
| 			if ts == nil { | 			head, err := api.ChainHead(ctx) | ||||||
| 				head, err := api.ChainHead(ctx) | 			if err != nil { | ||||||
| 				if err != nil { | 				return err | ||||||
| 					return err |  | ||||||
| 				} |  | ||||||
| 				ts = head |  | ||||||
| 			} | 			} | ||||||
|  | 			ts = head | ||||||
|  | 		} | ||||||
|  | 		if h == 0 { | ||||||
| 			h = ts.Height() | 			h = ts.Height() | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -859,14 +866,28 @@ var stateComputeStateCmd = &cli.Command{ | |||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		if cctx.Bool("json") { | ||||||
|  | 			out, err := json.Marshal(stout) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			fmt.Println(string(out)) | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		if cctx.Bool("html") { | 		if cctx.Bool("html") { | ||||||
|  | 			st, err := state.LoadStateTree(cbor.NewCborStore(apibstore.NewAPIBlockstore(api)), stout.Root) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return xerrors.Errorf("loading state tree: %w", err) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			codeCache := map[address.Address]cid.Cid{} | 			codeCache := map[address.Address]cid.Cid{} | ||||||
| 			getCode := func(addr address.Address) (cid.Cid, error) { | 			getCode := func(addr address.Address) (cid.Cid, error) { | ||||||
| 				if c, found := codeCache[addr]; found { | 				if c, found := codeCache[addr]; found { | ||||||
| 					return c, nil | 					return c, nil | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				c, err := api.StateGetActor(ctx, addr, ts.Key()) | 				c, err := st.GetActor(addr) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					return cid.Cid{}, err | 					return cid.Cid{}, err | ||||||
| 				} | 				} | ||||||
|  | |||||||
| @ -76,8 +76,6 @@ func main() { | |||||||
| 
 | 
 | ||||||
| 	log.Info("Starting lotus-bench") | 	log.Info("Starting lotus-bench") | ||||||
| 
 | 
 | ||||||
| 	policy.AddSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1) |  | ||||||
| 
 |  | ||||||
| 	app := &cli.App{ | 	app := &cli.App{ | ||||||
| 		Name:    "lotus-bench", | 		Name:    "lotus-bench", | ||||||
| 		Usage:   "Benchmark performance of lotus on your hardware", | 		Usage:   "Benchmark performance of lotus on your hardware", | ||||||
| @ -147,6 +145,8 @@ var sealBenchCmd = &cli.Command{ | |||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
|  | 		policy.AddSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1) | ||||||
|  | 
 | ||||||
| 		if c.Bool("no-gpu") { | 		if c.Bool("no-gpu") { | ||||||
| 			err := os.Setenv("BELLMAN_NO_GPU", "1") | 			err := os.Setenv("BELLMAN_NO_GPU", "1") | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
|  | |||||||
| @ -3,9 +3,16 @@ package main | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"strconv" | ||||||
|  | 
 | ||||||
|  | 	"github.com/docker/go-units" | ||||||
|  | 	lotusbuiltin "github.com/filecoin-project/lotus/chain/actors/builtin" | ||||||
|  | 	"github.com/filecoin-project/lotus/chain/actors/builtin/power" | ||||||
|  | 	"github.com/filecoin-project/lotus/chain/actors/builtin/reward" | ||||||
| 
 | 
 | ||||||
| 	"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" | ||||||
| 	"github.com/urfave/cli/v2" | 	"github.com/urfave/cli/v2" | ||||||
| 	"golang.org/x/xerrors" | 	"golang.org/x/xerrors" | ||||||
| 
 | 
 | ||||||
| @ -44,6 +51,7 @@ var auditsCmd = &cli.Command{ | |||||||
| 	Subcommands: []*cli.Command{ | 	Subcommands: []*cli.Command{ | ||||||
| 		chainBalanceCmd, | 		chainBalanceCmd, | ||||||
| 		chainBalanceStateCmd, | 		chainBalanceStateCmd, | ||||||
|  | 		chainPledgeCmd, | ||||||
| 	}, | 	}, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -248,3 +256,133 @@ var chainBalanceStateCmd = &cli.Command{ | |||||||
| 		return nil | 		return nil | ||||||
| 	}, | 	}, | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | var chainPledgeCmd = &cli.Command{ | ||||||
|  | 	Name:        "stateroot-pledge", | ||||||
|  | 	Description: "Calculate sector pledge numbers", | ||||||
|  | 	Flags: []cli.Flag{ | ||||||
|  | 		&cli.StringFlag{ | ||||||
|  | 			Name:  "repo", | ||||||
|  | 			Value: "~/.lotus", | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 	ArgsUsage: "[stateroot epoch]", | ||||||
|  | 	Action: func(cctx *cli.Context) error { | ||||||
|  | 		logging.SetLogLevel("badger", "ERROR") | ||||||
|  | 		ctx := context.TODO() | ||||||
|  | 
 | ||||||
|  | 		if !cctx.Args().Present() { | ||||||
|  | 			return fmt.Errorf("must pass state root") | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		sroot, err := cid.Decode(cctx.Args().First()) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("failed to parse input: %w", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		epoch, err := strconv.ParseInt(cctx.Args().Get(1), 10, 64) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return xerrors.Errorf("parsing epoch arg: %w", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		fsrepo, err := repo.NewFS(cctx.String("repo")) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		lkrepo, err := fsrepo.Lock(repo.FullNode) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		defer lkrepo.Close() //nolint:errcheck
 | ||||||
|  | 
 | ||||||
|  | 		ds, err := lkrepo.Datastore("/chain") | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		mds, err := lkrepo.Datastore("/metadata") | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		bs := blockstore.NewBlockstore(ds) | ||||||
|  | 
 | ||||||
|  | 		cs := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier)) | ||||||
|  | 
 | ||||||
|  | 		cst := cbor.NewCborStore(bs) | ||||||
|  | 		store := adt.WrapStore(ctx, cst) | ||||||
|  | 
 | ||||||
|  | 		sm := stmgr.NewStateManager(cs) | ||||||
|  | 
 | ||||||
|  | 		state, err := state.LoadStateTree(cst, sroot) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		var ( | ||||||
|  | 			powerSmoothed    lotusbuiltin.FilterEstimate | ||||||
|  | 			pledgeCollateral abi.TokenAmount | ||||||
|  | 		) | ||||||
|  | 		if act, err := state.GetActor(power.Address); err != nil { | ||||||
|  | 			return xerrors.Errorf("loading miner actor: %w", err) | ||||||
|  | 		} else if s, err := power.Load(store, act); err != nil { | ||||||
|  | 			return xerrors.Errorf("loading power actor state: %w", err) | ||||||
|  | 		} else if p, err := s.TotalPowerSmoothed(); err != nil { | ||||||
|  | 			return xerrors.Errorf("failed to determine total power: %w", err) | ||||||
|  | 		} else if c, err := s.TotalLocked(); err != nil { | ||||||
|  | 			return xerrors.Errorf("failed to determine pledge collateral: %w", err) | ||||||
|  | 		} else { | ||||||
|  | 			powerSmoothed = p | ||||||
|  | 			pledgeCollateral = c | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		circ, err := sm.GetCirculatingSupplyDetailed(ctx, abi.ChainEpoch(epoch), state) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		fmt.Println("(real) circulating supply: ", types.FIL(circ.FilCirculating)) | ||||||
|  | 		if circ.FilCirculating.LessThan(big.Zero()) { | ||||||
|  | 			circ.FilCirculating = big.Zero() | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		rewardActor, err := state.GetActor(reward.Address) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return xerrors.Errorf("loading miner actor: %w", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		rewardState, err := reward.Load(store, rewardActor) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return xerrors.Errorf("loading reward actor state: %w", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		fmt.Println("FilVested", types.FIL(circ.FilVested)) | ||||||
|  | 		fmt.Println("FilMined", types.FIL(circ.FilMined)) | ||||||
|  | 		fmt.Println("FilBurnt", types.FIL(circ.FilBurnt)) | ||||||
|  | 		fmt.Println("FilLocked", types.FIL(circ.FilLocked)) | ||||||
|  | 		fmt.Println("FilCirculating", types.FIL(circ.FilCirculating)) | ||||||
|  | 
 | ||||||
|  | 		for _, sectorWeight := range []abi.StoragePower{ | ||||||
|  | 			types.NewInt(32 << 30), | ||||||
|  | 			types.NewInt(64 << 30), | ||||||
|  | 			types.NewInt(32 << 30 * 10), | ||||||
|  | 			types.NewInt(64 << 30 * 10), | ||||||
|  | 		} { | ||||||
|  | 			initialPledge, err := rewardState.InitialPledgeForPower( | ||||||
|  | 				sectorWeight, | ||||||
|  | 				pledgeCollateral, | ||||||
|  | 				&powerSmoothed, | ||||||
|  | 				circ.FilCirculating, | ||||||
|  | 			) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return xerrors.Errorf("calculating initial pledge: %w", err) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			fmt.Println("IP ", units.HumanSize(float64(sectorWeight.Uint64())), types.FIL(initialPledge)) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return nil | ||||||
|  | 	}, | ||||||
|  | } | ||||||
|  | |||||||
| @ -3,11 +3,14 @@ | |||||||
| package main | package main | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"bufio" | ||||||
| 	"context" | 	"context" | ||||||
| 	"encoding/hex" | 	"encoding/hex" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"io" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
|  | 	"net/http" | ||||||
| 	"os" | 	"os" | ||||||
| 	"runtime/pprof" | 	"runtime/pprof" | ||||||
| 	"strings" | 	"strings" | ||||||
| @ -23,6 +26,7 @@ import ( | |||||||
| 	"go.opencensus.io/stats/view" | 	"go.opencensus.io/stats/view" | ||||||
| 	"go.opencensus.io/tag" | 	"go.opencensus.io/tag" | ||||||
| 	"golang.org/x/xerrors" | 	"golang.org/x/xerrors" | ||||||
|  | 	"gopkg.in/cheggaaa/pb.v1" | ||||||
| 
 | 
 | ||||||
| 	"github.com/filecoin-project/lotus/api" | 	"github.com/filecoin-project/lotus/api" | ||||||
| 	"github.com/filecoin-project/lotus/build" | 	"github.com/filecoin-project/lotus/build" | ||||||
| @ -100,11 +104,11 @@ var DaemonCmd = &cli.Command{ | |||||||
| 		}, | 		}, | ||||||
| 		&cli.StringFlag{ | 		&cli.StringFlag{ | ||||||
| 			Name:  "import-chain", | 			Name:  "import-chain", | ||||||
| 			Usage: "on first run, load chain from given file and validate", | 			Usage: "on first run, load chain from given file or url and validate", | ||||||
| 		}, | 		}, | ||||||
| 		&cli.StringFlag{ | 		&cli.StringFlag{ | ||||||
| 			Name:  "import-snapshot", | 			Name:  "import-snapshot", | ||||||
| 			Usage: "import chain state from a given chain export file", | 			Usage: "import chain state from a given chain export file or url", | ||||||
| 		}, | 		}, | ||||||
| 		&cli.BoolFlag{ | 		&cli.BoolFlag{ | ||||||
| 			Name:  "halt-after-import", | 			Name:  "halt-after-import", | ||||||
| @ -206,11 +210,6 @@ var DaemonCmd = &cli.Command{ | |||||||
| 				issnapshot = true | 				issnapshot = true | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			chainfile, err := homedir.Expand(chainfile) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return err |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if err := ImportChain(r, chainfile, issnapshot); err != nil { | 			if err := ImportChain(r, chainfile, issnapshot); err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| @ -326,12 +325,42 @@ func importKey(ctx context.Context, api api.FullNode, f string) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func ImportChain(r repo.Repo, fname string, snapshot bool) error { | func ImportChain(r repo.Repo, fname string, snapshot bool) (err error) { | ||||||
| 	fi, err := os.Open(fname) | 	var rd io.Reader | ||||||
| 	if err != nil { | 	var l int64 | ||||||
| 		return err | 	if strings.HasPrefix(fname, "http://") || strings.HasPrefix(fname, "https://") { | ||||||
|  | 		resp, err := http.Get(fname) //nolint:gosec
 | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		defer resp.Body.Close() //nolint:errcheck
 | ||||||
|  | 
 | ||||||
|  | 		if resp.StatusCode != http.StatusOK { | ||||||
|  | 			return xerrors.Errorf("non-200 response: %d", resp.StatusCode) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		rd = resp.Body | ||||||
|  | 		l = resp.ContentLength | ||||||
|  | 	} else { | ||||||
|  | 		fname, err = homedir.Expand(fname) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		fi, err := os.Open(fname) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		defer fi.Close() //nolint:errcheck
 | ||||||
|  | 
 | ||||||
|  | 		st, err := os.Stat(fname) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		rd = fi | ||||||
|  | 		l = st.Size() | ||||||
| 	} | 	} | ||||||
| 	defer fi.Close() //nolint:errcheck
 |  | ||||||
| 
 | 
 | ||||||
| 	lr, err := r.Lock(repo.FullNode) | 	lr, err := r.Lock(repo.FullNode) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -353,8 +382,21 @@ func ImportChain(r repo.Repo, fname string, snapshot bool) error { | |||||||
| 
 | 
 | ||||||
| 	cst := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier)) | 	cst := store.NewChainStore(bs, mds, vm.Syscalls(ffiwrapper.ProofVerifier)) | ||||||
| 
 | 
 | ||||||
| 	log.Info("importing chain from file...") | 	log.Infof("importing chain from %s...", fname) | ||||||
| 	ts, err := cst.Import(fi) | 
 | ||||||
|  | 	bufr := bufio.NewReaderSize(rd, 1<<20) | ||||||
|  | 
 | ||||||
|  | 	bar := pb.New64(l) | ||||||
|  | 	br := bar.NewProxyReader(bufr) | ||||||
|  | 	bar.ShowTimeLeft = true | ||||||
|  | 	bar.ShowPercent = true | ||||||
|  | 	bar.ShowSpeed = true | ||||||
|  | 	bar.Units = pb.U_BYTES | ||||||
|  | 
 | ||||||
|  | 	bar.Start() | ||||||
|  | 	ts, err := cst.Import(br) | ||||||
|  | 	bar.Finish() | ||||||
|  | 
 | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return xerrors.Errorf("importing chain failed: %w", err) | 		return xerrors.Errorf("importing chain failed: %w", err) | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -3825,7 +3825,7 @@ Inputs: | |||||||
| ] | ] | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Response: `2` | Response: `3` | ||||||
| 
 | 
 | ||||||
| ### StateReadState | ### StateReadState | ||||||
| StateReadState returns the indicated actor's state. | StateReadState returns the indicated actor's state. | ||||||
|  | |||||||
							
								
								
									
										9
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								go.mod
									
									
									
									
									
								
							| @ -21,13 +21,13 @@ require ( | |||||||
| 	github.com/elastic/go-sysinfo v1.3.0 | 	github.com/elastic/go-sysinfo v1.3.0 | ||||||
| 	github.com/fatih/color v1.8.0 | 	github.com/fatih/color v1.8.0 | ||||||
| 	github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200716204036-cddc56607e1d | 	github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200716204036-cddc56607e1d | ||||||
| 	github.com/filecoin-project/go-address v0.0.3 | 	github.com/filecoin-project/go-address v0.0.4 | ||||||
| 	github.com/filecoin-project/go-bitfield v0.2.0 | 	github.com/filecoin-project/go-bitfield v0.2.0 | ||||||
| 	github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 | 	github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 | ||||||
| 	github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 | 	github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 | ||||||
| 	github.com/filecoin-project/go-data-transfer v0.6.5 | 	github.com/filecoin-project/go-data-transfer v0.6.6 | ||||||
| 	github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f | 	github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f | ||||||
| 	github.com/filecoin-project/go-fil-markets v0.6.2 | 	github.com/filecoin-project/go-fil-markets v0.6.3 | ||||||
| 	github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52 | 	github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52 | ||||||
| 	github.com/filecoin-project/go-multistore v0.0.3 | 	github.com/filecoin-project/go-multistore v0.0.3 | ||||||
| 	github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 | 	github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 | ||||||
| @ -61,7 +61,7 @@ require ( | |||||||
| 	github.com/ipfs/go-ds-measure v0.1.0 | 	github.com/ipfs/go-ds-measure v0.1.0 | ||||||
| 	github.com/ipfs/go-filestore v1.0.0 | 	github.com/ipfs/go-filestore v1.0.0 | ||||||
| 	github.com/ipfs/go-fs-lock v0.0.6 | 	github.com/ipfs/go-fs-lock v0.0.6 | ||||||
| 	github.com/ipfs/go-graphsync v0.2.0 | 	github.com/ipfs/go-graphsync v0.2.1 | ||||||
| 	github.com/ipfs/go-ipfs-blockstore v1.0.1 | 	github.com/ipfs/go-ipfs-blockstore v1.0.1 | ||||||
| 	github.com/ipfs/go-ipfs-chunker v0.0.5 | 	github.com/ipfs/go-ipfs-chunker v0.0.5 | ||||||
| 	github.com/ipfs/go-ipfs-ds-help v1.0.0 | 	github.com/ipfs/go-ipfs-ds-help v1.0.0 | ||||||
| @ -126,6 +126,7 @@ require ( | |||||||
| 	golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 | 	golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 | ||||||
| 	golang.org/x/time v0.0.0-20191024005414-555d28b269f0 | 	golang.org/x/time v0.0.0-20191024005414-555d28b269f0 | ||||||
| 	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 | 	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 | ||||||
|  | 	gopkg.in/cheggaaa/pb.v1 v1.0.28 | ||||||
| 	gotest.tools v2.2.0+incompatible | 	gotest.tools v2.2.0+incompatible | ||||||
| 	launchpad.net/gocheck v0.0.0-20140225173054-000000000087 // indirect | 	launchpad.net/gocheck v0.0.0-20140225173054-000000000087 // indirect | ||||||
| ) | ) | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								go.sum
									
									
									
									
									
								
							| @ -214,6 +214,8 @@ github.com/fatih/color v1.8.0/go.mod h1:3l45GVGkyrnYNl9HoIjnp2NnNWvh6hLAqD8yTfGj | |||||||
| github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= | github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= | ||||||
| github.com/filecoin-project/go-address v0.0.3 h1:eVfbdjEbpbzIrbiSa+PiGUY+oDK9HnUn+M1R/ggoHf8= | github.com/filecoin-project/go-address v0.0.3 h1:eVfbdjEbpbzIrbiSa+PiGUY+oDK9HnUn+M1R/ggoHf8= | ||||||
| github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= | github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= | ||||||
|  | github.com/filecoin-project/go-address v0.0.4 h1:gSNMv0qWwH16fGQs7ycOUrDjY6YCSsgLUl0I0KLjo8w= | ||||||
|  | github.com/filecoin-project/go-address v0.0.4/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= | ||||||
| github.com/filecoin-project/go-amt-ipld/v2 v2.1.0 h1:t6qDiuGYYngDqaLc2ZUvdtAg4UNxPeOYaXhBWSNsVaM= | github.com/filecoin-project/go-amt-ipld/v2 v2.1.0 h1:t6qDiuGYYngDqaLc2ZUvdtAg4UNxPeOYaXhBWSNsVaM= | ||||||
| github.com/filecoin-project/go-amt-ipld/v2 v2.1.0/go.mod h1:nfFPoGyX0CU9SkXX8EoCcSuHN1XcbN0c6KBh7yvP5fs= | github.com/filecoin-project/go-amt-ipld/v2 v2.1.0/go.mod h1:nfFPoGyX0CU9SkXX8EoCcSuHN1XcbN0c6KBh7yvP5fs= | ||||||
| github.com/filecoin-project/go-bitfield v0.2.0 h1:gCtLcjskIPtdg4NfN7gQZSQF9yrBQ7mkT0qCJxzGI2Q= | github.com/filecoin-project/go-bitfield v0.2.0 h1:gCtLcjskIPtdg4NfN7gQZSQF9yrBQ7mkT0qCJxzGI2Q= | ||||||
| @ -222,12 +224,12 @@ github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:a | |||||||
| github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg= | github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg= | ||||||
| github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus= | github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus= | ||||||
| github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= | github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= | ||||||
| github.com/filecoin-project/go-data-transfer v0.6.5 h1:oP20la8Z0CLrw0uqvt6xVgw6rOevZeGJ9GNQeC0OCSU= | github.com/filecoin-project/go-data-transfer v0.6.6 h1:2TccLSxPYJENcYRdov2WvpTvQ1qUMrPkWe8sBrfj36g= | ||||||
| github.com/filecoin-project/go-data-transfer v0.6.5/go.mod h1:I9Ylb/UiZyqnI41wUoCXq/le0nDLhlwpFQCtNPxEPOA= | github.com/filecoin-project/go-data-transfer v0.6.6/go.mod h1:C++k1U6+jMQODOaen5OPDo9XQbth9Yq3ie94vNjBJbk= | ||||||
| github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s= | github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s= | ||||||
| github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= | github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= | ||||||
| github.com/filecoin-project/go-fil-markets v0.6.2 h1:9Z57KeaQSa1liCmT1pH6SIjrn9mGTDFJXmR2WQVuaiY= | github.com/filecoin-project/go-fil-markets v0.6.3 h1:3kTxfquGvk3zQY+hJH1kEA28tRQ47phqSRqOI4+YcQM= | ||||||
| github.com/filecoin-project/go-fil-markets v0.6.2/go.mod h1:wtN4Hc/1hoVCpWhSWYxwUxH3PQtjSkWWuC1nQjiIWog= | github.com/filecoin-project/go-fil-markets v0.6.3/go.mod h1:Ug1yhGhzTYC6qrpKsR2QpU8QRCeBpwkTA9RICVKuOMM= | ||||||
| github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= | github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= | ||||||
| github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= | github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= | ||||||
| github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= | github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= | ||||||
| @ -509,8 +511,8 @@ github.com/ipfs/go-filestore v1.0.0/go.mod h1:/XOCuNtIe2f1YPbiXdYvD0BKLA0JR1MgPi | |||||||
| github.com/ipfs/go-fs-lock v0.0.6 h1:sn3TWwNVQqSeNjlWy6zQ1uUGAZrV3hPOyEA6y1/N2a0= | github.com/ipfs/go-fs-lock v0.0.6 h1:sn3TWwNVQqSeNjlWy6zQ1uUGAZrV3hPOyEA6y1/N2a0= | ||||||
| github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM= | github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM= | ||||||
| github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= | github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= | ||||||
| github.com/ipfs/go-graphsync v0.2.0 h1:x94MvHLNuRwBlZzVal7tR1RYK7T7H6bqQLPopxDbIF0= | github.com/ipfs/go-graphsync v0.2.1 h1:MdehhqBSuTI2LARfKLkpYnt0mUrqHs/mtuDnESXHBfU= | ||||||
| github.com/ipfs/go-graphsync v0.2.0/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10= | github.com/ipfs/go-graphsync v0.2.1/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10= | ||||||
| github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk= | github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk= | ||||||
| github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= | github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= | ||||||
| github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= | github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= | ||||||
|  | |||||||
| @ -211,6 +211,8 @@ minerLoop: | |||||||
| 			base = prebase | 			base = prebase | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		base.NullRounds += injectNulls // testing
 | ||||||
|  | 
 | ||||||
| 		if base.TipSet.Equals(lastBase.TipSet) && lastBase.NullRounds == base.NullRounds { | 		if base.TipSet.Equals(lastBase.TipSet) && lastBase.NullRounds == base.NullRounds { | ||||||
| 			log.Warnf("BestMiningCandidate from the previous round: %s (nulls:%d)", lastBase.TipSet.Cids(), lastBase.NullRounds) | 			log.Warnf("BestMiningCandidate from the previous round: %s (nulls:%d)", lastBase.TipSet.Cids(), lastBase.NullRounds) | ||||||
| 			if !m.niceSleep(time.Duration(build.BlockDelaySecs) * time.Second) { | 			if !m.niceSleep(time.Duration(build.BlockDelaySecs) * time.Second) { | ||||||
| @ -219,8 +221,6 @@ minerLoop: | |||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		base.NullRounds += injectNulls // testing
 |  | ||||||
| 
 |  | ||||||
| 		b, err := m.mineOne(ctx, base) | 		b, err := m.mineOne(ctx, base) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Errorf("mining block failed: %+v", err) | 			log.Errorf("mining block failed: %+v", err) | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ import ( | |||||||
| 
 | 
 | ||||||
| 	"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" | 	"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/filecoin-project/lotus/build" | ||||||
| 	"github.com/filecoin-project/lotus/chain" | 	"github.com/filecoin-project/lotus/chain" | ||||||
| 	"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" | ||||||
| @ -157,6 +158,10 @@ func SetGenesis(cs *store.ChainStore, g Genesis) (dtypes.AfterGenesisSet, error) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func NetworkName(mctx helpers.MetricsCtx, lc fx.Lifecycle, cs *store.ChainStore, _ dtypes.AfterGenesisSet) (dtypes.NetworkName, error) { | func NetworkName(mctx helpers.MetricsCtx, lc fx.Lifecycle, cs *store.ChainStore, _ dtypes.AfterGenesisSet) (dtypes.NetworkName, error) { | ||||||
|  | 	if !build.Devnet { | ||||||
|  | 		return "testnetnet", nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	ctx := helpers.LifecycleCtx(mctx, lc) | 	ctx := helpers.LifecycleCtx(mctx, lc) | ||||||
| 
 | 
 | ||||||
| 	netName, err := stmgr.GetNetworkName(ctx, stmgr.NewStateManager(cs), cs.GetHeaviestTipSet().ParentState()) | 	netName, err := stmgr.GetNetworkName(ctx, stmgr.NewStateManager(cs), cs.GetHeaviestTipSet().ParentState()) | ||||||
|  | |||||||
| @ -109,6 +109,9 @@ func MinerID(ma dtypes.MinerAddress) (dtypes.MinerID, error) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func StorageNetworkName(ctx helpers.MetricsCtx, a lapi.FullNode) (dtypes.NetworkName, error) { | func StorageNetworkName(ctx helpers.MetricsCtx, a lapi.FullNode) (dtypes.NetworkName, error) { | ||||||
|  | 	if !build.Devnet { | ||||||
|  | 		return "testnetnet", nil | ||||||
|  | 	} | ||||||
| 	return a.StateNetworkName(ctx) | 	return a.StateNetworkName(ctx) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -371,6 +371,10 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty | |||||||
| 			return j | 			return j | ||||||
| 		}) | 		}) | ||||||
| 
 | 
 | ||||||
|  | 		if ts.Height() > build.UpgradeIgnitionHeight { | ||||||
|  | 			return // FORK: declaring faults after ignition upgrade makes no sense
 | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		if faults, sigmsg, err = s.checkNextFaults(context.TODO(), declDeadline, partitions); err != nil { | 		if faults, sigmsg, err = s.checkNextFaults(context.TODO(), declDeadline, partitions); err != nil { | ||||||
| 			// TODO: This is also potentially really bad, but we try to post anyways
 | 			// TODO: This is also potentially really bad, but we try to post anyways
 | ||||||
| 			log.Errorf("checking sector faults: %v", err) | 			log.Errorf("checking sector faults: %v", err) | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/filecoin-project/go-address" | ||||||
| 	"github.com/filecoin-project/lotus/api" | 	"github.com/filecoin-project/lotus/api" | ||||||
| 	"github.com/filecoin-project/lotus/build" | 	"github.com/filecoin-project/lotus/build" | ||||||
| 	"github.com/filecoin-project/lotus/chain/actors/builtin/reward" | 	"github.com/filecoin-project/lotus/chain/actors/builtin/reward" | ||||||
| @ -252,6 +253,14 @@ func RecordTipsetStatePoints(ctx context.Context, api api.FullNode, pl *PointLis | |||||||
| 	p := NewPoint("network.balance", netBalFilFloat) | 	p := NewPoint("network.balance", netBalFilFloat) | ||||||
| 	pl.AddPoint(p) | 	pl.AddPoint(p) | ||||||
| 
 | 
 | ||||||
|  | 	totalPower, err := api.StateMinerPower(ctx, address.Address{}, tipset.Key()) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	p = NewPoint("chain.power", totalPower.TotalPower.QualityAdjPower.Int64()) | ||||||
|  | 	pl.AddPoint(p) | ||||||
|  | 
 | ||||||
| 	miners, err := api.StateListMiners(ctx, tipset.Key()) | 	miners, err := api.StateListMiners(ctx, tipset.Key()) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user