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
|
||||
|
||||
# 0.8.0 / 2020-09-26
|
||||
|
||||
This consensus-breaking release of Lotus introduces an upgrade to the network. The changes that break consensus are:
|
||||
|
||||
- Upgrading to specs-actors v0.9.11, which reduces WindowPoSt faults per [FIP 0002](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0002.md) to reduce cost for honest miners with occasional faults (see https://github.com/filecoin-project/specs-actors/pull/1181)
|
||||
- Revisions to some cryptoeconomics and network params
|
||||
|
||||
This release also updates go-fil-markets to fix an incompatibility issue between v0.7.2 and earlier versions.
|
||||
|
||||
## Changes
|
||||
|
||||
#### Dependencies
|
||||
|
||||
- Update spec actors to 0.9.11 (https://github.com/filecoin-project/lotus/pull/4039)
|
||||
- Update markets to 0.6.3 (https://github.com/filecoin-project/lotus/pull/4013)
|
||||
|
||||
#### Core Lotus
|
||||
|
||||
- Network upgrade (https://github.com/filecoin-project/lotus/pull/4039)
|
||||
- Fix AddSupportedProofTypes (https://github.com/filecoin-project/lotus/pull/4033)
|
||||
- Return an error when we fail to find a sector when checking sector expiration (https://github.com/filecoin-project/lotus/pull/4026)
|
||||
- Batch blockstore copies after block validation (https://github.com/filecoin-project/lotus/pull/3980)
|
||||
- Remove a misleading miner actor abstraction (https://github.com/filecoin-project/lotus/pull/3977)
|
||||
- Fix out-of-bounds when loading all sector infos (https://github.com/filecoin-project/lotus/pull/3976)
|
||||
- Fix break condition in the miner (https://github.com/filecoin-project/lotus/pull/3953)
|
||||
|
||||
#### UX
|
||||
|
||||
- Correct helptext around miners setting ask (https://github.com/filecoin-project/lotus/pull/4009)
|
||||
- Make sync wait nicer (https://github.com/filecoin-project/lotus/pull/3991)
|
||||
|
||||
#### Tooling and validation
|
||||
|
||||
- Small adjustments following network upgradability changes (https://github.com/filecoin-project/lotus/pull/3996)
|
||||
- Add some more big pictures stats to stateroot stat (https://github.com/filecoin-project/lotus/pull/3995)
|
||||
- Add some actors policy setters for testing (https://github.com/filecoin-project/lotus/pull/3975)
|
||||
|
||||
## Contributors
|
||||
|
||||
The following contributors had 5 or more commits go into this release.
|
||||
We are grateful for every contribution!
|
||||
|
||||
| Contributor | Commits | Lines ± |
|
||||
|--------------------|---------|---------------|
|
||||
| arajasek | 66 | +3140/-1261 |
|
||||
| Stebalien | 64 | +3797/-3434 |
|
||||
| magik6k | 48 | +1892/-976 |
|
||||
| raulk | 40 | +2412/-1549 |
|
||||
| vyzo | 22 | +287/-196 |
|
||||
| alanshaw | 15 | +761/-146 |
|
||||
| whyrusleeping | 15 | +736/-52 |
|
||||
| hannahhoward | 14 | +1237/837- |
|
||||
| anton | 6 | +32/-8 |
|
||||
| travisperson | 5 | +502/-6 |
|
||||
| Frank | 5 | +78/-39 |
|
||||
| Jennifer | 5 | +148/-41 |
|
||||
|
||||
# 0.7.2 / 2020-09-23
|
||||
|
||||
This optional release of Lotus introduces a major refactor around how a Lotus node interacts with code from the specs-actors repo. We now use interfaces to read the state of actors, which is required to be able to reason about different versions of actors code at the same time.
|
||||
|
@ -94,6 +94,22 @@ func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
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")
|
||||
atomic.AddInt64(&mine, -1)
|
||||
<-done
|
||||
|
@ -4,3 +4,9 @@
|
||||
/dns4/bootstrap-4.testnet.fildev.network/tcp/1347/p2p/12D3KooWPkL9LrKRQgHtq7kn9ecNhGU9QaziG8R5tX8v9v7t3h34
|
||||
/dns4/bootstrap-3.testnet.fildev.network/tcp/1347/p2p/12D3KooWKYSsbpgZ3HAjax5M1BXCwXLa6gVkUARciz7uN3FNtr7T
|
||||
/dns4/bootstrap-5.testnet.fildev.network/tcp/1347/p2p/12D3KooWQYzqnLASJAabyMpPb1GcWZvNSe7JDcRuhdRqonFoiK9W
|
||||
/dns4/lotus-bootstrap.forceup.cn/tcp/41778/p2p/12D3KooWFQsv3nRMUevZNWWsY1Wu6NUzUbawnWU5NcRhgKuJA37C
|
||||
/dns4/bootstrap-0.starpool.in/tcp/12757/p2p/12D3KooWGHpBMeZbestVEWkfdnC9u7p6uFHXL1n7m1ZBqsEmiUzz
|
||||
/dns4/bootstrap-1.starpool.in/tcp/12757/p2p/12D3KooWQZrGH1PxSNZPum99M1zNvjNFM33d1AAu5DcvdHptuU7u
|
||||
/dns4/node.glif.io/tcp/1235/p2p/12D3KooWBF8cpp65hp2u9LK5mh19x67ftAam84z9LsfaquTDSBpt
|
||||
/dns4/bootstrap-0.ipfsmain.cn/tcp/34721/p2p/12D3KooWQnwEGNqcM2nAcPtRR9rAX8Hrg4k9kJLCHoTR5chJfz6d
|
||||
/dns4/bootstrap-1.ipfsmain.cn/tcp/34723/p2p/12D3KooWMKxMkD5DMpSWsW7dBddKxKT7L2GgbNuckz9otxvkvByP
|
||||
|
@ -12,6 +12,8 @@ const UpgradeBreezeHeight = -1
|
||||
const BreezeGasTampingDuration = 0
|
||||
|
||||
const UpgradeSmokeHeight = -1
|
||||
const UpgradeIgnitionHeight = -2
|
||||
const UpgradeLiftoffHeight = -3
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
|
@ -3,6 +3,8 @@ package build
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/protocol"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
@ -44,3 +46,7 @@ func UseNewestNetwork() bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func SetAddressNetwork(n address.Network) {
|
||||
address.CurrentNetwork = n
|
||||
}
|
||||
|
@ -4,6 +4,9 @@ package build
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"os"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
@ -22,8 +25,8 @@ const UnixfsLinksPerLevel = 1024
|
||||
// Consensus / Network
|
||||
|
||||
const AllowableClockDriftSecs = uint64(1)
|
||||
const NewestNetworkVersion = network.Version2
|
||||
const ActorUpgradeNetworkVersion = network.Version3
|
||||
const NewestNetworkVersion = network.Version3
|
||||
const ActorUpgradeNetworkVersion = network.Version4
|
||||
|
||||
// Epochs
|
||||
const ForkLengthThreshold = Finality
|
||||
@ -60,9 +63,16 @@ const TicketRandomnessLookback = abi.ChainEpoch(1)
|
||||
|
||||
const WinningPoStSectorSetLookback = abi.ChainEpoch(10)
|
||||
|
||||
// /////
|
||||
// Address
|
||||
|
||||
const AddressMainnetEnvVar = "_mainnet_"
|
||||
|
||||
// /////
|
||||
// Devnet settings
|
||||
|
||||
var Devnet = true
|
||||
|
||||
const FilBase = uint64(2_000_000_000)
|
||||
const FilAllocStorageMining = uint64(1_100_000_000)
|
||||
|
||||
@ -75,6 +85,10 @@ var InitialRewardBalance *big.Int
|
||||
func init() {
|
||||
InitialRewardBalance = big.NewInt(int64(FilAllocStorageMining))
|
||||
InitialRewardBalance = InitialRewardBalance.Mul(InitialRewardBalance, big.NewInt(int64(FilecoinPrecision)))
|
||||
|
||||
if os.Getenv("LOTUS_ADDRESS_TYPE") == AddressMainnetEnvVar {
|
||||
SetAddressNetwork(address.Mainnet)
|
||||
}
|
||||
}
|
||||
|
||||
// Sync
|
||||
|
@ -74,7 +74,9 @@ var (
|
||||
UpgradeBreezeHeight abi.ChainEpoch = -1
|
||||
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{
|
||||
0: DrandMainnet,
|
||||
@ -82,4 +84,6 @@ var (
|
||||
|
||||
NewestNetworkVersion = network.Version2
|
||||
ActorUpgradeNetworkVersion = network.Version3
|
||||
|
||||
Devnet = true
|
||||
)
|
||||
|
@ -21,12 +21,20 @@ const BreezeGasTampingDuration = 120
|
||||
|
||||
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() {
|
||||
policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40))
|
||||
policy.SetSupportedProofTypes(
|
||||
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg64GiBV1,
|
||||
)
|
||||
Devnet = false
|
||||
}
|
||||
|
||||
const BlockDelaySecs = uint64(builtin0.EpochDurationSeconds)
|
||||
|
@ -29,7 +29,7 @@ func buildType() string {
|
||||
}
|
||||
|
||||
// BuildVersion is the local build version, set by build system
|
||||
const BuildVersion = "0.7.2"
|
||||
const BuildVersion = "0.8.0"
|
||||
|
||||
func UserVersion() string {
|
||||
return BuildVersion + buildType() + CurrentCommit
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
|
||||
@ -106,9 +107,7 @@ func (s *state0) NumLiveSectors() (uint64, error) {
|
||||
|
||||
// GetSectorExpiration returns the effective expiration of the given sector.
|
||||
//
|
||||
// If the sector isn't found or has already been terminated, this method returns
|
||||
// nil and no error. If the sector does not expire early, the Early expiration
|
||||
// field is 0.
|
||||
// If the sector does not expire early, the Early expiration field is 0.
|
||||
func (s *state0) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, error) {
|
||||
dls, err := s.State.LoadDeadlines(s.store)
|
||||
if err != nil {
|
||||
@ -171,7 +170,7 @@ func (s *state0) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, e
|
||||
return nil, err
|
||||
}
|
||||
if out.Early == 0 && out.OnTime == 0 {
|
||||
return nil, nil
|
||||
return nil, xerrors.Errorf("failed to find sector %d", num)
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
@ -22,12 +22,10 @@ func SetSupportedProofTypes(types ...abi.RegisteredSealProof) {
|
||||
// AddSupportedProofTypes sets supported proof types, across all actor versions.
|
||||
// This should only be used for testing.
|
||||
func AddSupportedProofTypes(types ...abi.RegisteredSealProof) {
|
||||
newTypes := make(map[abi.RegisteredSealProof]struct{}, len(types))
|
||||
for _, t := range types {
|
||||
newTypes[t] = struct{}{}
|
||||
// Set for all miner versions.
|
||||
miner0.SupportedProofTypes[t] = struct{}{}
|
||||
}
|
||||
// Set for all miner versions.
|
||||
miner0.SupportedProofTypes = newTypes
|
||||
}
|
||||
|
||||
// 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.
|
||||
func VersionForNetwork(version network.Version) Version {
|
||||
switch version {
|
||||
case network.Version0, network.Version1, network.Version2:
|
||||
case network.Version0, network.Version1, network.Version2, network.Version3:
|
||||
return Version0
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported network version %d", version))
|
||||
|
@ -1,44 +1,59 @@
|
||||
package stmgr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"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-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
|
||||
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
var ForksAtHeight = map[abi.ChainEpoch]func(context.Context, *StateManager, types.StateTree, *types.TipSet) error{
|
||||
build.UpgradeBreezeHeight: UpgradeFaucetBurnRecovery,
|
||||
var ForksAtHeight = map[abi.ChainEpoch]func(context.Context, *StateManager, ExecCallback, cid.Cid, *types.TipSet) (cid.Cid, error){
|
||||
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]
|
||||
if ok {
|
||||
err := f(ctx, sm, st, ts)
|
||||
retCid, err = f(ctx, sm, cb, root, ts)
|
||||
if err != nil {
|
||||
return err
|
||||
return cid.Undef, err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return retCid, nil
|
||||
}
|
||||
|
||||
type forEachTree interface {
|
||||
ForEach(func(address.Address, *types.Actor) error) error
|
||||
}
|
||||
|
||||
func doTransfer(tree types.StateTree, from, to address.Address, amt abi.TokenAmount) error {
|
||||
func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address, amt abi.TokenAmount) error {
|
||||
fromAct, err := tree.GetActor(from)
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
FundsForMiners := types.FromFil(1_000_000)
|
||||
LookbackEpoch := abi.ChainEpoch(32000)
|
||||
@ -94,22 +142,22 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
|
||||
// Grab lookback state for account checks
|
||||
lbts, err := sm.ChainStore().GetTipsetByHeight(ctx, LookbackEpoch, ts, false)
|
||||
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)
|
||||
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")
|
||||
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)
|
||||
if !ok {
|
||||
return xerrors.Errorf("fork transition state tree doesnt support ForEach (%T)", tree)
|
||||
tree, err := sm.StateTree(root)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
|
||||
}
|
||||
|
||||
type transfer struct {
|
||||
@ -121,7 +169,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
|
||||
var transfers []transfer
|
||||
|
||||
// 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 {
|
||||
case builtin0.AccountActorCodeID, builtin0.MultisigActorCodeID, builtin0.PaymentChannelActorCodeID:
|
||||
sysAcc, err := isSystemAccount(addr)
|
||||
@ -163,13 +211,13 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
|
||||
return 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
|
||||
for _, t := range transfers {
|
||||
if err := doTransfer(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)
|
||||
if err := doTransfer(cb, tree, t.From, t.To, t.Amt); err != nil {
|
||||
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
|
||||
powAct, err := tree.GetActor(builtin0.StoragePowerActorAddr)
|
||||
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())
|
||||
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
|
||||
|
||||
var transfersBack []transfer
|
||||
// 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)
|
||||
if err != nil {
|
||||
if !xerrors.Is(err, types.ErrActorNotFound) {
|
||||
@ -267,53 +315,310 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, tree types
|
||||
return 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 {
|
||||
if err := doTransfer(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)
|
||||
if err := doTransfer(cb, tree, t.From, t.To, t.Amt); err != nil {
|
||||
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
|
||||
burntAct, err := tree.GetActor(builtin0.BurntFundsActorAddr)
|
||||
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 {
|
||||
return xerrors.Errorf("failed to unburn funds: %w", err)
|
||||
if err := doTransfer(cb, tree, builtin0.BurntFundsActorAddr, ReserveAddress, burntAct.Balance); err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to unburn funds: %w", err)
|
||||
}
|
||||
|
||||
// Top up the reimbursement service
|
||||
reimbAddr, err := address.NewFromString("t0111")
|
||||
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)
|
||||
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)
|
||||
if err := doTransfer(tree, ReserveAddress, reimbAddr, difference); err != nil {
|
||||
return xerrors.Errorf("failed to top up reimbursement account: %w", err)
|
||||
if err := doTransfer(cb, tree, ReserveAddress, reimbAddr, difference); err != nil {
|
||||
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
|
||||
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)
|
||||
return 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)
|
||||
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
|
||||
|
@ -129,33 +129,38 @@ func TestForkHeightTriggers(t *testing.T) {
|
||||
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())
|
||||
|
||||
st, err := sm.StateTree(root)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
|
||||
}
|
||||
|
||||
act, err := st.GetActor(taddr)
|
||||
if err != nil {
|
||||
return err
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
var tas testActorState
|
||||
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
|
||||
|
||||
ns, err := cst.Put(ctx, &tas)
|
||||
if err != nil {
|
||||
return err
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
act.Head = ns
|
||||
|
||||
if err := st.SetActor(taddr, act); err != nil {
|
||||
return err
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
return nil
|
||||
return st.Flush(ctx)
|
||||
}
|
||||
|
||||
inv.Register(nil, testActor{})
|
||||
|
@ -40,12 +40,13 @@ var log = logging.Logger("statemgr")
|
||||
type StateManager struct {
|
||||
cs *store.ChainStore
|
||||
|
||||
stCache map[string][]cid.Cid
|
||||
compWait map[string]chan struct{}
|
||||
stlk sync.Mutex
|
||||
genesisMsigLk sync.Mutex
|
||||
newVM func(context.Context, *vm.VMOpts) (*vm.VM, error)
|
||||
genInfo *genesisInfo
|
||||
stCache map[string][]cid.Cid
|
||||
compWait map[string]chan struct{}
|
||||
stlk sync.Mutex
|
||||
genesisMsigLk sync.Mutex
|
||||
newVM func(context.Context, *vm.VMOpts) (*vm.VM, error)
|
||||
preIgnitionGenInfos *genesisInfo
|
||||
postIgnitionGenInfos *genesisInfo
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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, func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
|
||||
func traceFunc(trace *[]*api.InvocResult) func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
|
||||
return func(mcid cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
|
||||
ir := &api.InvocResult{
|
||||
Msg: msg,
|
||||
MsgRct: &ret.MessageReceipt,
|
||||
@ -134,9 +134,14 @@ func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (c
|
||||
if ret.ActorErr != nil {
|
||||
ir.Error = ret.ActorErr.Error()
|
||||
}
|
||||
trace = append(trace, ir)
|
||||
*trace = append(*trace, ir)
|
||||
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 {
|
||||
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) {
|
||||
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: pstate,
|
||||
Epoch: epoch,
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
||||
NtwkVersion: sm.GetNtwkVersion,
|
||||
BaseFee: baseFee,
|
||||
makeVmWithBaseState := func(base cid.Cid) (*vm.VM, error) {
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: base,
|
||||
Epoch: epoch,
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
||||
NtwkVersion: sm.GetNtwkVersion,
|
||||
BaseFee: baseFee,
|
||||
}
|
||||
|
||||
return sm.newVM(ctx, vmopt)
|
||||
}
|
||||
|
||||
vmi, err := sm.newVM(ctx, vmopt)
|
||||
vmi, err := makeVmWithBaseState(pstate)
|
||||
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 {
|
||||
@ -201,19 +210,32 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
|
||||
for i := parentEpoch; i < epoch; i++ {
|
||||
// handle state forks
|
||||
// XXX: The state tree
|
||||
err = sm.handleStateForks(ctx, vmi.StateTree(), i, ts)
|
||||
newState, err := sm.handleStateForks(ctx, pstate, i, cb, ts)
|
||||
if err != nil {
|
||||
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 {
|
||||
// run cron for null rounds if any
|
||||
if err := runCron(); err != nil {
|
||||
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)
|
||||
pstate = newState
|
||||
}
|
||||
|
||||
var receipts []cbg.CBORMarshaler
|
||||
@ -903,7 +925,7 @@ func (sm *StateManager) setupGenesisActors(ctx context.Context) error {
|
||||
gi.genesisMsigs = append(gi.genesisMsigs, ns)
|
||||
}
|
||||
|
||||
sm.genInfo = &gi
|
||||
sm.preIgnitionGenInfos = &gi
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -911,7 +933,7 @@ func (sm *StateManager) setupGenesisActors(ctx context.Context) error {
|
||||
// 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
|
||||
// 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{}
|
||||
|
||||
@ -980,7 +1002,87 @@ func (sm *StateManager) setupGenesisActorsTestnet(ctx context.Context) error {
|
||||
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
|
||||
}
|
||||
@ -990,13 +1092,23 @@ func (sm *StateManager) setupGenesisActorsTestnet(ctx context.Context) error {
|
||||
// - For Accounts, it counts max(currentBalance - genesisBalance, 0).
|
||||
func (sm *StateManager) GetFilVested(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) {
|
||||
vf := big.Zero()
|
||||
for _, v := range sm.genInfo.genesisMsigs {
|
||||
au := big.Sub(v.InitialBalance, v.AmountLocked(height))
|
||||
vf = big.Add(vf, au)
|
||||
if height <= build.UpgradeIgnitionHeight {
|
||||
for _, v := range sm.preIgnitionGenInfos.genesisMsigs {
|
||||
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?)
|
||||
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)
|
||||
if err != nil {
|
||||
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)
|
||||
vf = big.Add(vf, sm.genInfo.genesisMarketFunds)
|
||||
// continue to use preIgnitionGenInfos, nothing changed at the Ignition epoch
|
||||
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
|
||||
}
|
||||
@ -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) {
|
||||
sm.genesisMsigLk.Lock()
|
||||
defer sm.genesisMsigLk.Unlock()
|
||||
if sm.genInfo == nil {
|
||||
err := sm.setupGenesisActorsTestnet(ctx)
|
||||
if sm.preIgnitionGenInfos == nil {
|
||||
err := sm.setupPreIgnitionGenesisActorsTestnet(ctx)
|
||||
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
|
||||
}
|
||||
|
||||
if height <= build.UpgradeIgnitionHeight {
|
||||
return network.Version2
|
||||
}
|
||||
|
||||
return build.NewestNetworkVersion
|
||||
}
|
||||
|
||||
|
@ -95,6 +95,7 @@ func GetPowerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr addres
|
||||
}
|
||||
|
||||
var mpow power.Claim
|
||||
var minpow bool
|
||||
if maddr != address.Undef {
|
||||
var found bool
|
||||
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?
|
||||
return power.Claim{}, power.Claim{}, false, err
|
||||
}
|
||||
}
|
||||
|
||||
minpow, err := pas.MinerNominalPowerMeetsConsensusMinimum(maddr)
|
||||
if err != nil {
|
||||
return power.Claim{}, power.Claim{}, false, err
|
||||
minpow, err = pas.MinerNominalPowerMeetsConsensusMinimum(maddr)
|
||||
if err != nil {
|
||||
return power.Claim{}, power.Claim{}, false, err
|
||||
}
|
||||
}
|
||||
|
||||
return mpow, tpow, minpow, nil
|
||||
@ -361,6 +362,16 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
|
||||
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())
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: base,
|
||||
@ -377,16 +388,6 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
|
||||
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 {
|
||||
// TODO: Use the signed message length for secp messages
|
||||
ret, err := vmi.ApplyMessage(ctx, msg)
|
||||
|
@ -10,14 +10,18 @@ import (
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/minio/blake2b-simd"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"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/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"github.com/filecoin-project/lotus/journal"
|
||||
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
|
||||
}
|
||||
|
||||
var blks []*types.BlockHeader
|
||||
for _, c := range tsk.Cids() {
|
||||
b, err := cs.GetBlock(c)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("get block %s: %w", c, err)
|
||||
}
|
||||
// Fetch tipset block headers from blockstore in parallel
|
||||
var eg errgroup.Group
|
||||
cids := tsk.Cids()
|
||||
blks := make([]*types.BlockHeader, len(cids))
|
||||
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)
|
||||
@ -1183,6 +1198,7 @@ func (cs *ChainStore) Export(ctx context.Context, ts *types.TipSet, inclRecentRo
|
||||
}
|
||||
|
||||
blocksToWalk := ts.Cids()
|
||||
currentMinHeight := ts.Height()
|
||||
|
||||
walkChain := func(blk cid.Cid) error {
|
||||
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)
|
||||
}
|
||||
|
||||
if currentMinHeight > b.Height {
|
||||
currentMinHeight = b.Height
|
||||
if currentMinHeight%builtin.EpochsInDay == 0 {
|
||||
log.Infow("export", "height", currentMinHeight)
|
||||
}
|
||||
}
|
||||
|
||||
var cids []cid.Cid
|
||||
if !skipOldMsgs || b.Height > ts.Height()-inclRecentRoots {
|
||||
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
|
||||
}
|
||||
|
||||
log.Infow("export started")
|
||||
exportStart := build.Clock.Now()
|
||||
|
||||
for len(blocksToWalk) > 0 {
|
||||
next := blocksToWalk[0]
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -167,12 +167,16 @@ func (ts *TipSet) Equals(ots *TipSet) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(ts.blks) != len(ots.blks) {
|
||||
if ts.height != ots.height {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, b := range ts.blks {
|
||||
if b.Cid() != ots.blks[i].Cid() {
|
||||
if len(ts.cids) != len(ots.cids) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, cid := range ts.cids {
|
||||
if cid != ots.cids[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
@ -35,3 +38,40 @@ func TestSignedMessageJsonRoundtrip(t *testing.T) {
|
||||
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/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/multiformats/go-multihash"
|
||||
"github.com/urfave/cli/v2"
|
||||
@ -30,7 +31,9 @@ import (
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/apibstore"
|
||||
"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/types"
|
||||
)
|
||||
@ -815,6 +818,10 @@ var stateComputeStateCmd = &cli.Command{
|
||||
Name: "html",
|
||||
Usage: "generate html report",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "json",
|
||||
Usage: "generate json output",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
@ -831,14 +838,14 @@ var stateComputeStateCmd = &cli.Command{
|
||||
}
|
||||
|
||||
h := abi.ChainEpoch(cctx.Uint64("vm-height"))
|
||||
if h == 0 {
|
||||
if ts == nil {
|
||||
head, err := api.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ts = head
|
||||
if ts == nil {
|
||||
head, err := api.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ts = head
|
||||
}
|
||||
if h == 0 {
|
||||
h = ts.Height()
|
||||
}
|
||||
|
||||
@ -859,14 +866,28 @@ var stateComputeStateCmd = &cli.Command{
|
||||
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") {
|
||||
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{}
|
||||
getCode := func(addr address.Address) (cid.Cid, error) {
|
||||
if c, found := codeCache[addr]; found {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
c, err := api.StateGetActor(ctx, addr, ts.Key())
|
||||
c, err := st.GetActor(addr)
|
||||
if err != nil {
|
||||
return cid.Cid{}, err
|
||||
}
|
||||
|
@ -76,8 +76,6 @@ func main() {
|
||||
|
||||
log.Info("Starting lotus-bench")
|
||||
|
||||
policy.AddSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
|
||||
|
||||
app := &cli.App{
|
||||
Name: "lotus-bench",
|
||||
Usage: "Benchmark performance of lotus on your hardware",
|
||||
@ -147,6 +145,8 @@ var sealBenchCmd = &cli.Command{
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
policy.AddSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
|
||||
|
||||
if c.Bool("no-gpu") {
|
||||
err := os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
if err != nil {
|
||||
|
@ -3,9 +3,16 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"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"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
@ -44,6 +51,7 @@ var auditsCmd = &cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
chainBalanceCmd,
|
||||
chainBalanceStateCmd,
|
||||
chainPledgeCmd,
|
||||
},
|
||||
}
|
||||
|
||||
@ -248,3 +256,133 @@ var chainBalanceStateCmd = &cli.Command{
|
||||
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
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
@ -23,6 +26,7 @@ import (
|
||||
"go.opencensus.io/stats/view"
|
||||
"go.opencensus.io/tag"
|
||||
"golang.org/x/xerrors"
|
||||
"gopkg.in/cheggaaa/pb.v1"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
@ -100,11 +104,11 @@ var DaemonCmd = &cli.Command{
|
||||
},
|
||||
&cli.StringFlag{
|
||||
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{
|
||||
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{
|
||||
Name: "halt-after-import",
|
||||
@ -206,11 +210,6 @@ var DaemonCmd = &cli.Command{
|
||||
issnapshot = true
|
||||
}
|
||||
|
||||
chainfile, err := homedir.Expand(chainfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ImportChain(r, chainfile, issnapshot); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -326,12 +325,42 @@ func importKey(ctx context.Context, api api.FullNode, f string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ImportChain(r repo.Repo, fname string, snapshot bool) error {
|
||||
fi, err := os.Open(fname)
|
||||
if err != nil {
|
||||
return err
|
||||
func ImportChain(r repo.Repo, fname string, snapshot bool) (err error) {
|
||||
var rd io.Reader
|
||||
var l int64
|
||||
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)
|
||||
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))
|
||||
|
||||
log.Info("importing chain from file...")
|
||||
ts, err := cst.Import(fi)
|
||||
log.Infof("importing chain from %s...", fname)
|
||||
|
||||
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 {
|
||||
return xerrors.Errorf("importing chain failed: %w", err)
|
||||
}
|
||||
|
@ -3825,7 +3825,7 @@ Inputs:
|
||||
]
|
||||
```
|
||||
|
||||
Response: `2`
|
||||
Response: `3`
|
||||
|
||||
### StateReadState
|
||||
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/fatih/color v1.8.0
|
||||
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-cbor-util v0.0.0-20191219014500-08c40a1e63a2
|
||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
|
||||
github.com/filecoin-project/go-data-transfer v0.6.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-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-multistore v0.0.3
|
||||
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-filestore v1.0.0
|
||||
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-chunker v0.0.5
|
||||
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/time v0.0.0-20191024005414-555d28b269f0
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.28
|
||||
gotest.tools v2.2.0+incompatible
|
||||
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/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.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/go.mod h1:nfFPoGyX0CU9SkXX8EoCcSuHN1XcbN0c6KBh7yvP5fs=
|
||||
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-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus=
|
||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ=
|
||||
github.com/filecoin-project/go-data-transfer v0.6.5 h1:oP20la8Z0CLrw0uqvt6xVgw6rOevZeGJ9GNQeC0OCSU=
|
||||
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 h1:2TccLSxPYJENcYRdov2WvpTvQ1qUMrPkWe8sBrfj36g=
|
||||
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/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.2/go.mod h1:wtN4Hc/1hoVCpWhSWYxwUxH3PQtjSkWWuC1nQjiIWog=
|
||||
github.com/filecoin-project/go-fil-markets v0.6.3 h1:3kTxfquGvk3zQY+hJH1kEA28tRQ47phqSRqOI4+YcQM=
|
||||
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/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/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM=
|
||||
github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE=
|
||||
github.com/ipfs/go-graphsync v0.2.0 h1:x94MvHLNuRwBlZzVal7tR1RYK7T7H6bqQLPopxDbIF0=
|
||||
github.com/ipfs/go-graphsync v0.2.0/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10=
|
||||
github.com/ipfs/go-graphsync v0.2.1 h1:MdehhqBSuTI2LARfKLkpYnt0mUrqHs/mtuDnESXHBfU=
|
||||
github.com/ipfs/go-graphsync v0.2.1/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10=
|
||||
github.com/ipfs/go-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.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw=
|
||||
|
@ -211,6 +211,8 @@ minerLoop:
|
||||
base = prebase
|
||||
}
|
||||
|
||||
base.NullRounds += injectNulls // testing
|
||||
|
||||
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)
|
||||
if !m.niceSleep(time.Duration(build.BlockDelaySecs) * time.Second) {
|
||||
@ -219,8 +221,6 @@ minerLoop:
|
||||
continue
|
||||
}
|
||||
|
||||
base.NullRounds += injectNulls // testing
|
||||
|
||||
b, err := m.mineOne(ctx, base)
|
||||
if err != nil {
|
||||
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/build"
|
||||
"github.com/filecoin-project/lotus/chain"
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
"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) {
|
||||
if !build.Devnet {
|
||||
return "testnetnet", nil
|
||||
}
|
||||
|
||||
ctx := helpers.LifecycleCtx(mctx, lc)
|
||||
|
||||
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) {
|
||||
if !build.Devnet {
|
||||
return "testnetnet", nil
|
||||
}
|
||||
return a.StateNetworkName(ctx)
|
||||
}
|
||||
|
||||
|
@ -371,6 +371,10 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty
|
||||
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 {
|
||||
// TODO: This is also potentially really bad, but we try to post anyways
|
||||
log.Errorf("checking sector faults: %v", err)
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
|
||||
@ -252,6 +253,14 @@ func RecordTipsetStatePoints(ctx context.Context, api api.FullNode, pl *PointLis
|
||||
p := NewPoint("network.balance", netBalFilFloat)
|
||||
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())
|
||||
if err != nil {
|
||||
return err
|
||||
|
Loading…
Reference in New Issue
Block a user