Merge branch 'master' into asr/spec-v1

This commit is contained in:
Steven Allen 2020-09-28 12:53:40 -07:00
commit 947d1e2902
32 changed files with 1031 additions and 153 deletions

View File

@ -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.

View File

@ -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

View File

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

View File

@ -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,

View File

@ -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
}

View File

@ -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

View File

@ -75,6 +75,8 @@ var (
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
) )

View File

@ -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)

View File

@ -29,7 +29,7 @@ func buildType() string {
} }
// BuildVersion is the local build version, set by build system // BuildVersion is the local build version, set by build system
const BuildVersion = "0.7.2" const BuildVersion = "0.8.0"
func UserVersion() string { func UserVersion() string {
return BuildVersion + buildType() + CurrentCommit return BuildVersion + buildType() + CurrentCommit

View File

@ -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
} }

View File

@ -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. // Set for all miner versions.
miner0.SupportedProofTypes = newTypes miner0.SupportedProofTypes[t] = struct{}{}
}
} }
// SetPreCommitChallengeDelay sets the pre-commit challenge delay across all // SetPreCommitChallengeDelay sets the pre-commit challenge delay across all

View File

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

View File

@ -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))

View File

@ -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

View File

@ -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{})

View File

@ -45,7 +45,8 @@ type StateManager 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,8 +153,9 @@ 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) {
makeVmWithBaseState := func(base cid.Cid) (*vm.VM, error) {
vmopt := &vm.VMOpts{ vmopt := &vm.VMOpts{
StateBase: pstate, StateBase: base,
Epoch: epoch, Epoch: epoch,
Rand: r, Rand: r,
Bstore: sm.cs.Blockstore(), Bstore: sm.cs.Blockstore(),
@ -159,9 +165,12 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
BaseFee: baseFee, BaseFee: baseFee,
} }
vmi, err := sm.newVM(ctx, vmopt) return 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 {
for _, v := range sm.preIgnitionGenInfos.genesisMsigs {
au := big.Sub(v.InitialBalance, v.AmountLocked(height)) au := big.Sub(v.InitialBalance, v.AmountLocked(height))
vf = big.Add(vf, au) 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
} }

View File

@ -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,12 +103,12 @@ 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)

View File

@ -10,14 +10,18 @@ import (
"strconv" "strconv"
"sync" "sync"
"golang.org/x/sync/errgroup"
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
"github.com/minio/blake2b-simd" "github.com/minio/blake2b-simd"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/journal"
bstore "github.com/filecoin-project/lotus/lib/blockstore" bstore "github.com/filecoin-project/lotus/lib/blockstore"
@ -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
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) b, err := cs.GetBlock(c)
if err != nil { if err != nil {
return nil, xerrors.Errorf("get block %s: %w", c, err) 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
} }

View File

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

View File

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

View File

@ -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,7 +838,6 @@ 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 {
@ -839,6 +845,7 @@ var stateComputeStateCmd = &cli.Command{
} }
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
} }

View File

@ -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 {

View File

@ -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
},
}

View File

@ -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,13 +325,43 @@ 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) {
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) fi, err := os.Open(fname)
if err != nil { if err != nil {
return err return err
} }
defer fi.Close() //nolint:errcheck defer fi.Close() //nolint:errcheck
st, err := os.Stat(fname)
if err != nil {
return err
}
rd = fi
l = st.Size()
}
lr, err := r.Lock(repo.FullNode) lr, err := r.Lock(repo.FullNode)
if err != nil { if err != nil {
return err return err
@ -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)
} }

View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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)

View File

@ -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())

View File

@ -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)
} }

View File

@ -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)

View File

@ -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