diff --git a/api/test/test.go b/api/test/test.go index eeddc23a089..44530191bd1 100644 --- a/api/test/test.go +++ b/api/test/test.go @@ -122,7 +122,8 @@ var TwoFull = DefaultFullOpts(2) var FullNodeWithLatestActorsAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts { if upgradeHeight == -1 { - upgradeHeight = 3 + // Attention: Update this when introducing new actor versions or your tests will be sad + upgradeHeight = 4 } return FullNodeOpts{ @@ -138,8 +139,12 @@ var FullNodeWithLatestActorsAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts Migration: stmgr.UpgradeActorsV3, }, { Network: network.Version12, - Height: upgradeHeight, + Height: 3, Migration: stmgr.UpgradeActorsV4, + }, { + Network: network.Version13, + Height: upgradeHeight, + Migration: stmgr.UpgradeActorsV5, }}) }, } diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 6cc950d7308..a44f87bc3be 100644 Binary files a/build/openrpc/full.json.gz and b/build/openrpc/full.json.gz differ diff --git a/build/params_2k.go b/build/params_2k.go index 12d497c4b6e..e6a52ea41cb 100644 --- a/build/params_2k.go +++ b/build/params_2k.go @@ -39,6 +39,8 @@ var UpgradeNorwegianHeight = abi.ChainEpoch(40) var UpgradeActorsV4Height = abi.ChainEpoch(45) +var UpgradeHyperdriveHeight = abi.ChainEpoch(50) + var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, } @@ -78,6 +80,7 @@ func init() { UpgradeActorsV3Height = getUpgradeHeight("LOTUS_ACTORSV3_HEIGHT", UpgradeActorsV3Height) UpgradeNorwegianHeight = getUpgradeHeight("LOTUS_NORWEGIAN_HEIGHT", UpgradeNorwegianHeight) UpgradeActorsV4Height = getUpgradeHeight("LOTUS_ACTORSV4_HEIGHT", UpgradeActorsV4Height) + UpgradeHyperdriveHeight = getUpgradeHeight("LOTUS_HYPERDRIVE_HEIGHT", UpgradeHyperdriveHeight) BuildType |= Build2k } diff --git a/build/params_butterfly.go b/build/params_butterfly.go index 6daeca50215..d85c1254528 100644 --- a/build/params_butterfly.go +++ b/build/params_butterfly.go @@ -35,6 +35,7 @@ const UpgradeOrangeHeight = 210 const UpgradeActorsV3Height = 240 const UpgradeNorwegianHeight = UpgradeActorsV3Height + (builtin2.EpochsInHour * 12) const UpgradeActorsV4Height = 8922 +const UpgradeHyperdriveHeight = 9999999 func init() { policy.SetConsensusMinerMinPower(abi.NewStoragePower(2 << 30)) diff --git a/build/params_calibnet.go b/build/params_calibnet.go index 997bb395bac..0c3cfe799a4 100644 --- a/build/params_calibnet.go +++ b/build/params_calibnet.go @@ -45,6 +45,8 @@ const UpgradeNorwegianHeight = 114000 const UpgradeActorsV4Height = 193789 +const UpgradeHyperdriveHeight = 9999999 + func init() { policy.SetConsensusMinerMinPower(abi.NewStoragePower(32 << 30)) policy.SetSupportedProofTypes( diff --git a/build/params_mainnet.go b/build/params_mainnet.go index ea4ae7d75ef..07dfb51077d 100644 --- a/build/params_mainnet.go +++ b/build/params_mainnet.go @@ -62,6 +62,9 @@ const UpgradeNorwegianHeight = 665280 // 2021-04-29T06:00:00Z var UpgradeActorsV4Height = abi.ChainEpoch(712320) +// ??? +var UpgradeHyperdriveHeight = abi.ChainEpoch(9999999) + func init() { policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40)) diff --git a/build/params_nerpanet.go b/build/params_nerpanet.go index fb6cfc47ab7..23ba4b0dca9 100644 --- a/build/params_nerpanet.go +++ b/build/params_nerpanet.go @@ -42,6 +42,7 @@ const UpgradeOrangeHeight = 300 const UpgradeActorsV3Height = 600 const UpgradeNorwegianHeight = 999999 const UpgradeActorsV4Height = 99999999 +const UpgradeHyperdriveHeight = 999999999 func init() { // Minimum block production power is set to 4 TiB diff --git a/build/params_shared_vals.go b/build/params_shared_vals.go index 92bbc5db915..e4240ccce12 100644 --- a/build/params_shared_vals.go +++ b/build/params_shared_vals.go @@ -25,7 +25,7 @@ const UnixfsLinksPerLevel = 1024 // Consensus / Network const AllowableClockDriftSecs = uint64(1) -const NewestNetworkVersion = network.Version11 +const NewestNetworkVersion = network.Version13 const ActorUpgradeNetworkVersion = network.Version4 // Epochs diff --git a/build/params_testground.go b/build/params_testground.go index 7da3c2272b7..9f2f9f3b3d0 100644 --- a/build/params_testground.go +++ b/build/params_testground.go @@ -82,20 +82,21 @@ var ( UpgradeBreezeHeight abi.ChainEpoch = -1 BreezeGasTampingDuration abi.ChainEpoch = 0 - UpgradeSmokeHeight abi.ChainEpoch = -1 - UpgradeIgnitionHeight abi.ChainEpoch = -2 - UpgradeRefuelHeight abi.ChainEpoch = -3 - UpgradeTapeHeight abi.ChainEpoch = -4 - UpgradeActorsV2Height abi.ChainEpoch = 10 - UpgradeLiftoffHeight abi.ChainEpoch = -5 - UpgradeKumquatHeight abi.ChainEpoch = -6 - UpgradeCalicoHeight abi.ChainEpoch = -7 - UpgradePersianHeight abi.ChainEpoch = -8 - UpgradeOrangeHeight abi.ChainEpoch = -9 - UpgradeClausHeight abi.ChainEpoch = -10 - UpgradeActorsV3Height abi.ChainEpoch = -11 - UpgradeNorwegianHeight abi.ChainEpoch = -12 - UpgradeActorsV4Height abi.ChainEpoch = -13 + UpgradeSmokeHeight abi.ChainEpoch = -1 + UpgradeIgnitionHeight abi.ChainEpoch = -2 + UpgradeRefuelHeight abi.ChainEpoch = -3 + UpgradeTapeHeight abi.ChainEpoch = -4 + UpgradeActorsV2Height abi.ChainEpoch = 10 + UpgradeLiftoffHeight abi.ChainEpoch = -5 + UpgradeKumquatHeight abi.ChainEpoch = -6 + UpgradeCalicoHeight abi.ChainEpoch = -7 + UpgradePersianHeight abi.ChainEpoch = -8 + UpgradeOrangeHeight abi.ChainEpoch = -9 + UpgradeClausHeight abi.ChainEpoch = -10 + UpgradeActorsV3Height abi.ChainEpoch = -11 + UpgradeNorwegianHeight abi.ChainEpoch = -12 + UpgradeActorsV4Height abi.ChainEpoch = -13 + UpgradeHyperdriveHeight abi.ChainEpoch = -13 DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, diff --git a/chain/actors/agen/main.go b/chain/actors/agen/main.go index 7269d9ae592..d34b43ca87f 100644 --- a/chain/actors/agen/main.go +++ b/chain/actors/agen/main.go @@ -11,15 +11,16 @@ import ( "golang.org/x/xerrors" ) -var latestVersion = 4 +var latestVersion = 5 -var versions = []int{0, 2, 3, latestVersion} +var versions = []int{0, 2, 3, 4, latestVersion} var versionImports = map[int]string{ 0: "/", 2: "/v2/", 3: "/v3/", - latestVersion: "/v4/", + 4: "/v4/", + latestVersion: "/v5/", } var actors = map[string][]int{ diff --git a/chain/actors/builtin/account/account.go b/chain/actors/builtin/account/account.go index 8242e300dae..7ac8f62d03c 100644 --- a/chain/actors/builtin/account/account.go +++ b/chain/actors/builtin/account/account.go @@ -18,6 +18,8 @@ import ( builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" ) func init() { @@ -37,6 +39,10 @@ func init() { builtin.RegisterActorState(builtin4.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load4(store, root) }) + + builtin.RegisterActorState(builtin5.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load5(store, root) + }) } var Methods = builtin4.MethodsAccount @@ -56,6 +62,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin4.AccountActorCodeID: return load4(store, act.Head) + case builtin5.AccountActorCodeID: + return load5(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/builtin/account/v5.go b/chain/actors/builtin/account/v5.go new file mode 100644 index 00000000000..e2df5904da6 --- /dev/null +++ b/chain/actors/builtin/account/v5.go @@ -0,0 +1,30 @@ +package account + +import ( + "github.com/filecoin-project/go-address" + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/lotus/chain/actors/adt" + + account5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/account" +) + +var _ State = (*state5)(nil) + +func load5(store adt.Store, root cid.Cid) (State, error) { + out := state5{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state5 struct { + account5.State + store adt.Store +} + +func (s *state5) PubkeyAddress() (address.Address, error) { + return s.Address, nil +} diff --git a/chain/actors/builtin/builtin.go b/chain/actors/builtin/builtin.go index 5e34c015a9d..74d6228193b 100644 --- a/chain/actors/builtin/builtin.go +++ b/chain/actors/builtin/builtin.go @@ -17,46 +17,49 @@ import ( builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" smoothing4 "github.com/filecoin-project/specs-actors/v4/actors/util/smoothing" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + smoothing5 "github.com/filecoin-project/specs-actors/v5/actors/util/smoothing" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/cbor" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" - miner4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner" - proof4 "github.com/filecoin-project/specs-actors/v4/actors/runtime/proof" + miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner" + proof5 "github.com/filecoin-project/specs-actors/v5/actors/runtime/proof" ) -var SystemActorAddr = builtin4.SystemActorAddr -var BurntFundsActorAddr = builtin4.BurntFundsActorAddr -var CronActorAddr = builtin4.CronActorAddr +var SystemActorAddr = builtin5.SystemActorAddr +var BurntFundsActorAddr = builtin5.BurntFundsActorAddr +var CronActorAddr = builtin5.CronActorAddr var SaftAddress = makeAddress("t0122") var ReserveAddress = makeAddress("t090") var RootVerifierAddress = makeAddress("t080") var ( - ExpectedLeadersPerEpoch = builtin4.ExpectedLeadersPerEpoch + ExpectedLeadersPerEpoch = builtin5.ExpectedLeadersPerEpoch ) const ( - EpochDurationSeconds = builtin4.EpochDurationSeconds - EpochsInDay = builtin4.EpochsInDay - SecondsInDay = builtin4.SecondsInDay + EpochDurationSeconds = builtin5.EpochDurationSeconds + EpochsInDay = builtin5.EpochsInDay + SecondsInDay = builtin5.SecondsInDay ) const ( - MethodSend = builtin4.MethodSend - MethodConstructor = builtin4.MethodConstructor + MethodSend = builtin5.MethodSend + MethodConstructor = builtin5.MethodConstructor ) // These are all just type aliases across actor versions. In the future, that might change // and we might need to do something fancier. -type SectorInfo = proof4.SectorInfo -type PoStProof = proof4.PoStProof +type SectorInfo = proof5.SectorInfo +type PoStProof = proof5.PoStProof type FilterEstimate = smoothing0.FilterEstimate func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower { - return miner4.QAPowerForWeight(size, duration, dealWeight, verifiedWeight) + return miner5.QAPowerForWeight(size, duration, dealWeight, verifiedWeight) } func FromV0FilterEstimate(v0 smoothing0.FilterEstimate) FilterEstimate { @@ -83,6 +86,12 @@ func FromV4FilterEstimate(v4 smoothing4.FilterEstimate) FilterEstimate { } +func FromV5FilterEstimate(v5 smoothing5.FilterEstimate) FilterEstimate { + + return (FilterEstimate)(v5) + +} + type ActorStateLoader func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) var ActorStateLoaders = make(map[cid.Cid]ActorStateLoader) @@ -114,6 +123,9 @@ func ActorNameByCode(c cid.Cid) string { case builtin4.IsBuiltinActor(c): return builtin4.ActorNameByCode(c) + case builtin5.IsBuiltinActor(c): + return builtin5.ActorNameByCode(c) + default: return "" } @@ -137,6 +149,10 @@ func IsBuiltinActor(c cid.Cid) bool { return true } + if builtin5.IsBuiltinActor(c) { + return true + } + return false } @@ -158,6 +174,10 @@ func IsAccountActor(c cid.Cid) bool { return true } + if c == builtin5.AccountActorCodeID { + return true + } + return false } @@ -179,6 +199,10 @@ func IsStorageMinerActor(c cid.Cid) bool { return true } + if c == builtin5.StorageMinerActorCodeID { + return true + } + return false } @@ -200,6 +224,10 @@ func IsMultisigActor(c cid.Cid) bool { return true } + if c == builtin5.MultisigActorCodeID { + return true + } + return false } @@ -221,6 +249,10 @@ func IsPaymentChannelActor(c cid.Cid) bool { return true } + if c == builtin5.PaymentChannelActorCodeID { + return true + } + return false } diff --git a/chain/actors/builtin/cron/cron.go b/chain/actors/builtin/cron/cron.go index 52a9fab0708..a601f2b1e6b 100644 --- a/chain/actors/builtin/cron/cron.go +++ b/chain/actors/builtin/cron/cron.go @@ -1,10 +1,10 @@ package cron import ( - builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" ) var ( - Address = builtin4.CronActorAddr - Methods = builtin4.MethodsCron + Address = builtin5.CronActorAddr + Methods = builtin5.MethodsCron ) diff --git a/chain/actors/builtin/init/init.go b/chain/actors/builtin/init/init.go index 730d21fd83f..605f2d1031b 100644 --- a/chain/actors/builtin/init/init.go +++ b/chain/actors/builtin/init/init.go @@ -20,6 +20,8 @@ import ( builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" ) func init() { @@ -39,11 +41,15 @@ func init() { builtin.RegisterActorState(builtin4.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load4(store, root) }) + + builtin.RegisterActorState(builtin5.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load5(store, root) + }) } var ( - Address = builtin4.InitActorAddr - Methods = builtin4.MethodsInit + Address = builtin5.InitActorAddr + Methods = builtin5.MethodsInit ) func Load(store adt.Store, act *types.Actor) (State, error) { @@ -61,6 +67,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin4.InitActorCodeID: return load4(store, act.Head) + case builtin5.InitActorCodeID: + return load5(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/builtin/init/v5.go b/chain/actors/builtin/init/v5.go new file mode 100644 index 00000000000..01c20fc23f2 --- /dev/null +++ b/chain/actors/builtin/init/v5.go @@ -0,0 +1,87 @@ +package init + +import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/node/modules/dtypes" + + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + + init5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/init" + adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" +) + +var _ State = (*state5)(nil) + +func load5(store adt.Store, root cid.Cid) (State, error) { + out := state5{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state5 struct { + init5.State + store adt.Store +} + +func (s *state5) ResolveAddress(address address.Address) (address.Address, bool, error) { + return s.State.ResolveAddress(s.store, address) +} + +func (s *state5) MapAddressToNewID(address address.Address) (address.Address, error) { + return s.State.MapAddressToNewID(s.store, address) +} + +func (s *state5) ForEachActor(cb func(id abi.ActorID, address address.Address) error) error { + addrs, err := adt5.AsMap(s.store, s.State.AddressMap, builtin5.DefaultHamtBitwidth) + if err != nil { + return err + } + var actorID cbg.CborInt + return addrs.ForEach(&actorID, func(key string) error { + addr, err := address.NewFromBytes([]byte(key)) + if err != nil { + return err + } + return cb(abi.ActorID(actorID), addr) + }) +} + +func (s *state5) NetworkName() (dtypes.NetworkName, error) { + return dtypes.NetworkName(s.State.NetworkName), nil +} + +func (s *state5) SetNetworkName(name string) error { + s.State.NetworkName = name + return nil +} + +func (s *state5) Remove(addrs ...address.Address) (err error) { + m, err := adt5.AsMap(s.store, s.State.AddressMap, builtin5.DefaultHamtBitwidth) + if err != nil { + return err + } + for _, addr := range addrs { + if err = m.Delete(abi.AddrKey(addr)); err != nil { + return xerrors.Errorf("failed to delete entry for address: %s; err: %w", addr, err) + } + } + amr, err := m.Root() + if err != nil { + return xerrors.Errorf("failed to get address map root: %w", err) + } + s.State.AddressMap = amr + return nil +} + +func (s *state5) addressMap() (adt.Map, error) { + return adt5.AsMap(s.store, s.AddressMap, builtin5.DefaultHamtBitwidth) +} diff --git a/chain/actors/builtin/market/market.go b/chain/actors/builtin/market/market.go index 63e8c42d3a4..8f5964ecc5e 100644 --- a/chain/actors/builtin/market/market.go +++ b/chain/actors/builtin/market/market.go @@ -19,6 +19,8 @@ import ( builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/types" @@ -41,11 +43,15 @@ func init() { builtin.RegisterActorState(builtin4.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load4(store, root) }) + + builtin.RegisterActorState(builtin5.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load5(store, root) + }) } var ( - Address = builtin4.StorageMarketActorAddr - Methods = builtin4.MethodsMarket + Address = builtin5.StorageMarketActorAddr + Methods = builtin5.MethodsMarket ) func Load(store adt.Store, act *types.Actor) (State, error) { @@ -63,6 +69,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin4.StorageMarketActorCodeID: return load4(store, act.Head) + case builtin5.StorageMarketActorCodeID: + return load5(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/builtin/market/v5.go b/chain/actors/builtin/market/v5.go new file mode 100644 index 00000000000..9acd3d57e81 --- /dev/null +++ b/chain/actors/builtin/market/v5.go @@ -0,0 +1,209 @@ +package market + +import ( + "bytes" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/types" + + market5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/market" + adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" +) + +var _ State = (*state5)(nil) + +func load5(store adt.Store, root cid.Cid) (State, error) { + out := state5{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state5 struct { + market5.State + store adt.Store +} + +func (s *state5) TotalLocked() (abi.TokenAmount, error) { + fml := types.BigAdd(s.TotalClientLockedCollateral, s.TotalProviderLockedCollateral) + fml = types.BigAdd(fml, s.TotalClientStorageFee) + return fml, nil +} + +func (s *state5) BalancesChanged(otherState State) (bool, error) { + otherState5, ok := otherState.(*state5) + if !ok { + // there's no way to compare different versions of the state, so let's + // just say that means the state of balances has changed + return true, nil + } + return !s.State.EscrowTable.Equals(otherState5.State.EscrowTable) || !s.State.LockedTable.Equals(otherState5.State.LockedTable), nil +} + +func (s *state5) StatesChanged(otherState State) (bool, error) { + otherState5, ok := otherState.(*state5) + if !ok { + // there's no way to compare different versions of the state, so let's + // just say that means the state of balances has changed + return true, nil + } + return !s.State.States.Equals(otherState5.State.States), nil +} + +func (s *state5) States() (DealStates, error) { + stateArray, err := adt5.AsArray(s.store, s.State.States, market5.StatesAmtBitwidth) + if err != nil { + return nil, err + } + return &dealStates5{stateArray}, nil +} + +func (s *state5) ProposalsChanged(otherState State) (bool, error) { + otherState5, ok := otherState.(*state5) + if !ok { + // there's no way to compare different versions of the state, so let's + // just say that means the state of balances has changed + return true, nil + } + return !s.State.Proposals.Equals(otherState5.State.Proposals), nil +} + +func (s *state5) Proposals() (DealProposals, error) { + proposalArray, err := adt5.AsArray(s.store, s.State.Proposals, market5.ProposalsAmtBitwidth) + if err != nil { + return nil, err + } + return &dealProposals5{proposalArray}, nil +} + +func (s *state5) EscrowTable() (BalanceTable, error) { + bt, err := adt5.AsBalanceTable(s.store, s.State.EscrowTable) + if err != nil { + return nil, err + } + return &balanceTable5{bt}, nil +} + +func (s *state5) LockedTable() (BalanceTable, error) { + bt, err := adt5.AsBalanceTable(s.store, s.State.LockedTable) + if err != nil { + return nil, err + } + return &balanceTable5{bt}, nil +} + +func (s *state5) VerifyDealsForActivation( + minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch, +) (weight, verifiedWeight abi.DealWeight, err error) { + w, vw, _, err := market5.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch) + return w, vw, err +} + +func (s *state5) NextID() (abi.DealID, error) { + return s.State.NextID, nil +} + +type balanceTable5 struct { + *adt5.BalanceTable +} + +func (bt *balanceTable5) ForEach(cb func(address.Address, abi.TokenAmount) error) error { + asMap := (*adt5.Map)(bt.BalanceTable) + var ta abi.TokenAmount + return asMap.ForEach(&ta, func(key string) error { + a, err := address.NewFromBytes([]byte(key)) + if err != nil { + return err + } + return cb(a, ta) + }) +} + +type dealStates5 struct { + adt.Array +} + +func (s *dealStates5) Get(dealID abi.DealID) (*DealState, bool, error) { + var deal5 market5.DealState + found, err := s.Array.Get(uint64(dealID), &deal5) + if err != nil { + return nil, false, err + } + if !found { + return nil, false, nil + } + deal := fromV5DealState(deal5) + return &deal, true, nil +} + +func (s *dealStates5) ForEach(cb func(dealID abi.DealID, ds DealState) error) error { + var ds5 market5.DealState + return s.Array.ForEach(&ds5, func(idx int64) error { + return cb(abi.DealID(idx), fromV5DealState(ds5)) + }) +} + +func (s *dealStates5) decode(val *cbg.Deferred) (*DealState, error) { + var ds5 market5.DealState + if err := ds5.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return nil, err + } + ds := fromV5DealState(ds5) + return &ds, nil +} + +func (s *dealStates5) array() adt.Array { + return s.Array +} + +func fromV5DealState(v5 market5.DealState) DealState { + return (DealState)(v5) +} + +type dealProposals5 struct { + adt.Array +} + +func (s *dealProposals5) Get(dealID abi.DealID) (*DealProposal, bool, error) { + var proposal5 market5.DealProposal + found, err := s.Array.Get(uint64(dealID), &proposal5) + if err != nil { + return nil, false, err + } + if !found { + return nil, false, nil + } + proposal := fromV5DealProposal(proposal5) + return &proposal, true, nil +} + +func (s *dealProposals5) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error { + var dp5 market5.DealProposal + return s.Array.ForEach(&dp5, func(idx int64) error { + return cb(abi.DealID(idx), fromV5DealProposal(dp5)) + }) +} + +func (s *dealProposals5) decode(val *cbg.Deferred) (*DealProposal, error) { + var dp5 market5.DealProposal + if err := dp5.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return nil, err + } + dp := fromV5DealProposal(dp5) + return &dp, nil +} + +func (s *dealProposals5) array() adt.Array { + return s.Array +} + +func fromV5DealProposal(v5 market5.DealProposal) DealProposal { + return (DealProposal)(v5) +} diff --git a/chain/actors/builtin/miner/miner.go b/chain/actors/builtin/miner/miner.go index a426e063b9c..195e8f17738 100644 --- a/chain/actors/builtin/miner/miner.go +++ b/chain/actors/builtin/miner/miner.go @@ -29,6 +29,8 @@ import ( builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" ) func init() { @@ -49,9 +51,13 @@ func init() { return load4(store, root) }) + builtin.RegisterActorState(builtin5.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load5(store, root) + }) + } -var Methods = builtin4.MethodsMiner +var Methods = builtin5.MethodsMiner // Unchanged between v0, v2, v3, and v4 actors var WPoStProvingPeriod = miner0.WPoStProvingPeriod @@ -82,6 +88,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin4.StorageMinerActorCodeID: return load4(store, act.Head) + case builtin5.StorageMinerActorCodeID: + return load5(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/builtin/miner/v5.go b/chain/actors/builtin/miner/v5.go new file mode 100644 index 00000000000..eea00b6e9e4 --- /dev/null +++ b/chain/actors/builtin/miner/v5.go @@ -0,0 +1,445 @@ +package miner + +import ( + "bytes" + "errors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-bitfield" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/dline" + "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" + + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + + miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner" + adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" +) + +var _ State = (*state5)(nil) + +func load5(store adt.Store, root cid.Cid) (State, error) { + out := state5{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state5 struct { + miner5.State + store adt.Store +} + +type deadline5 struct { + miner5.Deadline + store adt.Store +} + +type partition5 struct { + miner5.Partition + store adt.Store +} + +func (s *state5) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmount, err error) { + defer func() { + if r := recover(); r != nil { + err = xerrors.Errorf("failed to get available balance: %w", r) + available = abi.NewTokenAmount(0) + } + }() + // this panics if the miner doesnt have enough funds to cover their locked pledge + available, err = s.GetAvailableBalance(bal) + return available, err +} + +func (s *state5) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) { + return s.CheckVestedFunds(s.store, epoch) +} + +func (s *state5) LockedFunds() (LockedFunds, error) { + return LockedFunds{ + VestingFunds: s.State.LockedFunds, + InitialPledgeRequirement: s.State.InitialPledge, + PreCommitDeposits: s.State.PreCommitDeposits, + }, nil +} + +func (s *state5) FeeDebt() (abi.TokenAmount, error) { + return s.State.FeeDebt, nil +} + +func (s *state5) InitialPledge() (abi.TokenAmount, error) { + return s.State.InitialPledge, nil +} + +func (s *state5) PreCommitDeposits() (abi.TokenAmount, error) { + return s.State.PreCommitDeposits, nil +} + +func (s *state5) GetSector(num abi.SectorNumber) (*SectorOnChainInfo, error) { + info, ok, err := s.State.GetSector(s.store, num) + if !ok || err != nil { + return nil, err + } + + ret := fromV5SectorOnChainInfo(*info) + return &ret, nil +} + +func (s *state5) FindSector(num abi.SectorNumber) (*SectorLocation, error) { + dlIdx, partIdx, err := s.State.FindSector(s.store, num) + if err != nil { + return nil, err + } + return &SectorLocation{ + Deadline: dlIdx, + Partition: partIdx, + }, nil +} + +func (s *state5) NumLiveSectors() (uint64, error) { + dls, err := s.State.LoadDeadlines(s.store) + if err != nil { + return 0, err + } + var total uint64 + if err := dls.ForEach(s.store, func(dlIdx uint64, dl *miner5.Deadline) error { + total += dl.LiveSectors + return nil + }); err != nil { + return 0, err + } + return total, nil +} + +// GetSectorExpiration returns the effective expiration of the given sector. +// +// If the sector does not expire early, the Early expiration field is 0. +func (s *state5) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, error) { + dls, err := s.State.LoadDeadlines(s.store) + if err != nil { + return nil, err + } + // NOTE: this can be optimized significantly. + // 1. If the sector is non-faulty, it will either expire on-time (can be + // learned from the sector info), or in the next quantized expiration + // epoch (i.e., the first element in the partition's expiration queue. + // 2. If it's faulty, it will expire early within the first 14 entries + // of the expiration queue. + stopErr := errors.New("stop") + out := SectorExpiration{} + err = dls.ForEach(s.store, func(dlIdx uint64, dl *miner5.Deadline) error { + partitions, err := dl.PartitionsArray(s.store) + if err != nil { + return err + } + quant := s.State.QuantSpecForDeadline(dlIdx) + var part miner5.Partition + return partitions.ForEach(&part, func(partIdx int64) error { + if found, err := part.Sectors.IsSet(uint64(num)); err != nil { + return err + } else if !found { + return nil + } + if found, err := part.Terminated.IsSet(uint64(num)); err != nil { + return err + } else if found { + // already terminated + return stopErr + } + + q, err := miner5.LoadExpirationQueue(s.store, part.ExpirationsEpochs, quant, miner5.PartitionExpirationAmtBitwidth) + if err != nil { + return err + } + var exp miner5.ExpirationSet + return q.ForEach(&exp, func(epoch int64) error { + if early, err := exp.EarlySectors.IsSet(uint64(num)); err != nil { + return err + } else if early { + out.Early = abi.ChainEpoch(epoch) + return nil + } + if onTime, err := exp.OnTimeSectors.IsSet(uint64(num)); err != nil { + return err + } else if onTime { + out.OnTime = abi.ChainEpoch(epoch) + return stopErr + } + return nil + }) + }) + }) + if err == stopErr { + err = nil + } + if err != nil { + return nil, err + } + if out.Early == 0 && out.OnTime == 0 { + return nil, xerrors.Errorf("failed to find sector %d", num) + } + return &out, nil +} + +func (s *state5) GetPrecommittedSector(num abi.SectorNumber) (*SectorPreCommitOnChainInfo, error) { + info, ok, err := s.State.GetPrecommittedSector(s.store, num) + if !ok || err != nil { + return nil, err + } + + ret := fromV5SectorPreCommitOnChainInfo(*info) + + return &ret, nil +} + +func (s *state5) LoadSectors(snos *bitfield.BitField) ([]*SectorOnChainInfo, error) { + sectors, err := miner5.LoadSectors(s.store, s.State.Sectors) + if err != nil { + return nil, err + } + + // If no sector numbers are specified, load all. + if snos == nil { + infos := make([]*SectorOnChainInfo, 0, sectors.Length()) + var info5 miner5.SectorOnChainInfo + if err := sectors.ForEach(&info5, func(_ int64) error { + info := fromV5SectorOnChainInfo(info5) + infos = append(infos, &info) + return nil + }); err != nil { + return nil, err + } + return infos, nil + } + + // Otherwise, load selected. + infos5, err := sectors.Load(*snos) + if err != nil { + return nil, err + } + infos := make([]*SectorOnChainInfo, len(infos5)) + for i, info5 := range infos5 { + info := fromV5SectorOnChainInfo(*info5) + infos[i] = &info + } + return infos, nil +} + +func (s *state5) IsAllocated(num abi.SectorNumber) (bool, error) { + var allocatedSectors bitfield.BitField + if err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors); err != nil { + return false, err + } + + return allocatedSectors.IsSet(uint64(num)) +} + +func (s *state5) LoadDeadline(idx uint64) (Deadline, error) { + dls, err := s.State.LoadDeadlines(s.store) + if err != nil { + return nil, err + } + dl, err := dls.LoadDeadline(s.store, idx) + if err != nil { + return nil, err + } + return &deadline5{*dl, s.store}, nil +} + +func (s *state5) ForEachDeadline(cb func(uint64, Deadline) error) error { + dls, err := s.State.LoadDeadlines(s.store) + if err != nil { + return err + } + return dls.ForEach(s.store, func(i uint64, dl *miner5.Deadline) error { + return cb(i, &deadline5{*dl, s.store}) + }) +} + +func (s *state5) NumDeadlines() (uint64, error) { + return miner5.WPoStPeriodDeadlines, nil +} + +func (s *state5) DeadlinesChanged(other State) (bool, error) { + other5, ok := other.(*state5) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + + return !s.State.Deadlines.Equals(other5.Deadlines), nil +} + +func (s *state5) MinerInfoChanged(other State) (bool, error) { + other0, ok := other.(*state5) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + return !s.State.Info.Equals(other0.State.Info), nil +} + +func (s *state5) Info() (MinerInfo, error) { + info, err := s.State.GetInfo(s.store) + if err != nil { + return MinerInfo{}, err + } + + var pid *peer.ID + if peerID, err := peer.IDFromBytes(info.PeerId); err == nil { + pid = &peerID + } + + mi := MinerInfo{ + Owner: info.Owner, + Worker: info.Worker, + ControlAddresses: info.ControlAddresses, + + NewWorker: address.Undef, + WorkerChangeEpoch: -1, + + PeerId: pid, + Multiaddrs: info.Multiaddrs, + WindowPoStProofType: info.WindowPoStProofType, + SectorSize: info.SectorSize, + WindowPoStPartitionSectors: info.WindowPoStPartitionSectors, + ConsensusFaultElapsed: info.ConsensusFaultElapsed, + } + + if info.PendingWorkerKey != nil { + mi.NewWorker = info.PendingWorkerKey.NewWorker + mi.WorkerChangeEpoch = info.PendingWorkerKey.EffectiveAt + } + + return mi, nil +} + +func (s *state5) DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error) { + return s.State.RecordedDeadlineInfo(epoch), nil +} + +func (s *state5) DeadlineCronActive() (bool, error) { + return s.State.DeadlineCronActive, nil +} + +func (s *state5) sectors() (adt.Array, error) { + return adt5.AsArray(s.store, s.Sectors, miner5.SectorsAmtBitwidth) +} + +func (s *state5) decodeSectorOnChainInfo(val *cbg.Deferred) (SectorOnChainInfo, error) { + var si miner5.SectorOnChainInfo + err := si.UnmarshalCBOR(bytes.NewReader(val.Raw)) + if err != nil { + return SectorOnChainInfo{}, err + } + + return fromV5SectorOnChainInfo(si), nil +} + +func (s *state5) precommits() (adt.Map, error) { + return adt5.AsMap(s.store, s.PreCommittedSectors, builtin5.DefaultHamtBitwidth) +} + +func (s *state5) decodeSectorPreCommitOnChainInfo(val *cbg.Deferred) (SectorPreCommitOnChainInfo, error) { + var sp miner5.SectorPreCommitOnChainInfo + err := sp.UnmarshalCBOR(bytes.NewReader(val.Raw)) + if err != nil { + return SectorPreCommitOnChainInfo{}, err + } + + return fromV5SectorPreCommitOnChainInfo(sp), nil +} + +func (d *deadline5) LoadPartition(idx uint64) (Partition, error) { + p, err := d.Deadline.LoadPartition(d.store, idx) + if err != nil { + return nil, err + } + return &partition5{*p, d.store}, nil +} + +func (d *deadline5) ForEachPartition(cb func(uint64, Partition) error) error { + ps, err := d.Deadline.PartitionsArray(d.store) + if err != nil { + return err + } + var part miner5.Partition + return ps.ForEach(&part, func(i int64) error { + return cb(uint64(i), &partition5{part, d.store}) + }) +} + +func (d *deadline5) PartitionsChanged(other Deadline) (bool, error) { + other5, ok := other.(*deadline5) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + + return !d.Deadline.Partitions.Equals(other5.Deadline.Partitions), nil +} + +func (d *deadline5) PartitionsPoSted() (bitfield.BitField, error) { + return d.Deadline.PartitionsPoSted, nil +} + +func (d *deadline5) DisputableProofCount() (uint64, error) { + + ops, err := d.OptimisticProofsSnapshotArray(d.store) + if err != nil { + return 0, err + } + + return ops.Length(), nil + +} + +func (p *partition5) AllSectors() (bitfield.BitField, error) { + return p.Partition.Sectors, nil +} + +func (p *partition5) FaultySectors() (bitfield.BitField, error) { + return p.Partition.Faults, nil +} + +func (p *partition5) RecoveringSectors() (bitfield.BitField, error) { + return p.Partition.Recoveries, nil +} + +func fromV5SectorOnChainInfo(v5 miner5.SectorOnChainInfo) SectorOnChainInfo { + + return SectorOnChainInfo{ + SectorNumber: v5.SectorNumber, + SealProof: v5.SealProof, + SealedCID: v5.SealedCID, + DealIDs: v5.DealIDs, + Activation: v5.Activation, + Expiration: v5.Expiration, + DealWeight: v5.DealWeight, + VerifiedDealWeight: v5.VerifiedDealWeight, + InitialPledge: v5.InitialPledge, + ExpectedDayReward: v5.ExpectedDayReward, + ExpectedStoragePledge: v5.ExpectedStoragePledge, + } + +} + +func fromV5SectorPreCommitOnChainInfo(v5 miner5.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { + + return SectorPreCommitOnChainInfo{ + Info: (SectorPreCommitInfo)(v5.Info), + PreCommitDeposit: v5.PreCommitDeposit, + PreCommitEpoch: v5.PreCommitEpoch, + DealWeight: v5.DealWeight, + VerifiedDealWeight: v5.VerifiedDealWeight, + } + +} diff --git a/chain/actors/builtin/multisig/actor.go.template b/chain/actors/builtin/multisig/actor.go.template index 304c0610c53..f741eba936e 100644 --- a/chain/actors/builtin/multisig/actor.go.template +++ b/chain/actors/builtin/multisig/actor.go.template @@ -13,7 +13,7 @@ import ( "github.com/ipfs/go-cid" msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" - msig4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/multisig" + msig{{.latestVersion}} "github.com/filecoin-project/specs-actors{{import .latestVersion}}actors/builtin/multisig" {{range .versions}} builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin" {{end}} @@ -95,7 +95,7 @@ type ProposeReturn = msig{{.latestVersion}}.ProposeReturn type ProposeParams = msig{{.latestVersion}}.ProposeParams func txnParams(id uint64, data *ProposalHashData) ([]byte, error) { - params := msig{{.latestVersion}}.TxnIDParams{ID: msig4.TxnID(id)} + params := msig{{.latestVersion}}.TxnIDParams{ID: msig{{.latestVersion}}.TxnID(id)} if data != nil { if data.Requester.Protocol() != address.ID { return nil, xerrors.Errorf("proposer address must be an ID address, was %s", data.Requester) diff --git a/chain/actors/builtin/multisig/message5.go b/chain/actors/builtin/multisig/message5.go new file mode 100644 index 00000000000..9a8110f2cd5 --- /dev/null +++ b/chain/actors/builtin/multisig/message5.go @@ -0,0 +1,71 @@ +package multisig + +import ( + "golang.org/x/xerrors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + init5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/init" + multisig5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/multisig" + + "github.com/filecoin-project/lotus/chain/actors" + init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init" + "github.com/filecoin-project/lotus/chain/types" +) + +type message5 struct{ message0 } + +func (m message5) Create( + signers []address.Address, threshold uint64, + unlockStart, unlockDuration abi.ChainEpoch, + initialAmount abi.TokenAmount, +) (*types.Message, error) { + + lenAddrs := uint64(len(signers)) + + if lenAddrs < threshold { + return nil, xerrors.Errorf("cannot require signing of more addresses than provided for multisig") + } + + if threshold == 0 { + threshold = lenAddrs + } + + if m.from == address.Undef { + return nil, xerrors.Errorf("must provide source address") + } + + // Set up constructor parameters for multisig + msigParams := &multisig5.ConstructorParams{ + Signers: signers, + NumApprovalsThreshold: threshold, + UnlockDuration: unlockDuration, + StartEpoch: unlockStart, + } + + enc, actErr := actors.SerializeParams(msigParams) + if actErr != nil { + return nil, actErr + } + + // new actors are created by invoking 'exec' on the init actor with the constructor params + execParams := &init5.ExecParams{ + CodeCID: builtin5.MultisigActorCodeID, + ConstructorParams: enc, + } + + enc, actErr = actors.SerializeParams(execParams) + if actErr != nil { + return nil, actErr + } + + return &types.Message{ + To: init_.Address, + From: m.from, + Method: builtin5.MethodsInit.Exec, + Params: enc, + Value: initialAmount, + }, nil +} diff --git a/chain/actors/builtin/multisig/multisig.go b/chain/actors/builtin/multisig/multisig.go index 79b1a57d7ba..eafd418e0ee 100644 --- a/chain/actors/builtin/multisig/multisig.go +++ b/chain/actors/builtin/multisig/multisig.go @@ -13,7 +13,7 @@ import ( "github.com/ipfs/go-cid" msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" - msig4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/multisig" + msig5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/multisig" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" @@ -23,6 +23,8 @@ import ( builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -46,6 +48,10 @@ func init() { builtin.RegisterActorState(builtin4.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load4(store, root) }) + + builtin.RegisterActorState(builtin5.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load5(store, root) + }) } func Load(store adt.Store, act *types.Actor) (State, error) { @@ -63,6 +69,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin4.MultisigActorCodeID: return load4(store, act.Head) + case builtin5.MultisigActorCodeID: + return load5(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } @@ -86,7 +95,7 @@ type State interface { type Transaction = msig0.Transaction -var Methods = builtin4.MethodsMultisig +var Methods = builtin5.MethodsMultisig func Message(version actors.Version, from address.Address) MessageBuilder { switch version { @@ -102,6 +111,9 @@ func Message(version actors.Version, from address.Address) MessageBuilder { case actors.Version4: return message4{message0{from}} + + case actors.Version5: + return message5{message0{from}} default: panic(fmt.Sprintf("unsupported actors version: %d", version)) } @@ -125,12 +137,12 @@ type MessageBuilder interface { } // this type is the same between v0 and v2 -type ProposalHashData = msig4.ProposalHashData -type ProposeReturn = msig4.ProposeReturn -type ProposeParams = msig4.ProposeParams +type ProposalHashData = msig5.ProposalHashData +type ProposeReturn = msig5.ProposeReturn +type ProposeParams = msig5.ProposeParams func txnParams(id uint64, data *ProposalHashData) ([]byte, error) { - params := msig4.TxnIDParams{ID: msig4.TxnID(id)} + params := msig5.TxnIDParams{ID: msig5.TxnID(id)} if data != nil { if data.Requester.Protocol() != address.ID { return nil, xerrors.Errorf("proposer address must be an ID address, was %s", data.Requester) diff --git a/chain/actors/builtin/multisig/v5.go b/chain/actors/builtin/multisig/v5.go new file mode 100644 index 00000000000..e879783badd --- /dev/null +++ b/chain/actors/builtin/multisig/v5.go @@ -0,0 +1,96 @@ +package multisig + +import ( + "bytes" + "encoding/binary" + + adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/chain/actors/adt" + + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + + msig5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/multisig" +) + +var _ State = (*state5)(nil) + +func load5(store adt.Store, root cid.Cid) (State, error) { + out := state5{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state5 struct { + msig5.State + store adt.Store +} + +func (s *state5) LockedBalance(currEpoch abi.ChainEpoch) (abi.TokenAmount, error) { + return s.State.AmountLocked(currEpoch - s.State.StartEpoch), nil +} + +func (s *state5) StartEpoch() (abi.ChainEpoch, error) { + return s.State.StartEpoch, nil +} + +func (s *state5) UnlockDuration() (abi.ChainEpoch, error) { + return s.State.UnlockDuration, nil +} + +func (s *state5) InitialBalance() (abi.TokenAmount, error) { + return s.State.InitialBalance, nil +} + +func (s *state5) Threshold() (uint64, error) { + return s.State.NumApprovalsThreshold, nil +} + +func (s *state5) Signers() ([]address.Address, error) { + return s.State.Signers, nil +} + +func (s *state5) ForEachPendingTxn(cb func(id int64, txn Transaction) error) error { + arr, err := adt5.AsMap(s.store, s.State.PendingTxns, builtin5.DefaultHamtBitwidth) + if err != nil { + return err + } + var out msig5.Transaction + return arr.ForEach(&out, func(key string) error { + txid, n := binary.Varint([]byte(key)) + if n <= 0 { + return xerrors.Errorf("invalid pending transaction key: %v", key) + } + return cb(txid, (Transaction)(out)) //nolint:unconvert + }) +} + +func (s *state5) PendingTxnChanged(other State) (bool, error) { + other5, ok := other.(*state5) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + return !s.State.PendingTxns.Equals(other5.PendingTxns), nil +} + +func (s *state5) transactions() (adt.Map, error) { + return adt5.AsMap(s.store, s.PendingTxns, builtin5.DefaultHamtBitwidth) +} + +func (s *state5) decodeTransaction(val *cbg.Deferred) (Transaction, error) { + var tx msig5.Transaction + if err := tx.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return Transaction{}, err + } + return tx, nil +} diff --git a/chain/actors/builtin/paych/message5.go b/chain/actors/builtin/paych/message5.go new file mode 100644 index 00000000000..37a2b6f04af --- /dev/null +++ b/chain/actors/builtin/paych/message5.go @@ -0,0 +1,74 @@ +package paych + +import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + init5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/init" + paych5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/paych" + + "github.com/filecoin-project/lotus/chain/actors" + init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init" + "github.com/filecoin-project/lotus/chain/types" +) + +type message5 struct{ from address.Address } + +func (m message5) Create(to address.Address, initialAmount abi.TokenAmount) (*types.Message, error) { + params, aerr := actors.SerializeParams(&paych5.ConstructorParams{From: m.from, To: to}) + if aerr != nil { + return nil, aerr + } + enc, aerr := actors.SerializeParams(&init5.ExecParams{ + CodeCID: builtin5.PaymentChannelActorCodeID, + ConstructorParams: params, + }) + if aerr != nil { + return nil, aerr + } + + return &types.Message{ + To: init_.Address, + From: m.from, + Value: initialAmount, + Method: builtin5.MethodsInit.Exec, + Params: enc, + }, nil +} + +func (m message5) Update(paych address.Address, sv *SignedVoucher, secret []byte) (*types.Message, error) { + params, aerr := actors.SerializeParams(&paych5.UpdateChannelStateParams{ + Sv: *sv, + Secret: secret, + }) + if aerr != nil { + return nil, aerr + } + + return &types.Message{ + To: paych, + From: m.from, + Value: abi.NewTokenAmount(0), + Method: builtin5.MethodsPaych.UpdateChannelState, + Params: params, + }, nil +} + +func (m message5) Settle(paych address.Address) (*types.Message, error) { + return &types.Message{ + To: paych, + From: m.from, + Value: abi.NewTokenAmount(0), + Method: builtin5.MethodsPaych.Settle, + }, nil +} + +func (m message5) Collect(paych address.Address) (*types.Message, error) { + return &types.Message{ + To: paych, + From: m.from, + Value: abi.NewTokenAmount(0), + Method: builtin5.MethodsPaych.Collect, + }, nil +} diff --git a/chain/actors/builtin/paych/paych.go b/chain/actors/builtin/paych/paych.go index 30e4408d8fe..bafd6e94dee 100644 --- a/chain/actors/builtin/paych/paych.go +++ b/chain/actors/builtin/paych/paych.go @@ -23,6 +23,8 @@ import ( builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -46,6 +48,10 @@ func init() { builtin.RegisterActorState(builtin4.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load4(store, root) }) + + builtin.RegisterActorState(builtin5.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load5(store, root) + }) } // Load returns an abstract copy of payment channel state, irregardless of actor version @@ -64,6 +70,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin4.PaymentChannelActorCodeID: return load4(store, act.Head) + case builtin5.PaymentChannelActorCodeID: + return load5(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } @@ -114,7 +123,7 @@ func DecodeSignedVoucher(s string) (*SignedVoucher, error) { return &sv, nil } -var Methods = builtin4.MethodsPaych +var Methods = builtin5.MethodsPaych func Message(version actors.Version, from address.Address) MessageBuilder { switch version { @@ -131,6 +140,9 @@ func Message(version actors.Version, from address.Address) MessageBuilder { case actors.Version4: return message4{from} + case actors.Version5: + return message5{from} + default: panic(fmt.Sprintf("unsupported actors version: %d", version)) } diff --git a/chain/actors/builtin/paych/v5.go b/chain/actors/builtin/paych/v5.go new file mode 100644 index 00000000000..f878d858cb4 --- /dev/null +++ b/chain/actors/builtin/paych/v5.go @@ -0,0 +1,104 @@ +package paych + +import ( + "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" + + "github.com/filecoin-project/lotus/chain/actors/adt" + + paych5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/paych" + adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" +) + +var _ State = (*state5)(nil) + +func load5(store adt.Store, root cid.Cid) (State, error) { + out := state5{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state5 struct { + paych5.State + store adt.Store + lsAmt *adt5.Array +} + +// Channel owner, who has funded the actor +func (s *state5) From() (address.Address, error) { + return s.State.From, nil +} + +// Recipient of payouts from channel +func (s *state5) To() (address.Address, error) { + return s.State.To, nil +} + +// Height at which the channel can be `Collected` +func (s *state5) SettlingAt() (abi.ChainEpoch, error) { + return s.State.SettlingAt, nil +} + +// Amount successfully redeemed through the payment channel, paid out on `Collect()` +func (s *state5) ToSend() (abi.TokenAmount, error) { + return s.State.ToSend, nil +} + +func (s *state5) getOrLoadLsAmt() (*adt5.Array, error) { + if s.lsAmt != nil { + return s.lsAmt, nil + } + + // Get the lane state from the chain + lsamt, err := adt5.AsArray(s.store, s.State.LaneStates, paych5.LaneStatesAmtBitwidth) + if err != nil { + return nil, err + } + + s.lsAmt = lsamt + return lsamt, nil +} + +// Get total number of lanes +func (s *state5) LaneCount() (uint64, error) { + lsamt, err := s.getOrLoadLsAmt() + if err != nil { + return 0, err + } + return lsamt.Length(), nil +} + +// Iterate lane states +func (s *state5) ForEachLaneState(cb func(idx uint64, dl LaneState) error) error { + // Get the lane state from the chain + lsamt, err := s.getOrLoadLsAmt() + if err != nil { + return err + } + + // Note: we use a map instead of an array to store laneStates because the + // client sets the lane ID (the index) and potentially they could use a + // very large index. + var ls paych5.LaneState + return lsamt.ForEach(&ls, func(i int64) error { + return cb(uint64(i), &laneState5{ls}) + }) +} + +type laneState5 struct { + paych5.LaneState +} + +func (ls *laneState5) Redeemed() (big.Int, error) { + return ls.LaneState.Redeemed, nil +} + +func (ls *laneState5) Nonce() (uint64, error) { + return ls.LaneState.Nonce, nil +} diff --git a/chain/actors/builtin/power/power.go b/chain/actors/builtin/power/power.go index bf530a21a60..2cf59ef021c 100644 --- a/chain/actors/builtin/power/power.go +++ b/chain/actors/builtin/power/power.go @@ -21,6 +21,8 @@ import ( builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" ) func init() { @@ -40,11 +42,15 @@ func init() { builtin.RegisterActorState(builtin4.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load4(store, root) }) + + builtin.RegisterActorState(builtin5.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load5(store, root) + }) } var ( - Address = builtin4.StoragePowerActorAddr - Methods = builtin4.MethodsPower + Address = builtin5.StoragePowerActorAddr + Methods = builtin5.MethodsPower ) func Load(store adt.Store, act *types.Actor) (State, error) { @@ -62,6 +68,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin4.StoragePowerActorCodeID: return load4(store, act.Head) + case builtin5.StoragePowerActorCodeID: + return load5(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/builtin/power/v5.go b/chain/actors/builtin/power/v5.go new file mode 100644 index 00000000000..33a5d3b62c0 --- /dev/null +++ b/chain/actors/builtin/power/v5.go @@ -0,0 +1,150 @@ +package power + +import ( + "bytes" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + + power5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/power" + adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" +) + +var _ State = (*state5)(nil) + +func load5(store adt.Store, root cid.Cid) (State, error) { + out := state5{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state5 struct { + power5.State + store adt.Store +} + +func (s *state5) TotalLocked() (abi.TokenAmount, error) { + return s.TotalPledgeCollateral, nil +} + +func (s *state5) TotalPower() (Claim, error) { + return Claim{ + RawBytePower: s.TotalRawBytePower, + QualityAdjPower: s.TotalQualityAdjPower, + }, nil +} + +// Committed power to the network. Includes miners below the minimum threshold. +func (s *state5) TotalCommitted() (Claim, error) { + return Claim{ + RawBytePower: s.TotalBytesCommitted, + QualityAdjPower: s.TotalQABytesCommitted, + }, nil +} + +func (s *state5) MinerPower(addr address.Address) (Claim, bool, error) { + claims, err := s.claims() + if err != nil { + return Claim{}, false, err + } + var claim power5.Claim + ok, err := claims.Get(abi.AddrKey(addr), &claim) + if err != nil { + return Claim{}, false, err + } + return Claim{ + RawBytePower: claim.RawBytePower, + QualityAdjPower: claim.QualityAdjPower, + }, ok, nil +} + +func (s *state5) MinerNominalPowerMeetsConsensusMinimum(a address.Address) (bool, error) { + return s.State.MinerNominalPowerMeetsConsensusMinimum(s.store, a) +} + +func (s *state5) TotalPowerSmoothed() (builtin.FilterEstimate, error) { + return builtin.FromV5FilterEstimate(s.State.ThisEpochQAPowerSmoothed), nil +} + +func (s *state5) MinerCounts() (uint64, uint64, error) { + return uint64(s.State.MinerAboveMinPowerCount), uint64(s.State.MinerCount), nil +} + +func (s *state5) ListAllMiners() ([]address.Address, error) { + claims, err := s.claims() + if err != nil { + return nil, err + } + + var miners []address.Address + err = claims.ForEach(nil, func(k string) error { + a, err := address.NewFromBytes([]byte(k)) + if err != nil { + return err + } + miners = append(miners, a) + return nil + }) + if err != nil { + return nil, err + } + + return miners, nil +} + +func (s *state5) ForEachClaim(cb func(miner address.Address, claim Claim) error) error { + claims, err := s.claims() + if err != nil { + return err + } + + var claim power5.Claim + return claims.ForEach(&claim, func(k string) error { + a, err := address.NewFromBytes([]byte(k)) + if err != nil { + return err + } + return cb(a, Claim{ + RawBytePower: claim.RawBytePower, + QualityAdjPower: claim.QualityAdjPower, + }) + }) +} + +func (s *state5) ClaimsChanged(other State) (bool, error) { + other5, ok := other.(*state5) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + return !s.State.Claims.Equals(other5.State.Claims), nil +} + +func (s *state5) claims() (adt.Map, error) { + return adt5.AsMap(s.store, s.Claims, builtin5.DefaultHamtBitwidth) +} + +func (s *state5) decodeClaim(val *cbg.Deferred) (Claim, error) { + var ci power5.Claim + if err := ci.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return Claim{}, err + } + return fromV5Claim(ci), nil +} + +func fromV5Claim(v5 power5.Claim) Claim { + return Claim{ + RawBytePower: v5.RawBytePower, + QualityAdjPower: v5.QualityAdjPower, + } +} diff --git a/chain/actors/builtin/reward/reward.go b/chain/actors/builtin/reward/reward.go index 1037cf7412c..5f6131334d9 100644 --- a/chain/actors/builtin/reward/reward.go +++ b/chain/actors/builtin/reward/reward.go @@ -16,6 +16,8 @@ import ( builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/types" @@ -38,11 +40,15 @@ func init() { builtin.RegisterActorState(builtin4.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load4(store, root) }) + + builtin.RegisterActorState(builtin5.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load5(store, root) + }) } var ( - Address = builtin4.RewardActorAddr - Methods = builtin4.MethodsReward + Address = builtin5.RewardActorAddr + Methods = builtin5.MethodsReward ) func Load(store adt.Store, act *types.Actor) (State, error) { @@ -60,6 +66,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin4.RewardActorCodeID: return load4(store, act.Head) + case builtin5.RewardActorCodeID: + return load5(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/builtin/reward/v5.go b/chain/actors/builtin/reward/v5.go new file mode 100644 index 00000000000..0dd75de735e --- /dev/null +++ b/chain/actors/builtin/reward/v5.go @@ -0,0 +1,88 @@ +package reward + +import ( + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + + miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner" + reward5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/reward" + smoothing5 "github.com/filecoin-project/specs-actors/v5/actors/util/smoothing" +) + +var _ State = (*state5)(nil) + +func load5(store adt.Store, root cid.Cid) (State, error) { + out := state5{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state5 struct { + reward5.State + store adt.Store +} + +func (s *state5) ThisEpochReward() (abi.TokenAmount, error) { + return s.State.ThisEpochReward, nil +} + +func (s *state5) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) { + + return builtin.FilterEstimate{ + PositionEstimate: s.State.ThisEpochRewardSmoothed.PositionEstimate, + VelocityEstimate: s.State.ThisEpochRewardSmoothed.VelocityEstimate, + }, nil + +} + +func (s *state5) ThisEpochBaselinePower() (abi.StoragePower, error) { + return s.State.ThisEpochBaselinePower, nil +} + +func (s *state5) TotalStoragePowerReward() (abi.TokenAmount, error) { + return s.State.TotalStoragePowerReward, nil +} + +func (s *state5) EffectiveBaselinePower() (abi.StoragePower, error) { + return s.State.EffectiveBaselinePower, nil +} + +func (s *state5) EffectiveNetworkTime() (abi.ChainEpoch, error) { + return s.State.EffectiveNetworkTime, nil +} + +func (s *state5) CumsumBaseline() (reward5.Spacetime, error) { + return s.State.CumsumBaseline, nil +} + +func (s *state5) CumsumRealized() (reward5.Spacetime, error) { + return s.State.CumsumRealized, nil +} + +func (s *state5) InitialPledgeForPower(qaPower abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) { + return miner5.InitialPledgeForPower( + qaPower, + s.State.ThisEpochBaselinePower, + s.State.ThisEpochRewardSmoothed, + smoothing5.FilterEstimate{ + PositionEstimate: networkQAPower.PositionEstimate, + VelocityEstimate: networkQAPower.VelocityEstimate, + }, + circSupply, + ), nil +} + +func (s *state5) PreCommitDepositForPower(networkQAPower builtin.FilterEstimate, sectorWeight abi.StoragePower) (abi.TokenAmount, error) { + return miner5.PreCommitDepositForPower(s.State.ThisEpochRewardSmoothed, + smoothing5.FilterEstimate{ + PositionEstimate: networkQAPower.PositionEstimate, + VelocityEstimate: networkQAPower.VelocityEstimate, + }, + sectorWeight), nil +} diff --git a/chain/actors/builtin/verifreg/v5.go b/chain/actors/builtin/verifreg/v5.go new file mode 100644 index 00000000000..367d38498eb --- /dev/null +++ b/chain/actors/builtin/verifreg/v5.go @@ -0,0 +1,58 @@ +package verifreg + +import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/actors/adt" + + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + verifreg5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/verifreg" + adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" +) + +var _ State = (*state5)(nil) + +func load5(store adt.Store, root cid.Cid) (State, error) { + out := state5{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state5 struct { + verifreg5.State + store adt.Store +} + +func (s *state5) RootKey() (address.Address, error) { + return s.State.RootKey, nil +} + +func (s *state5) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) { + return getDataCap(s.store, actors.Version5, s.verifiedClients, addr) +} + +func (s *state5) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) { + return getDataCap(s.store, actors.Version5, s.verifiers, addr) +} + +func (s *state5) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { + return forEachCap(s.store, actors.Version5, s.verifiers, cb) +} + +func (s *state5) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error { + return forEachCap(s.store, actors.Version5, s.verifiedClients, cb) +} + +func (s *state5) verifiedClients() (adt.Map, error) { + return adt5.AsMap(s.store, s.VerifiedClients, builtin5.DefaultHamtBitwidth) +} + +func (s *state5) verifiers() (adt.Map, error) { + return adt5.AsMap(s.store, s.Verifiers, builtin5.DefaultHamtBitwidth) +} diff --git a/chain/actors/builtin/verifreg/verifreg.go b/chain/actors/builtin/verifreg/verifreg.go index 32f50a4ae32..baca6617775 100644 --- a/chain/actors/builtin/verifreg/verifreg.go +++ b/chain/actors/builtin/verifreg/verifreg.go @@ -17,6 +17,8 @@ import ( builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/types" @@ -40,11 +42,15 @@ func init() { return load4(store, root) }) + builtin.RegisterActorState(builtin5.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load5(store, root) + }) + } var ( - Address = builtin4.VerifiedRegistryActorAddr - Methods = builtin4.MethodsVerifiedRegistry + Address = builtin5.VerifiedRegistryActorAddr + Methods = builtin5.MethodsVerifiedRegistry ) func Load(store adt.Store, act *types.Actor) (State, error) { @@ -62,6 +68,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin4.VerifiedRegistryActorCodeID: return load4(store, act.Head) + case builtin5.VerifiedRegistryActorCodeID: + return load5(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/policy/policy.go b/chain/actors/policy/policy.go index 164f19a76f2..191ffb5f5ad 100644 --- a/chain/actors/policy/policy.go +++ b/chain/actors/policy/policy.go @@ -27,14 +27,19 @@ import ( miner4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner" verifreg4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg" - paych4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/paych" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + market5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/market" + miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner" + verifreg5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/verifreg" + + paych5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/paych" ) const ( - ChainFinality = miner4.ChainFinality + ChainFinality = miner5.ChainFinality SealRandomnessLookback = ChainFinality - PaychSettleDelay = paych4.SettleDelay - MaxPreCommitRandomnessLookback = builtin4.EpochsInDay + SealRandomnessLookback + PaychSettleDelay = paych5.SettleDelay + MaxPreCommitRandomnessLookback = builtin5.EpochsInDay + SealRandomnessLookback ) // SetSupportedProofTypes sets supported proof types, across all actor versions. @@ -55,6 +60,10 @@ func SetSupportedProofTypes(types ...abi.RegisteredSealProof) { miner4.PreCommitSealProofTypesV7 = make(map[abi.RegisteredSealProof]struct{}, len(types)*2) miner4.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types)) + miner5.PreCommitSealProofTypesV0 = make(map[abi.RegisteredSealProof]struct{}, len(types)) + miner5.PreCommitSealProofTypesV7 = make(map[abi.RegisteredSealProof]struct{}, len(types)*2) + miner5.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types)) + AddSupportedProofTypes(types...) } @@ -84,6 +93,11 @@ func AddSupportedProofTypes(types ...abi.RegisteredSealProof) { miner4.PreCommitSealProofTypesV7[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{} miner4.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{} + miner5.PreCommitSealProofTypesV0[t] = struct{}{} + miner5.PreCommitSealProofTypesV7[t] = struct{}{} + miner5.PreCommitSealProofTypesV7[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{} + miner5.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{} + } } @@ -100,11 +114,13 @@ func SetPreCommitChallengeDelay(delay abi.ChainEpoch) { miner4.PreCommitChallengeDelay = delay + miner5.PreCommitChallengeDelay = delay + } // TODO: this function shouldn't really exist. Instead, the API should expose the precommit delay. func GetPreCommitChallengeDelay() abi.ChainEpoch { - return miner4.PreCommitChallengeDelay + return miner5.PreCommitChallengeDelay } // SetConsensusMinerMinPower sets the minimum power of an individual miner must @@ -126,6 +142,10 @@ func SetConsensusMinerMinPower(p abi.StoragePower) { policy.ConsensusMinerMinPower = p } + for _, policy := range builtin5.PoStProofPolicies { + policy.ConsensusMinerMinPower = p + } + } // SetMinVerifiedDealSize sets the minimum size of a verified deal. This should @@ -140,6 +160,8 @@ func SetMinVerifiedDealSize(size abi.StoragePower) { verifreg4.MinVerifiedDealSize = size + verifreg5.MinVerifiedDealSize = size + } func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) abi.ChainEpoch { @@ -161,6 +183,10 @@ func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) ab return miner4.MaxProveCommitDuration[t] + case actors.Version5: + + return miner5.MaxProveCommitDuration[t] + default: panic("unsupported actors version") } @@ -189,13 +215,17 @@ func DealProviderCollateralBounds( return market4.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil) + case actors.Version5: + + return market5.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil) + default: panic("unsupported actors version") } } func DealDurationBounds(pieceSize abi.PaddedPieceSize) (min, max abi.ChainEpoch) { - return market4.DealDurationBounds(pieceSize) + return market5.DealDurationBounds(pieceSize) } // Sets the challenge window and scales the proving period to match (such that @@ -222,6 +252,13 @@ func SetWPoStChallengeWindow(period abi.ChainEpoch) { // scale it if we're scaling the challenge period. miner4.WPoStDisputeWindow = period * 30 + miner5.WPoStChallengeWindow = period + miner5.WPoStProvingPeriod = period * abi.ChainEpoch(miner5.WPoStPeriodDeadlines) + + // by default, this is 2x finality which is 30 periods. + // scale it if we're scaling the challenge period. + miner5.WPoStDisputeWindow = period * 30 + } func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch { @@ -234,22 +271,22 @@ func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch { } func GetMaxSectorExpirationExtension() abi.ChainEpoch { - return miner4.MaxSectorExpirationExtension + return miner5.MaxSectorExpirationExtension } // TODO: we'll probably need to abstract over this better in the future. func GetMaxPoStPartitions(p abi.RegisteredPoStProof) (int, error) { - sectorsPerPart, err := builtin4.PoStProofWindowPoStPartitionSectors(p) + sectorsPerPart, err := builtin5.PoStProofWindowPoStPartitionSectors(p) if err != nil { return 0, err } - return int(miner4.AddressedSectorsMax / sectorsPerPart), nil + return int(miner5.AddressedSectorsMax / sectorsPerPart), nil } func GetDefaultSectorSize() abi.SectorSize { // supported sector sizes are the same across versions. - szs := make([]abi.SectorSize, 0, len(miner4.PreCommitSealProofTypesV8)) - for spt := range miner4.PreCommitSealProofTypesV8 { + szs := make([]abi.SectorSize, 0, len(miner5.PreCommitSealProofTypesV8)) + for spt := range miner5.PreCommitSealProofTypesV8 { ss, err := spt.SectorSize() if err != nil { panic(err) @@ -267,10 +304,10 @@ func GetDefaultSectorSize() abi.SectorSize { func GetSectorMaxLifetime(proof abi.RegisteredSealProof, nwVer network.Version) abi.ChainEpoch { if nwVer <= network.Version10 { - return builtin4.SealProofPoliciesV0[proof].SectorMaxLifetime + return builtin5.SealProofPoliciesV0[proof].SectorMaxLifetime } - return builtin4.SealProofPoliciesV11[proof].SectorMaxLifetime + return builtin5.SealProofPoliciesV11[proof].SectorMaxLifetime } func GetAddressedSectorsMax(nwVer network.Version) int { @@ -288,6 +325,9 @@ func GetAddressedSectorsMax(nwVer network.Version) int { case actors.Version4: return miner4.AddressedSectorsMax + case actors.Version5: + return miner5.AddressedSectorsMax + default: panic("unsupported network version") } @@ -313,6 +353,10 @@ func GetDeclarationsMax(nwVer network.Version) int { return miner4.DeclarationsMax + case actors.Version5: + + return miner5.DeclarationsMax + default: panic("unsupported network version") } diff --git a/chain/actors/version.go b/chain/actors/version.go index bd7b708bdcd..e6ca2e9bd9d 100644 --- a/chain/actors/version.go +++ b/chain/actors/version.go @@ -13,6 +13,7 @@ const ( Version2 Version = 2 Version3 Version = 3 Version4 Version = 4 + Version5 Version = 5 ) // Converts a network version into an actors adt version. @@ -26,6 +27,8 @@ func VersionForNetwork(version network.Version) Version { return Version3 case network.Version12: return Version4 + case network.Version13: + return Version5 default: panic(fmt.Sprintf("unsupported network version %d", version)) } diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go index a7b56f67997..357c22a7cfe 100644 --- a/chain/stmgr/forks.go +++ b/chain/stmgr/forks.go @@ -207,6 +207,10 @@ func DefaultUpgradeSchedule() UpgradeSchedule { StopWithin: 5, }}, Expensive: true, + }, { + Height: build.UpgradeHyperdriveHeight, + Network: network.Version13, + Migration: nil, }} for _, u := range updates { @@ -1053,7 +1057,7 @@ func upgradeActorsV3Common( // Perform the migration newHamtRoot, err := nv10.MigrateStateTree(ctx, store, stateRoot.Actors, epoch, config, migrationLogger{}, cache) if err != nil { - return cid.Undef, xerrors.Errorf("upgrading to actors v2: %w", err) + return cid.Undef, xerrors.Errorf("upgrading to actors v3: %w", err) } // Persist the result. @@ -1139,7 +1143,7 @@ func upgradeActorsV4Common( // Perform the migration newHamtRoot, err := nv12.MigrateStateTree(ctx, store, stateRoot.Actors, epoch, config, migrationLogger{}, cache) if err != nil { - return cid.Undef, xerrors.Errorf("upgrading to actors v2: %w", err) + return cid.Undef, xerrors.Errorf("upgrading to actors v4: %w", err) } // Persist the result. diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index be4b9cd4f4c..ce6d0bf2b37 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -9,6 +9,8 @@ import ( "runtime" "strings" + exported5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/exported" + "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/network" @@ -550,6 +552,7 @@ func init() { actors = append(actors, exported2.BuiltinActors()...) actors = append(actors, exported3.BuiltinActors()...) actors = append(actors, exported4.BuiltinActors()...) + actors = append(actors, exported5.BuiltinActors()...) for _, actor := range actors { exports := actor.Exports() diff --git a/chain/types/state.go b/chain/types/state.go index b561aab71e2..23061c15eb5 100644 --- a/chain/types/state.go +++ b/chain/types/state.go @@ -14,6 +14,8 @@ const ( // StateTreeVersion2 corresponds to actors v3. StateTreeVersion2 // StateTreeVersion3 corresponds to actors >= v4. + // TODO: The v3 -> v4 change actually did not need a state tree version bump + // We should be able to safely undo this, but will need some care StateTreeVersion3 ) diff --git a/chain/vm/invoker.go b/chain/vm/invoker.go index 8e0e6edd6e7..126b5709034 100644 --- a/chain/vm/invoker.go +++ b/chain/vm/invoker.go @@ -19,6 +19,7 @@ import ( vmr "github.com/filecoin-project/specs-actors/v2/actors/runtime" exported3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/exported" exported4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/exported" + exported5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/exported" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/exitcode" @@ -66,6 +67,7 @@ func NewActorRegistry() *ActorRegistry { inv.Register(ActorsVersionPredicate(actors.Version2), exported2.BuiltinActors()...) inv.Register(ActorsVersionPredicate(actors.Version3), exported3.BuiltinActors()...) inv.Register(ActorsVersionPredicate(actors.Version4), exported4.BuiltinActors()...) + inv.Register(ActorsVersionPredicate(actors.Version5), exported5.BuiltinActors()...) return inv } diff --git a/chain/vm/mkactor.go b/chain/vm/mkactor.go index 11de7362b52..669c1450f1a 100644 --- a/chain/vm/mkactor.go +++ b/chain/vm/mkactor.go @@ -18,6 +18,7 @@ import ( builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/chain/actors/aerrors" @@ -105,6 +106,8 @@ func newAccountActor(ver actors.Version) *types.Actor { code = builtin3.AccountActorCodeID case actors.Version4: code = builtin4.AccountActorCodeID + case actors.Version5: + code = builtin5.AccountActorCodeID default: panic("unsupported actors version") } diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 493fd7d2b8f..743432cb0ee 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -4517,7 +4517,7 @@ Inputs: ] ``` -Response: `11` +Response: `13` ### StateReadState StateReadState returns the indicated actor's state. diff --git a/go.mod b/go.mod index 86e6da40dc2..aede934c3e7 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( 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-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261 - github.com/filecoin-project/go-state-types v0.1.0 + github.com/filecoin-project/go-state-types v0.1.1-0.20210506134452-99b279731c48 github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe github.com/filecoin-project/go-statestore v0.1.1 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b @@ -47,6 +47,7 @@ require ( github.com/filecoin-project/specs-actors/v2 v2.3.5-0.20210114162132-5b58b773f4fb github.com/filecoin-project/specs-actors/v3 v3.1.0 github.com/filecoin-project/specs-actors/v4 v4.0.0 + github.com/filecoin-project/specs-actors/v5 v5.0.0-20210504172221-f6a8d2a6f157 github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 github.com/filecoin-project/test-vectors/schema v0.0.5 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 diff --git a/go.sum b/go.sum index 8bcfafdfc0b..fb9c4aac5dd 100644 --- a/go.sum +++ b/go.sum @@ -295,6 +295,8 @@ github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.0 h1:9r2HCSMMCmyMfGyMKxQtv0GKp6VT/m5GgVk8EhYbLJU= github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= +github.com/filecoin-project/go-state-types v0.1.1-0.20210506134452-99b279731c48 h1:Jc4OprDp3bRDxbsrXNHPwJabZJM3iDy+ri8/1e0ZnX4= +github.com/filecoin-project/go-state-types v0.1.1-0.20210506134452-99b279731c48/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statestore v0.1.0/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI= @@ -314,6 +316,8 @@ github.com/filecoin-project/specs-actors/v3 v3.1.0 h1:s4qiPw8pgypqBGAy853u/zdZJ7 github.com/filecoin-project/specs-actors/v3 v3.1.0/go.mod h1:mpynccOLlIRy0QnR008BwYBwT9fen+sPR13MA1VmMww= github.com/filecoin-project/specs-actors/v4 v4.0.0 h1:vMALksY5G3J5rj3q9rbcyB+f4Tk1xrLqSgdB3jOok4s= github.com/filecoin-project/specs-actors/v4 v4.0.0/go.mod h1:TkHXf/l7Wyw4ZejyXIPS2rK8bBO0rdwhTZyQQgaglng= +github.com/filecoin-project/specs-actors/v5 v5.0.0-20210504172221-f6a8d2a6f157 h1:14bRnM75i55IyoanGghulx3uaDxFnvXOGFWaDZwk3Bc= +github.com/filecoin-project/specs-actors/v5 v5.0.0-20210504172221-f6a8d2a6f157/go.mod h1:qXv7oUdv/qeFfiiip/YYOj67373nxKypM17AbM8LZmw= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 h1:Ur/l2+6qN+lQiqjozWWc5p9UDaAMDZKTlDS98oRnlIw= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg=