Merge branch 'release/v1.12.0' into jen/12tomaster

This commit is contained in:
Jennifer Wang 2021-10-04 02:08:35 -04:00
commit 38e01cba83
113 changed files with 3928 additions and 607 deletions

View File

@ -1,5 +1,61 @@
# Lotus changelog
# v1.12.0-rc1 / 2021-10-01
This is the first release candidate for lotus v1.11.3. Changelog will be updated later.
## Changelog
- github.com/filecoin-project/lotus:
- bump the version to v1.12.0-rc1
- Upgrade to actors v6-rc1
- Set Chocolate upgrade epoch for butterfly
- reset of the butterfly network
- reset butterfly network
- Precommit batch balancer support/config ([filecoin-project/lotus#7410](https://github.com/filecoin-project/lotus/pull/7410))
- Extend FaultMaxAge to 6 weeks for actors v6 on test networks only ([filecoin-project/lotus#7421](https://github.com/filecoin-project/lotus/pull/7421))
- Update to actors master ([filecoin-project/lotus#7404](https://github.com/filecoin-project/lotus/pull/7404))
- Fix Drand fetching around null tipsets ([filecoin-project/lotus#7376](https://github.com/filecoin-project/lotus/pull/7376))
- ChainStore: Add a tiebreaker rule for tipsets of equal weight ([filecoin-project/lotus#7378](https://github.com/filecoin-project/lotus/pull/7378))
- Sync: Sanity check msg siggy type ([filecoin-project/lotus#7379](https://github.com/filecoin-project/lotus/pull/7379))
- Add v6 actors ([filecoin-project/lotus#7357](https://github.com/filecoin-project/lotus/pull/7357))
- Randomness: Move getters from ChainAPI to StateAPI
- github.com/filecoin-project/go-state-types (v0.1.1-0.20210810190654-139e0e79e69e -> v0.1.1-0.20210915140513-d354ccf10379):
- Add v14
- github.com/filecoin-project/specs-actors/v6 (null -> v6.0.0-20211001193936-c3afe7fa3c5c):
- Better logging (#1503) ([filecoin-project/specs-actors#1503](https://github.com/filecoin-project/specs-actors/pull/1503))
- Defensive programming: harden power actor against seal verify failures (#1502) ([filecoin-project/specs-actors#1502](https://github.com/filecoin-project/specs-actors/pull/1502))
- BatchBalancer fee charged on precommit aggregate (#1497) ([filecoin-project/specs-actors#1497](https://github.com/filecoin-project/specs-actors/pull/1497))
- Fix #1486 (#1489) ([filecoin-project/specs-actors#1489](https://github.com/filecoin-project/specs-actors/pull/1489))
- Sector extension deal weight bug fix (#1498) ([filecoin-project/specs-actors#1498](https://github.com/filecoin-project/specs-actors/pull/1498))
- Fip 0021 (#1487) ([filecoin-project/specs-actors#1487](https://github.com/filecoin-project/specs-actors/pull/1487))
- Fix #176 (swap to xerrors from pkg/errors) (#1494) ([filecoin-project/specs-actors#1494](https://github.com/filecoin-project/specs-actors/pull/1494))
- Merge branch 'master' of github.com:filecoin-project/specs-actors
- Merge branch 'fix-799'
- compute the hash of the proposal iff the proposal hash is present (#1365) ([filecoin-project/specs-actors#1365](https://github.com/filecoin-project/specs-actors/pull/1365))
- Revert "Remove cc upgrade (#1473)" (#1475) ([filecoin-project/specs-actors#1475](https://github.com/filecoin-project/specs-actors/pull/1475))
- Remove cc upgrade (#1473) ([filecoin-project/specs-actors#1473](https://github.com/filecoin-project/specs-actors/pull/1473))
- Update to v6 (#1468) ([filecoin-project/specs-actors#1468](https://github.com/filecoin-project/specs-actors/pull/1468))
- go state types version revert (#1467) ([filecoin-project/specs-actors#1467](https://github.com/filecoin-project/specs-actors/pull/1467))
- Adjust code for subtle change in go-multihash 0.0.15 (#1463) ([filecoin-project/specs-actors#1463](https://github.com/filecoin-project/specs-actors/pull/1463))
- Bump go state types (#1464) ([filecoin-project/specs-actors#1464](https://github.com/filecoin-project/specs-actors/pull/1464))
- Create CODEOWNERS (#1465) ([filecoin-project/specs-actors#1465](https://github.com/filecoin-project/specs-actors/pull/1465))
- Test deterministic offset (#1462) ([filecoin-project/specs-actors#1462](https://github.com/filecoin-project/specs-actors/pull/1462))
Contributors
| Contributor | Commits | Lines ± | Files Changed |
|-------------|---------|---------|---------------|
| ZenGround0 | 12 | +4202/-2752 | 187 |
| Aayush Rajasekaran | 19 | +4491/-825 | 169 |
| c r | 4 | +1276/-435 | 37 |
| Claudia Richoux | 12 | +1350/-209 | 43 |
| Łukasz Magiera | 1 | +171/-13 | 8 |
| Steven Allen | 2 | +115/-12 | 6 |
| Travis Person | 2 | +19/-19 | 7 |
| Peter Rabbitson | 1 | +5/-3 | 1 |
| Jennifer Wang | 1 | +4/-4 | 7 |
| Steve Loeppky | 1 | +6/-0 | 1 |
# v1.11.3 / 2021-09-29
lotus v1.11.3 is a feature release that's **highly recommended to ALL lotus users to upgrade**, including node

View File

@ -1,2 +1,2 @@
/dns4/bootstrap-0.butterfly.fildev.network/tcp/1347/p2p/12D3KooWBbZd7Su9XfLUQ12RynGQ3ZmGY1nGqFntmqop9pLNJE6g
/dns4/bootstrap-1.butterfly.fildev.network/tcp/1347/p2p/12D3KooWGKRzEY4tJFTmAmrYUpa1CVVohmV9YjJbC9v5XWY2gUji
/dns4/bootstrap-0.butterfly.fildev.network/tcp/1347/p2p/12D3KooWBzv5sf4eTyo8cjJGfGnpxo6QkEPkRShG9GqjE2A5QaW5
/dns4/bootstrap-1.butterfly.fildev.network/tcp/1347/p2p/12D3KooWBo9TSD4XXRFtu6snv6QNYvXgRaSaVb116YiYEsDWgKtq

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -10,12 +10,16 @@ import (
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/policy"
miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner"
)
const BootstrappersFile = ""
const GenesisFile = ""
const GenesisNetworkVersion = network.Version14
var UpgradeBreezeHeight = abi.ChainEpoch(-1)
const BreezeGasTampingDuration = 0
@ -42,6 +46,8 @@ var UpgradeTurboHeight = abi.ChainEpoch(-15)
var UpgradeHyperdriveHeight = abi.ChainEpoch(-16)
var UpgradeChocolateHeight = abi.ChainEpoch(-17)
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
}
@ -82,8 +88,12 @@ func init() {
UpgradeNorwegianHeight = getUpgradeHeight("LOTUS_NORWEGIAN_HEIGHT", UpgradeNorwegianHeight)
UpgradeTurboHeight = getUpgradeHeight("LOTUS_ACTORSV4_HEIGHT", UpgradeTurboHeight)
UpgradeHyperdriveHeight = getUpgradeHeight("LOTUS_HYPERDRIVE_HEIGHT", UpgradeHyperdriveHeight)
UpgradeChocolateHeight = getUpgradeHeight("LOTUS_CHOCOLATE_HEIGHT", UpgradeChocolateHeight)
BuildType |= Build2k
// To test out what this proposal would like on devnets / testnets: https://github.com/filecoin-project/FIPs/pull/190
miner6.FaultMaxAge = miner6.WPoStProvingPeriod * 42
}
const BlockDelaySecs = uint64(4)

View File

@ -6,8 +6,10 @@ package build
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/policy"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner"
"github.com/ipfs/go-cid"
)
@ -15,6 +17,8 @@ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
}
const GenesisNetworkVersion = network.Version13
const BootstrappersFile = "butterflynet.pi"
const GenesisFile = "butterflynet.car"
@ -24,19 +28,20 @@ const UpgradeSmokeHeight = -2
const UpgradeIgnitionHeight = -3
const UpgradeRefuelHeight = -4
var UpgradeAssemblyHeight = abi.ChainEpoch(30)
var UpgradeAssemblyHeight = abi.ChainEpoch(-5)
const UpgradeTapeHeight = 60
const UpgradeLiftoffHeight = -5
const UpgradeKumquatHeight = 90
const UpgradeCalicoHeight = 120
const UpgradePersianHeight = 150
const UpgradeClausHeight = 180
const UpgradeOrangeHeight = 210
const UpgradeTrustHeight = 240
const UpgradeNorwegianHeight = UpgradeTrustHeight + (builtin2.EpochsInHour * 12)
const UpgradeTurboHeight = 8922
const UpgradeHyperdriveHeight = 9999999
const UpgradeTapeHeight = -6
const UpgradeLiftoffHeight = -7
const UpgradeKumquatHeight = -8
const UpgradeCalicoHeight = -9
const UpgradePersianHeight = -10
const UpgradeClausHeight = -11
const UpgradeOrangeHeight = -12
const UpgradeTrustHeight = -13
const UpgradeNorwegianHeight = -14
const UpgradeTurboHeight = -15
const UpgradeHyperdriveHeight = -16
const UpgradeChocolateHeight = 6360
func init() {
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2 << 30))
@ -49,6 +54,9 @@ func init() {
Devnet = true
BuildType = BuildButterflynet
// To test out what this proposal would like on devnets / testnets: https://github.com/filecoin-project/FIPs/pull/190
miner6.FaultMaxAge = miner6.WPoStProvingPeriod * 42
}
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)

View File

@ -6,8 +6,10 @@ package build
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/policy"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner"
"github.com/ipfs/go-cid"
)
@ -15,6 +17,8 @@ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
}
const GenesisNetworkVersion = network.Version0
const BootstrappersFile = "calibnet.pi"
const GenesisFile = "calibnet.car"
@ -49,6 +53,8 @@ const UpgradeTurboHeight = 390
const UpgradeHyperdriveHeight = 420
const UpgradeChocolateHeight = 312746
func init() {
policy.SetConsensusMinerMinPower(abi.NewStoragePower(32 << 30))
policy.SetSupportedProofTypes(
@ -61,6 +67,9 @@ func init() {
Devnet = true
BuildType = BuildCalibnet
// To test out what this proposal would like on devnets / testnets: https://github.com/filecoin-project/FIPs/pull/190
miner6.FaultMaxAge = miner6.WPoStProvingPeriod * 42
}
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)

View File

@ -11,7 +11,9 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/policy"
)
@ -19,6 +21,8 @@ import (
const BootstrappersFile = "interopnet.pi"
const GenesisFile = "interopnet.car"
const GenesisNetworkVersion = network.Version13
var UpgradeBreezeHeight = abi.ChainEpoch(-1)
const BreezeGasTampingDuration = 0
@ -44,6 +48,7 @@ var UpgradeNorwegianHeight = abi.ChainEpoch(-14)
var UpgradeTurboHeight = abi.ChainEpoch(-15)
var UpgradeHyperdriveHeight = abi.ChainEpoch(-16)
var UpgradeChocolateHeight = abi.ChainEpoch(-17)
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
@ -93,6 +98,9 @@ func init() {
BuildType |= BuildInteropnet
SetAddressNetwork(address.Testnet)
Devnet = true
// To test out what this proposal would like on devnets / testnets: https://github.com/filecoin-project/FIPs/pull/190
miner6.FaultMaxAge = miner6.WPoStProvingPeriod * 42
}
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)

View File

@ -7,6 +7,8 @@ import (
"math"
"os"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
@ -17,6 +19,8 @@ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
UpgradeSmokeHeight: DrandMainnet,
}
const GenesisNetworkVersion = network.Version0
const BootstrappersFile = "mainnet.pi"
const GenesisFile = "mainnet.car"
@ -60,13 +64,16 @@ const UpgradeTurboHeight = 712320
// 2021-06-30T22:00:00Z
var UpgradeHyperdriveHeight = abi.ChainEpoch(892800)
// ???
var UpgradeChocolateHeight = abi.ChainEpoch(999999999)
func init() {
if os.Getenv("LOTUS_USE_TEST_ADDRESSES") != "1" {
SetAddressNetwork(address.Mainnet)
}
if os.Getenv("LOTUS_DISABLE_HYPERDRIVE") == "1" {
UpgradeHyperdriveHeight = math.MaxInt64
if os.Getenv("LOTUS_DISABLE_CHOCOLATE") == "1" {
UpgradeChocolateHeight = math.MaxInt64
}
Devnet = false

View File

@ -26,6 +26,8 @@ const UnixfsLinksPerLevel = 1024
// Consensus / Network
const AllowableClockDriftSecs = uint64(1)
// TODO: This is still terrible...What's the impact of updating this before mainnet actually upgrades
const NewestNetworkVersion = network.Version13
// Epochs

View File

@ -98,12 +98,15 @@ var (
UpgradeNorwegianHeight abi.ChainEpoch = -13
UpgradeTurboHeight abi.ChainEpoch = -14
UpgradeHyperdriveHeight abi.ChainEpoch = -15
UpgradeChocolateHeight abi.ChainEpoch = -16
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
}
NewestNetworkVersion = network.Version11
GenesisNetworkVersion = network.Version0
NewestNetworkVersion = network.Version14
ActorUpgradeNetworkVersion = network.Version4
Devnet = true

View File

@ -37,7 +37,7 @@ func BuildTypeString() string {
}
// BuildVersion is the local build version
const BuildVersion = "1.11.4-dev"
const BuildVersion = "1.13.0-dev"
func UserVersion() string {
if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" {

View File

@ -21,6 +21,8 @@ import (
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
)
func init() {
@ -44,6 +46,10 @@ func init() {
builtin.RegisterActorState(builtin5.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load5(store, root)
})
builtin.RegisterActorState(builtin6.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load6(store, root)
})
}
var Methods = builtin4.MethodsAccount
@ -66,6 +72,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
case builtin5.AccountActorCodeID:
return load5(store, act.Head)
case builtin6.AccountActorCodeID:
return load6(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@ -88,6 +97,9 @@ func MakeState(store adt.Store, av actors.Version, addr address.Address) (State,
case actors.Version5:
return make5(store, addr)
case actors.Version6:
return make6(store, addr)
}
return nil, xerrors.Errorf("unknown actor version %d", av)
}
@ -110,6 +122,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) {
case actors.Version5:
return builtin5.AccountActorCodeID, nil
case actors.Version6:
return builtin6.AccountActorCodeID, nil
}
return cid.Undef, xerrors.Errorf("unknown actor version %d", av)

View File

@ -0,0 +1,40 @@
package account
import (
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
account6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/account"
)
var _ State = (*state6)(nil)
func load6(store adt.Store, root cid.Cid) (State, error) {
out := state6{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
func make6(store adt.Store, addr address.Address) (State, error) {
out := state6{store: store}
out.State = account6.State{Address: addr}
return &out, nil
}
type state6 struct {
account6.State
store adt.Store
}
func (s *state6) PubkeyAddress() (address.Address, error) {
return s.Address, nil
}
func (s *state6) GetState() interface{} {
return &s.State
}

View File

@ -20,46 +20,49 @@ import (
builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin"
smoothing5 "github.com/filecoin-project/specs-actors/v5/actors/util/smoothing"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
smoothing6 "github.com/filecoin-project/specs-actors/v6/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"
miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner"
proof5 "github.com/filecoin-project/specs-actors/v5/actors/runtime/proof"
miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner"
proof6 "github.com/filecoin-project/specs-actors/v6/actors/runtime/proof"
)
var SystemActorAddr = builtin5.SystemActorAddr
var BurntFundsActorAddr = builtin5.BurntFundsActorAddr
var CronActorAddr = builtin5.CronActorAddr
var SystemActorAddr = builtin6.SystemActorAddr
var BurntFundsActorAddr = builtin6.BurntFundsActorAddr
var CronActorAddr = builtin6.CronActorAddr
var SaftAddress = makeAddress("t0122")
var ReserveAddress = makeAddress("t090")
var RootVerifierAddress = makeAddress("t080")
var (
ExpectedLeadersPerEpoch = builtin5.ExpectedLeadersPerEpoch
ExpectedLeadersPerEpoch = builtin6.ExpectedLeadersPerEpoch
)
const (
EpochDurationSeconds = builtin5.EpochDurationSeconds
EpochsInDay = builtin5.EpochsInDay
SecondsInDay = builtin5.SecondsInDay
EpochDurationSeconds = builtin6.EpochDurationSeconds
EpochsInDay = builtin6.EpochsInDay
SecondsInDay = builtin6.SecondsInDay
)
const (
MethodSend = builtin5.MethodSend
MethodConstructor = builtin5.MethodConstructor
MethodSend = builtin6.MethodSend
MethodConstructor = builtin6.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 = proof5.SectorInfo
type PoStProof = proof5.PoStProof
type SectorInfo = proof6.SectorInfo
type PoStProof = proof6.PoStProof
type FilterEstimate = smoothing0.FilterEstimate
func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower {
return miner5.QAPowerForWeight(size, duration, dealWeight, verifiedWeight)
return miner6.QAPowerForWeight(size, duration, dealWeight, verifiedWeight)
}
func FromV0FilterEstimate(v0 smoothing0.FilterEstimate) FilterEstimate {
@ -92,6 +95,12 @@ func FromV5FilterEstimate(v5 smoothing5.FilterEstimate) FilterEstimate {
}
func FromV6FilterEstimate(v6 smoothing6.FilterEstimate) FilterEstimate {
return (FilterEstimate)(v6)
}
type ActorStateLoader func(store adt.Store, root cid.Cid) (cbor.Marshaler, error)
var ActorStateLoaders = make(map[cid.Cid]ActorStateLoader)
@ -126,6 +135,9 @@ func ActorNameByCode(c cid.Cid) string {
case builtin5.IsBuiltinActor(c):
return builtin5.ActorNameByCode(c)
case builtin6.IsBuiltinActor(c):
return builtin6.ActorNameByCode(c)
default:
return "<unknown>"
}
@ -153,6 +165,10 @@ func IsBuiltinActor(c cid.Cid) bool {
return true
}
if builtin6.IsBuiltinActor(c) {
return true
}
return false
}
@ -178,6 +194,10 @@ func IsAccountActor(c cid.Cid) bool {
return true
}
if c == builtin6.AccountActorCodeID {
return true
}
return false
}
@ -203,6 +223,10 @@ func IsStorageMinerActor(c cid.Cid) bool {
return true
}
if c == builtin6.StorageMinerActorCodeID {
return true
}
return false
}
@ -228,6 +252,10 @@ func IsMultisigActor(c cid.Cid) bool {
return true
}
if c == builtin6.MultisigActorCodeID {
return true
}
return false
}
@ -253,6 +281,10 @@ func IsPaymentChannelActor(c cid.Cid) bool {
return true
}
if c == builtin6.PaymentChannelActorCodeID {
return true
}
return false
}

View File

@ -15,6 +15,8 @@ import (
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
)
func MakeState(store adt.Store, av actors.Version) (State, error) {
@ -35,6 +37,9 @@ func MakeState(store adt.Store, av actors.Version) (State, error) {
case actors.Version5:
return make5(store)
case actors.Version6:
return make6(store)
}
return nil, xerrors.Errorf("unknown actor version %d", av)
}
@ -57,14 +62,17 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) {
case actors.Version5:
return builtin5.CronActorCodeID, nil
case actors.Version6:
return builtin6.CronActorCodeID, nil
}
return cid.Undef, xerrors.Errorf("unknown actor version %d", av)
}
var (
Address = builtin5.CronActorAddr
Methods = builtin5.MethodsCron
Address = builtin6.CronActorAddr
Methods = builtin6.MethodsCron
)
type State interface {

View File

@ -0,0 +1,35 @@
package cron
import (
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
cron6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/cron"
)
var _ State = (*state6)(nil)
func load6(store adt.Store, root cid.Cid) (State, error) {
out := state6{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
func make6(store adt.Store) (State, error) {
out := state6{store: store}
out.State = *cron6.ConstructState(cron6.BuiltInEntries())
return &out, nil
}
type state6 struct {
cron6.State
store adt.Store
}
func (s *state6) GetState() interface{} {
return &s.State
}

View File

@ -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"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
)
func init() {
@ -46,11 +48,15 @@ func init() {
builtin.RegisterActorState(builtin5.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load5(store, root)
})
builtin.RegisterActorState(builtin6.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load6(store, root)
})
}
var (
Address = builtin5.InitActorAddr
Methods = builtin5.MethodsInit
Address = builtin6.InitActorAddr
Methods = builtin6.MethodsInit
)
func Load(store adt.Store, act *types.Actor) (State, error) {
@ -71,6 +77,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
case builtin5.InitActorCodeID:
return load5(store, act.Head)
case builtin6.InitActorCodeID:
return load6(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@ -93,6 +102,9 @@ func MakeState(store adt.Store, av actors.Version, networkName string) (State, e
case actors.Version5:
return make5(store, networkName)
case actors.Version6:
return make6(store, networkName)
}
return nil, xerrors.Errorf("unknown actor version %d", av)
}
@ -115,6 +127,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) {
case actors.Version5:
return builtin5.InitActorCodeID, nil
case actors.Version6:
return builtin6.InitActorCodeID, nil
}
return cid.Undef, xerrors.Errorf("unknown actor version %d", av)

View File

@ -0,0 +1,114 @@
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"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
init6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/init"
adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt"
)
var _ State = (*state6)(nil)
func load6(store adt.Store, root cid.Cid) (State, error) {
out := state6{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
func make6(store adt.Store, networkName string) (State, error) {
out := state6{store: store}
s, err := init6.ConstructState(store, networkName)
if err != nil {
return nil, err
}
out.State = *s
return &out, nil
}
type state6 struct {
init6.State
store adt.Store
}
func (s *state6) ResolveAddress(address address.Address) (address.Address, bool, error) {
return s.State.ResolveAddress(s.store, address)
}
func (s *state6) MapAddressToNewID(address address.Address) (address.Address, error) {
return s.State.MapAddressToNewID(s.store, address)
}
func (s *state6) ForEachActor(cb func(id abi.ActorID, address address.Address) error) error {
addrs, err := adt6.AsMap(s.store, s.State.AddressMap, builtin6.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 *state6) NetworkName() (dtypes.NetworkName, error) {
return dtypes.NetworkName(s.State.NetworkName), nil
}
func (s *state6) SetNetworkName(name string) error {
s.State.NetworkName = name
return nil
}
func (s *state6) SetNextID(id abi.ActorID) error {
s.State.NextID = id
return nil
}
func (s *state6) Remove(addrs ...address.Address) (err error) {
m, err := adt6.AsMap(s.store, s.State.AddressMap, builtin6.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 *state6) SetAddressMap(mcid cid.Cid) error {
s.State.AddressMap = mcid
return nil
}
func (s *state6) AddressMap() (adt.Map, error) {
return adt6.AsMap(s.store, s.State.AddressMap, builtin6.DefaultHamtBitwidth)
}
func (s *state6) GetState() interface{} {
return &s.State
}

View File

@ -1,6 +1,7 @@
package market
import (
"github.com/filecoin-project/go-state-types/network"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
@ -103,7 +104,28 @@ type DealProposals interface {
}
type PublishStorageDealsParams = market0.PublishStorageDealsParams
type PublishStorageDealsReturn = market0.PublishStorageDealsReturn
type PublishStorageDealsReturn interface {
DealIDs() ([]abi.DealID, error)
// Note that this index is based on the batch of deals that were published, NOT the DealID
IsDealValid(index uint64) (bool, error)
}
func DecodePublishStorageDealsReturn(b []byte, nv network.Version) (PublishStorageDealsReturn, error) {
av, err := actors.VersionForNetwork(nv)
if err != nil {
return nil, err
}
switch av {
{{range .versions}}
case actors.Version{{.}}:
return decodePublishStorageDealsReturn{{.}}(b)
{{end}}
}
return nil, xerrors.Errorf("unknown actor version %d", av)
}
type VerifyDealsForActivationParams = market0.VerifyDealsForActivationParams
type WithdrawBalanceParams = market0.WithdrawBalanceParams

View File

@ -1,6 +1,7 @@
package market
import (
"github.com/filecoin-project/go-state-types/network"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
@ -22,6 +23,8 @@ import (
builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin"
builtin6 "github.com/filecoin-project/specs-actors/v6/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"
@ -49,11 +52,15 @@ func init() {
builtin.RegisterActorState(builtin5.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load5(store, root)
})
builtin.RegisterActorState(builtin6.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load6(store, root)
})
}
var (
Address = builtin5.StorageMarketActorAddr
Methods = builtin5.MethodsMarket
Address = builtin6.StorageMarketActorAddr
Methods = builtin6.MethodsMarket
)
func Load(store adt.Store, act *types.Actor) (State, error) {
@ -74,6 +81,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
case builtin5.StorageMarketActorCodeID:
return load5(store, act.Head)
case builtin6.StorageMarketActorCodeID:
return load6(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@ -96,6 +106,9 @@ func MakeState(store adt.Store, av actors.Version) (State, error) {
case actors.Version5:
return make5(store)
case actors.Version6:
return make6(store)
}
return nil, xerrors.Errorf("unknown actor version %d", av)
}
@ -118,6 +131,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) {
case actors.Version5:
return builtin5.StorageMarketActorCodeID, nil
case actors.Version6:
return builtin6.StorageMarketActorCodeID, nil
}
return cid.Undef, xerrors.Errorf("unknown actor version %d", av)
@ -162,7 +178,43 @@ type DealProposals interface {
}
type PublishStorageDealsParams = market0.PublishStorageDealsParams
type PublishStorageDealsReturn = market0.PublishStorageDealsReturn
type PublishStorageDealsReturn interface {
DealIDs() ([]abi.DealID, error)
// Note that this index is based on the batch of deals that were published, NOT the DealID
IsDealValid(index uint64) (bool, error)
}
func DecodePublishStorageDealsReturn(b []byte, nv network.Version) (PublishStorageDealsReturn, error) {
av, err := actors.VersionForNetwork(nv)
if err != nil {
return nil, err
}
switch av {
case actors.Version0:
return decodePublishStorageDealsReturn0(b)
case actors.Version2:
return decodePublishStorageDealsReturn2(b)
case actors.Version3:
return decodePublishStorageDealsReturn3(b)
case actors.Version4:
return decodePublishStorageDealsReturn4(b)
case actors.Version5:
return decodePublishStorageDealsReturn5(b)
case actors.Version6:
return decodePublishStorageDealsReturn6(b)
}
return nil, xerrors.Errorf("unknown actor version %d", av)
}
type VerifyDealsForActivationParams = market0.VerifyDealsForActivationParams
type WithdrawBalanceParams = market0.WithdrawBalanceParams

View File

@ -7,6 +7,7 @@ import (
"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/chain/types"
@ -236,3 +237,31 @@ func fromV{{.v}}DealProposal(v{{.v}} market{{.v}}.DealProposal) DealProposal {
func (s *state{{.v}}) GetState() interface{} {
return &s.State
}
var _ PublishStorageDealsReturn = (*publishStorageDealsReturn{{.v}})(nil)
func decodePublishStorageDealsReturn{{.v}}(b []byte) (PublishStorageDealsReturn, error) {
var retval market{{.v}}.PublishStorageDealsReturn
if err := retval.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
return nil, xerrors.Errorf("failed to unmarshal PublishStorageDealsReturn: %w", err)
}
return &publishStorageDealsReturn{{.v}}{retval}, nil
}
type publishStorageDealsReturn{{.v}} struct {
market{{.v}}.PublishStorageDealsReturn
}
func (r *publishStorageDealsReturn{{.v}}) IsDealValid(index uint64) (bool, error) {
{{if (ge .v 6)}}
return r.ValidDeals.IsSet(index)
{{else}}
// PublishStorageDeals only succeeded if all deals were valid in this version of actors
return true, nil
{{end}}
}
func (r *publishStorageDealsReturn{{.v}}) DealIDs() ([]abi.DealID, error) {
return r.IDs, nil
}

View File

@ -7,6 +7,7 @@ import (
"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/chain/types"
@ -229,3 +230,29 @@ func fromV0DealProposal(v0 market0.DealProposal) DealProposal {
func (s *state0) GetState() interface{} {
return &s.State
}
var _ PublishStorageDealsReturn = (*publishStorageDealsReturn0)(nil)
func decodePublishStorageDealsReturn0(b []byte) (PublishStorageDealsReturn, error) {
var retval market0.PublishStorageDealsReturn
if err := retval.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
return nil, xerrors.Errorf("failed to unmarshal PublishStorageDealsReturn: %w", err)
}
return &publishStorageDealsReturn0{retval}, nil
}
type publishStorageDealsReturn0 struct {
market0.PublishStorageDealsReturn
}
func (r *publishStorageDealsReturn0) IsDealValid(index uint64) (bool, error) {
// PublishStorageDeals only succeeded if all deals were valid in this version of actors
return true, nil
}
func (r *publishStorageDealsReturn0) DealIDs() ([]abi.DealID, error) {
return r.IDs, nil
}

View File

@ -7,6 +7,7 @@ import (
"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/chain/types"
@ -229,3 +230,29 @@ func fromV2DealProposal(v2 market2.DealProposal) DealProposal {
func (s *state2) GetState() interface{} {
return &s.State
}
var _ PublishStorageDealsReturn = (*publishStorageDealsReturn2)(nil)
func decodePublishStorageDealsReturn2(b []byte) (PublishStorageDealsReturn, error) {
var retval market2.PublishStorageDealsReturn
if err := retval.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
return nil, xerrors.Errorf("failed to unmarshal PublishStorageDealsReturn: %w", err)
}
return &publishStorageDealsReturn2{retval}, nil
}
type publishStorageDealsReturn2 struct {
market2.PublishStorageDealsReturn
}
func (r *publishStorageDealsReturn2) IsDealValid(index uint64) (bool, error) {
// PublishStorageDeals only succeeded if all deals were valid in this version of actors
return true, nil
}
func (r *publishStorageDealsReturn2) DealIDs() ([]abi.DealID, error) {
return r.IDs, nil
}

View File

@ -7,6 +7,7 @@ import (
"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/chain/types"
@ -224,3 +225,29 @@ func fromV3DealProposal(v3 market3.DealProposal) DealProposal {
func (s *state3) GetState() interface{} {
return &s.State
}
var _ PublishStorageDealsReturn = (*publishStorageDealsReturn3)(nil)
func decodePublishStorageDealsReturn3(b []byte) (PublishStorageDealsReturn, error) {
var retval market3.PublishStorageDealsReturn
if err := retval.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
return nil, xerrors.Errorf("failed to unmarshal PublishStorageDealsReturn: %w", err)
}
return &publishStorageDealsReturn3{retval}, nil
}
type publishStorageDealsReturn3 struct {
market3.PublishStorageDealsReturn
}
func (r *publishStorageDealsReturn3) IsDealValid(index uint64) (bool, error) {
// PublishStorageDeals only succeeded if all deals were valid in this version of actors
return true, nil
}
func (r *publishStorageDealsReturn3) DealIDs() ([]abi.DealID, error) {
return r.IDs, nil
}

View File

@ -7,6 +7,7 @@ import (
"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/chain/types"
@ -224,3 +225,29 @@ func fromV4DealProposal(v4 market4.DealProposal) DealProposal {
func (s *state4) GetState() interface{} {
return &s.State
}
var _ PublishStorageDealsReturn = (*publishStorageDealsReturn4)(nil)
func decodePublishStorageDealsReturn4(b []byte) (PublishStorageDealsReturn, error) {
var retval market4.PublishStorageDealsReturn
if err := retval.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
return nil, xerrors.Errorf("failed to unmarshal PublishStorageDealsReturn: %w", err)
}
return &publishStorageDealsReturn4{retval}, nil
}
type publishStorageDealsReturn4 struct {
market4.PublishStorageDealsReturn
}
func (r *publishStorageDealsReturn4) IsDealValid(index uint64) (bool, error) {
// PublishStorageDeals only succeeded if all deals were valid in this version of actors
return true, nil
}
func (r *publishStorageDealsReturn4) DealIDs() ([]abi.DealID, error) {
return r.IDs, nil
}

View File

@ -7,6 +7,7 @@ import (
"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/chain/types"
@ -224,3 +225,29 @@ func fromV5DealProposal(v5 market5.DealProposal) DealProposal {
func (s *state5) GetState() interface{} {
return &s.State
}
var _ PublishStorageDealsReturn = (*publishStorageDealsReturn5)(nil)
func decodePublishStorageDealsReturn5(b []byte) (PublishStorageDealsReturn, error) {
var retval market5.PublishStorageDealsReturn
if err := retval.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
return nil, xerrors.Errorf("failed to unmarshal PublishStorageDealsReturn: %w", err)
}
return &publishStorageDealsReturn5{retval}, nil
}
type publishStorageDealsReturn5 struct {
market5.PublishStorageDealsReturn
}
func (r *publishStorageDealsReturn5) IsDealValid(index uint64) (bool, error) {
// PublishStorageDeals only succeeded if all deals were valid in this version of actors
return true, nil
}
func (r *publishStorageDealsReturn5) DealIDs() ([]abi.DealID, error) {
return r.IDs, nil
}

View File

@ -0,0 +1,252 @@
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"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
market6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/market"
adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt"
)
var _ State = (*state6)(nil)
func load6(store adt.Store, root cid.Cid) (State, error) {
out := state6{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
func make6(store adt.Store) (State, error) {
out := state6{store: store}
s, err := market6.ConstructState(store)
if err != nil {
return nil, err
}
out.State = *s
return &out, nil
}
type state6 struct {
market6.State
store adt.Store
}
func (s *state6) TotalLocked() (abi.TokenAmount, error) {
fml := types.BigAdd(s.TotalClientLockedCollateral, s.TotalProviderLockedCollateral)
fml = types.BigAdd(fml, s.TotalClientStorageFee)
return fml, nil
}
func (s *state6) BalancesChanged(otherState State) (bool, error) {
otherState6, ok := otherState.(*state6)
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(otherState6.State.EscrowTable) || !s.State.LockedTable.Equals(otherState6.State.LockedTable), nil
}
func (s *state6) StatesChanged(otherState State) (bool, error) {
otherState6, ok := otherState.(*state6)
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(otherState6.State.States), nil
}
func (s *state6) States() (DealStates, error) {
stateArray, err := adt6.AsArray(s.store, s.State.States, market6.StatesAmtBitwidth)
if err != nil {
return nil, err
}
return &dealStates6{stateArray}, nil
}
func (s *state6) ProposalsChanged(otherState State) (bool, error) {
otherState6, ok := otherState.(*state6)
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(otherState6.State.Proposals), nil
}
func (s *state6) Proposals() (DealProposals, error) {
proposalArray, err := adt6.AsArray(s.store, s.State.Proposals, market6.ProposalsAmtBitwidth)
if err != nil {
return nil, err
}
return &dealProposals6{proposalArray}, nil
}
func (s *state6) EscrowTable() (BalanceTable, error) {
bt, err := adt6.AsBalanceTable(s.store, s.State.EscrowTable)
if err != nil {
return nil, err
}
return &balanceTable6{bt}, nil
}
func (s *state6) LockedTable() (BalanceTable, error) {
bt, err := adt6.AsBalanceTable(s.store, s.State.LockedTable)
if err != nil {
return nil, err
}
return &balanceTable6{bt}, nil
}
func (s *state6) VerifyDealsForActivation(
minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch,
) (weight, verifiedWeight abi.DealWeight, err error) {
w, vw, _, err := market6.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch)
return w, vw, err
}
func (s *state6) NextID() (abi.DealID, error) {
return s.State.NextID, nil
}
type balanceTable6 struct {
*adt6.BalanceTable
}
func (bt *balanceTable6) ForEach(cb func(address.Address, abi.TokenAmount) error) error {
asMap := (*adt6.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 dealStates6 struct {
adt.Array
}
func (s *dealStates6) Get(dealID abi.DealID) (*DealState, bool, error) {
var deal6 market6.DealState
found, err := s.Array.Get(uint64(dealID), &deal6)
if err != nil {
return nil, false, err
}
if !found {
return nil, false, nil
}
deal := fromV6DealState(deal6)
return &deal, true, nil
}
func (s *dealStates6) ForEach(cb func(dealID abi.DealID, ds DealState) error) error {
var ds6 market6.DealState
return s.Array.ForEach(&ds6, func(idx int64) error {
return cb(abi.DealID(idx), fromV6DealState(ds6))
})
}
func (s *dealStates6) decode(val *cbg.Deferred) (*DealState, error) {
var ds6 market6.DealState
if err := ds6.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err
}
ds := fromV6DealState(ds6)
return &ds, nil
}
func (s *dealStates6) array() adt.Array {
return s.Array
}
func fromV6DealState(v6 market6.DealState) DealState {
return (DealState)(v6)
}
type dealProposals6 struct {
adt.Array
}
func (s *dealProposals6) Get(dealID abi.DealID) (*DealProposal, bool, error) {
var proposal6 market6.DealProposal
found, err := s.Array.Get(uint64(dealID), &proposal6)
if err != nil {
return nil, false, err
}
if !found {
return nil, false, nil
}
proposal := fromV6DealProposal(proposal6)
return &proposal, true, nil
}
func (s *dealProposals6) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error {
var dp6 market6.DealProposal
return s.Array.ForEach(&dp6, func(idx int64) error {
return cb(abi.DealID(idx), fromV6DealProposal(dp6))
})
}
func (s *dealProposals6) decode(val *cbg.Deferred) (*DealProposal, error) {
var dp6 market6.DealProposal
if err := dp6.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err
}
dp := fromV6DealProposal(dp6)
return &dp, nil
}
func (s *dealProposals6) array() adt.Array {
return s.Array
}
func fromV6DealProposal(v6 market6.DealProposal) DealProposal {
return (DealProposal)(v6)
}
func (s *state6) GetState() interface{} {
return &s.State
}
var _ PublishStorageDealsReturn = (*publishStorageDealsReturn6)(nil)
func decodePublishStorageDealsReturn6(b []byte) (PublishStorageDealsReturn, error) {
var retval market6.PublishStorageDealsReturn
if err := retval.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
return nil, xerrors.Errorf("failed to unmarshal PublishStorageDealsReturn: %w", err)
}
return &publishStorageDealsReturn6{retval}, nil
}
type publishStorageDealsReturn6 struct {
market6.PublishStorageDealsReturn
}
func (r *publishStorageDealsReturn6) IsDealValid(index uint64) (bool, error) {
return r.ValidDeals.IsSet(index)
}
func (r *publishStorageDealsReturn6) DealIDs() ([]abi.DealID, error) {
return r.IDs, nil
}

View File

@ -33,6 +33,8 @@ import (
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
)
func init() {
@ -57,9 +59,13 @@ func init() {
return load5(store, root)
})
builtin.RegisterActorState(builtin6.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load6(store, root)
})
}
var Methods = builtin5.MethodsMiner
var Methods = builtin6.MethodsMiner
// Unchanged between v0, v2, v3, v4, and v5 actors
var WPoStProvingPeriod = miner0.WPoStProvingPeriod
@ -93,6 +99,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
case builtin5.StorageMinerActorCodeID:
return load5(store, act.Head)
case builtin6.StorageMinerActorCodeID:
return load6(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@ -115,6 +124,9 @@ func MakeState(store adt.Store, av actors.Version) (State, error) {
case actors.Version5:
return make5(store)
case actors.Version6:
return make6(store)
}
return nil, xerrors.Errorf("unknown actor version %d", av)
}
@ -137,6 +149,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) {
case actors.Version5:
return builtin5.StorageMinerActorCodeID, nil
case actors.Version6:
return builtin6.StorageMinerActorCodeID, nil
}
return cid.Undef, xerrors.Errorf("unknown actor version %d", av)

View File

@ -0,0 +1,570 @@
package miner
import (
"bytes"
"errors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
rle "github.com/filecoin-project/go-bitfield/rle"
"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"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner"
adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt"
)
var _ State = (*state6)(nil)
func load6(store adt.Store, root cid.Cid) (State, error) {
out := state6{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
func make6(store adt.Store) (State, error) {
out := state6{store: store}
out.State = miner6.State{}
return &out, nil
}
type state6 struct {
miner6.State
store adt.Store
}
type deadline6 struct {
miner6.Deadline
store adt.Store
}
type partition6 struct {
miner6.Partition
store adt.Store
}
func (s *state6) 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 *state6) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) {
return s.CheckVestedFunds(s.store, epoch)
}
func (s *state6) LockedFunds() (LockedFunds, error) {
return LockedFunds{
VestingFunds: s.State.LockedFunds,
InitialPledgeRequirement: s.State.InitialPledge,
PreCommitDeposits: s.State.PreCommitDeposits,
}, nil
}
func (s *state6) FeeDebt() (abi.TokenAmount, error) {
return s.State.FeeDebt, nil
}
func (s *state6) InitialPledge() (abi.TokenAmount, error) {
return s.State.InitialPledge, nil
}
func (s *state6) PreCommitDeposits() (abi.TokenAmount, error) {
return s.State.PreCommitDeposits, nil
}
func (s *state6) GetSector(num abi.SectorNumber) (*SectorOnChainInfo, error) {
info, ok, err := s.State.GetSector(s.store, num)
if !ok || err != nil {
return nil, err
}
ret := fromV6SectorOnChainInfo(*info)
return &ret, nil
}
func (s *state6) 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 *state6) 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 *miner6.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 *state6) 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 *miner6.Deadline) error {
partitions, err := dl.PartitionsArray(s.store)
if err != nil {
return err
}
quant := s.State.QuantSpecForDeadline(dlIdx)
var part miner6.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 := miner6.LoadExpirationQueue(s.store, part.ExpirationsEpochs, quant, miner6.PartitionExpirationAmtBitwidth)
if err != nil {
return err
}
var exp miner6.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 *state6) GetPrecommittedSector(num abi.SectorNumber) (*SectorPreCommitOnChainInfo, error) {
info, ok, err := s.State.GetPrecommittedSector(s.store, num)
if !ok || err != nil {
return nil, err
}
ret := fromV6SectorPreCommitOnChainInfo(*info)
return &ret, nil
}
func (s *state6) ForEachPrecommittedSector(cb func(SectorPreCommitOnChainInfo) error) error {
precommitted, err := adt6.AsMap(s.store, s.State.PreCommittedSectors, builtin6.DefaultHamtBitwidth)
if err != nil {
return err
}
var info miner6.SectorPreCommitOnChainInfo
if err := precommitted.ForEach(&info, func(_ string) error {
return cb(fromV6SectorPreCommitOnChainInfo(info))
}); err != nil {
return err
}
return nil
}
func (s *state6) LoadSectors(snos *bitfield.BitField) ([]*SectorOnChainInfo, error) {
sectors, err := miner6.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 info6 miner6.SectorOnChainInfo
if err := sectors.ForEach(&info6, func(_ int64) error {
info := fromV6SectorOnChainInfo(info6)
infos = append(infos, &info)
return nil
}); err != nil {
return nil, err
}
return infos, nil
}
// Otherwise, load selected.
infos6, err := sectors.Load(*snos)
if err != nil {
return nil, err
}
infos := make([]*SectorOnChainInfo, len(infos6))
for i, info6 := range infos6 {
info := fromV6SectorOnChainInfo(*info6)
infos[i] = &info
}
return infos, nil
}
func (s *state6) loadAllocatedSectorNumbers() (bitfield.BitField, error) {
var allocatedSectors bitfield.BitField
err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors)
return allocatedSectors, err
}
func (s *state6) IsAllocated(num abi.SectorNumber) (bool, error) {
allocatedSectors, err := s.loadAllocatedSectorNumbers()
if err != nil {
return false, err
}
return allocatedSectors.IsSet(uint64(num))
}
func (s *state6) GetProvingPeriodStart() (abi.ChainEpoch, error) {
return s.State.ProvingPeriodStart, nil
}
func (s *state6) UnallocatedSectorNumbers(count int) ([]abi.SectorNumber, error) {
allocatedSectors, err := s.loadAllocatedSectorNumbers()
if err != nil {
return nil, err
}
allocatedRuns, err := allocatedSectors.RunIterator()
if err != nil {
return nil, err
}
unallocatedRuns, err := rle.Subtract(
&rle.RunSliceIterator{Runs: []rle.Run{{Val: true, Len: abi.MaxSectorNumber}}},
allocatedRuns,
)
if err != nil {
return nil, err
}
iter, err := rle.BitsFromRuns(unallocatedRuns)
if err != nil {
return nil, err
}
sectors := make([]abi.SectorNumber, 0, count)
for iter.HasNext() && len(sectors) < count {
nextNo, err := iter.Next()
if err != nil {
return nil, err
}
sectors = append(sectors, abi.SectorNumber(nextNo))
}
return sectors, nil
}
func (s *state6) GetAllocatedSectors() (*bitfield.BitField, error) {
var allocatedSectors bitfield.BitField
if err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors); err != nil {
return nil, err
}
return &allocatedSectors, nil
}
func (s *state6) 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 &deadline6{*dl, s.store}, nil
}
func (s *state6) 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 *miner6.Deadline) error {
return cb(i, &deadline6{*dl, s.store})
})
}
func (s *state6) NumDeadlines() (uint64, error) {
return miner6.WPoStPeriodDeadlines, nil
}
func (s *state6) DeadlinesChanged(other State) (bool, error) {
other6, ok := other.(*state6)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.Deadlines.Equals(other6.Deadlines), nil
}
func (s *state6) MinerInfoChanged(other State) (bool, error) {
other0, ok := other.(*state6)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.Info.Equals(other0.State.Info), nil
}
func (s *state6) 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 *state6) DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error) {
return s.State.RecordedDeadlineInfo(epoch), nil
}
func (s *state6) DeadlineCronActive() (bool, error) {
return s.State.DeadlineCronActive, nil
}
func (s *state6) sectors() (adt.Array, error) {
return adt6.AsArray(s.store, s.Sectors, miner6.SectorsAmtBitwidth)
}
func (s *state6) decodeSectorOnChainInfo(val *cbg.Deferred) (SectorOnChainInfo, error) {
var si miner6.SectorOnChainInfo
err := si.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return SectorOnChainInfo{}, err
}
return fromV6SectorOnChainInfo(si), nil
}
func (s *state6) precommits() (adt.Map, error) {
return adt6.AsMap(s.store, s.PreCommittedSectors, builtin6.DefaultHamtBitwidth)
}
func (s *state6) decodeSectorPreCommitOnChainInfo(val *cbg.Deferred) (SectorPreCommitOnChainInfo, error) {
var sp miner6.SectorPreCommitOnChainInfo
err := sp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return SectorPreCommitOnChainInfo{}, err
}
return fromV6SectorPreCommitOnChainInfo(sp), nil
}
func (s *state6) EraseAllUnproven() error {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return err
}
err = dls.ForEach(s.store, func(dindx uint64, dl *miner6.Deadline) error {
ps, err := dl.PartitionsArray(s.store)
if err != nil {
return err
}
var part miner6.Partition
err = ps.ForEach(&part, func(pindx int64) error {
_ = part.ActivateUnproven()
err = ps.Set(uint64(pindx), &part)
return nil
})
if err != nil {
return err
}
dl.Partitions, err = ps.Root()
if err != nil {
return err
}
return dls.UpdateDeadline(s.store, dindx, dl)
})
if err != nil {
return err
}
return s.State.SaveDeadlines(s.store, dls)
}
func (d *deadline6) LoadPartition(idx uint64) (Partition, error) {
p, err := d.Deadline.LoadPartition(d.store, idx)
if err != nil {
return nil, err
}
return &partition6{*p, d.store}, nil
}
func (d *deadline6) ForEachPartition(cb func(uint64, Partition) error) error {
ps, err := d.Deadline.PartitionsArray(d.store)
if err != nil {
return err
}
var part miner6.Partition
return ps.ForEach(&part, func(i int64) error {
return cb(uint64(i), &partition6{part, d.store})
})
}
func (d *deadline6) PartitionsChanged(other Deadline) (bool, error) {
other6, ok := other.(*deadline6)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !d.Deadline.Partitions.Equals(other6.Deadline.Partitions), nil
}
func (d *deadline6) PartitionsPoSted() (bitfield.BitField, error) {
return d.Deadline.PartitionsPoSted, nil
}
func (d *deadline6) DisputableProofCount() (uint64, error) {
ops, err := d.OptimisticProofsSnapshotArray(d.store)
if err != nil {
return 0, err
}
return ops.Length(), nil
}
func (p *partition6) AllSectors() (bitfield.BitField, error) {
return p.Partition.Sectors, nil
}
func (p *partition6) FaultySectors() (bitfield.BitField, error) {
return p.Partition.Faults, nil
}
func (p *partition6) RecoveringSectors() (bitfield.BitField, error) {
return p.Partition.Recoveries, nil
}
func (p *partition6) UnprovenSectors() (bitfield.BitField, error) {
return p.Partition.Unproven, nil
}
func fromV6SectorOnChainInfo(v6 miner6.SectorOnChainInfo) SectorOnChainInfo {
return SectorOnChainInfo{
SectorNumber: v6.SectorNumber,
SealProof: v6.SealProof,
SealedCID: v6.SealedCID,
DealIDs: v6.DealIDs,
Activation: v6.Activation,
Expiration: v6.Expiration,
DealWeight: v6.DealWeight,
VerifiedDealWeight: v6.VerifiedDealWeight,
InitialPledge: v6.InitialPledge,
ExpectedDayReward: v6.ExpectedDayReward,
ExpectedStoragePledge: v6.ExpectedStoragePledge,
}
}
func fromV6SectorPreCommitOnChainInfo(v6 miner6.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo {
return SectorPreCommitOnChainInfo{
Info: (SectorPreCommitInfo)(v6.Info),
PreCommitDeposit: v6.PreCommitDeposit,
PreCommitEpoch: v6.PreCommitEpoch,
DealWeight: v6.DealWeight,
VerifiedDealWeight: v6.VerifiedDealWeight,
}
}
func (s *state6) GetState() interface{} {
return &s.State
}

View File

@ -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"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
init6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/init"
multisig6 "github.com/filecoin-project/specs-actors/v6/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 message6 struct{ message0 }
func (m message6) 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 := &multisig6.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 := &init6.ExecParams{
CodeCID: builtin6.MultisigActorCodeID,
ConstructorParams: enc,
}
enc, actErr = actors.SerializeParams(execParams)
if actErr != nil {
return nil, actErr
}
return &types.Message{
To: init_.Address,
From: m.from,
Method: builtin6.MethodsInit.Exec,
Params: enc,
Value: initialAmount,
}, nil
}

View File

@ -13,7 +13,7 @@ import (
"github.com/ipfs/go-cid"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
msig5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/multisig"
msig6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/multisig"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
@ -25,6 +25,8 @@ import (
builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin"
builtin6 "github.com/filecoin-project/specs-actors/v6/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"
@ -52,6 +54,10 @@ func init() {
builtin.RegisterActorState(builtin5.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load5(store, root)
})
builtin.RegisterActorState(builtin6.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load6(store, root)
})
}
func Load(store adt.Store, act *types.Actor) (State, error) {
@ -72,6 +78,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
case builtin5.MultisigActorCodeID:
return load5(store, act.Head)
case builtin6.MultisigActorCodeID:
return load6(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@ -94,6 +103,9 @@ func MakeState(store adt.Store, av actors.Version, signers []address.Address, th
case actors.Version5:
return make5(store, signers, threshold, startEpoch, unlockDuration, initialBalance)
case actors.Version6:
return make6(store, signers, threshold, startEpoch, unlockDuration, initialBalance)
}
return nil, xerrors.Errorf("unknown actor version %d", av)
}
@ -116,6 +128,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) {
case actors.Version5:
return builtin5.MultisigActorCodeID, nil
case actors.Version6:
return builtin6.MultisigActorCodeID, nil
}
return cid.Undef, xerrors.Errorf("unknown actor version %d", av)
@ -141,7 +156,7 @@ type State interface {
type Transaction = msig0.Transaction
var Methods = builtin5.MethodsMultisig
var Methods = builtin6.MethodsMultisig
func Message(version actors.Version, from address.Address) MessageBuilder {
switch version {
@ -160,6 +175,9 @@ func Message(version actors.Version, from address.Address) MessageBuilder {
case actors.Version5:
return message5{message0{from}}
case actors.Version6:
return message6{message0{from}}
default:
panic(fmt.Sprintf("unsupported actors version: %d", version))
}
@ -183,13 +201,13 @@ type MessageBuilder interface {
}
// this type is the same between v0 and v2
type ProposalHashData = msig5.ProposalHashData
type ProposeReturn = msig5.ProposeReturn
type ProposeParams = msig5.ProposeParams
type ApproveReturn = msig5.ApproveReturn
type ProposalHashData = msig6.ProposalHashData
type ProposeReturn = msig6.ProposeReturn
type ProposeParams = msig6.ProposeParams
type ApproveReturn = msig6.ApproveReturn
func txnParams(id uint64, data *ProposalHashData) ([]byte, error) {
params := msig5.TxnIDParams{ID: msig5.TxnID(id)}
params := msig6.TxnIDParams{ID: msig6.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)

View File

@ -0,0 +1,119 @@
package multisig
import (
"bytes"
"encoding/binary"
adt6 "github.com/filecoin-project/specs-actors/v6/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"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
msig6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/multisig"
)
var _ State = (*state6)(nil)
func load6(store adt.Store, root cid.Cid) (State, error) {
out := state6{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
func make6(store adt.Store, signers []address.Address, threshold uint64, startEpoch abi.ChainEpoch, unlockDuration abi.ChainEpoch, initialBalance abi.TokenAmount) (State, error) {
out := state6{store: store}
out.State = msig6.State{}
out.State.Signers = signers
out.State.NumApprovalsThreshold = threshold
out.State.StartEpoch = startEpoch
out.State.UnlockDuration = unlockDuration
out.State.InitialBalance = initialBalance
em, err := adt6.StoreEmptyMap(store, builtin6.DefaultHamtBitwidth)
if err != nil {
return nil, err
}
out.State.PendingTxns = em
return &out, nil
}
type state6 struct {
msig6.State
store adt.Store
}
func (s *state6) LockedBalance(currEpoch abi.ChainEpoch) (abi.TokenAmount, error) {
return s.State.AmountLocked(currEpoch - s.State.StartEpoch), nil
}
func (s *state6) StartEpoch() (abi.ChainEpoch, error) {
return s.State.StartEpoch, nil
}
func (s *state6) UnlockDuration() (abi.ChainEpoch, error) {
return s.State.UnlockDuration, nil
}
func (s *state6) InitialBalance() (abi.TokenAmount, error) {
return s.State.InitialBalance, nil
}
func (s *state6) Threshold() (uint64, error) {
return s.State.NumApprovalsThreshold, nil
}
func (s *state6) Signers() ([]address.Address, error) {
return s.State.Signers, nil
}
func (s *state6) ForEachPendingTxn(cb func(id int64, txn Transaction) error) error {
arr, err := adt6.AsMap(s.store, s.State.PendingTxns, builtin6.DefaultHamtBitwidth)
if err != nil {
return err
}
var out msig6.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 *state6) PendingTxnChanged(other State) (bool, error) {
other6, ok := other.(*state6)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.PendingTxns.Equals(other6.PendingTxns), nil
}
func (s *state6) transactions() (adt.Map, error) {
return adt6.AsMap(s.store, s.PendingTxns, builtin6.DefaultHamtBitwidth)
}
func (s *state6) decodeTransaction(val *cbg.Deferred) (Transaction, error) {
var tx msig6.Transaction
if err := tx.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return Transaction{}, err
}
return tx, nil
}
func (s *state6) GetState() interface{} {
return &s.State
}

View File

@ -0,0 +1,74 @@
package paych
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
init6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/init"
paych6 "github.com/filecoin-project/specs-actors/v6/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 message6 struct{ from address.Address }
func (m message6) Create(to address.Address, initialAmount abi.TokenAmount) (*types.Message, error) {
params, aerr := actors.SerializeParams(&paych6.ConstructorParams{From: m.from, To: to})
if aerr != nil {
return nil, aerr
}
enc, aerr := actors.SerializeParams(&init6.ExecParams{
CodeCID: builtin6.PaymentChannelActorCodeID,
ConstructorParams: params,
})
if aerr != nil {
return nil, aerr
}
return &types.Message{
To: init_.Address,
From: m.from,
Value: initialAmount,
Method: builtin6.MethodsInit.Exec,
Params: enc,
}, nil
}
func (m message6) Update(paych address.Address, sv *SignedVoucher, secret []byte) (*types.Message, error) {
params, aerr := actors.SerializeParams(&paych6.UpdateChannelStateParams{
Sv: *sv,
Secret: secret,
})
if aerr != nil {
return nil, aerr
}
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin6.MethodsPaych.UpdateChannelState,
Params: params,
}, nil
}
func (m message6) Settle(paych address.Address) (*types.Message, error) {
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin6.MethodsPaych.Settle,
}, nil
}
func (m message6) Collect(paych address.Address) (*types.Message, error) {
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin6.MethodsPaych.Collect,
}, nil
}

View File

@ -25,6 +25,8 @@ import (
builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin"
builtin6 "github.com/filecoin-project/specs-actors/v6/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"
@ -52,6 +54,10 @@ func init() {
builtin.RegisterActorState(builtin5.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load5(store, root)
})
builtin.RegisterActorState(builtin6.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load6(store, root)
})
}
// Load returns an abstract copy of payment channel state, irregardless of actor version
@ -73,6 +79,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
case builtin5.PaymentChannelActorCodeID:
return load5(store, act.Head)
case builtin6.PaymentChannelActorCodeID:
return load6(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@ -95,6 +104,9 @@ func MakeState(store adt.Store, av actors.Version) (State, error) {
case actors.Version5:
return make5(store)
case actors.Version6:
return make6(store)
}
return nil, xerrors.Errorf("unknown actor version %d", av)
}
@ -117,6 +129,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) {
case actors.Version5:
return builtin5.PaymentChannelActorCodeID, nil
case actors.Version6:
return builtin6.PaymentChannelActorCodeID, nil
}
return cid.Undef, xerrors.Errorf("unknown actor version %d", av)
@ -170,7 +185,7 @@ func DecodeSignedVoucher(s string) (*SignedVoucher, error) {
return &sv, nil
}
var Methods = builtin5.MethodsPaych
var Methods = builtin6.MethodsPaych
func Message(version actors.Version, from address.Address) MessageBuilder {
switch version {
@ -190,6 +205,9 @@ func Message(version actors.Version, from address.Address) MessageBuilder {
case actors.Version5:
return message5{from}
case actors.Version6:
return message6{from}
default:
panic(fmt.Sprintf("unsupported actors version: %d", version))
}

View File

@ -0,0 +1,114 @@
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"
paych6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/paych"
adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt"
)
var _ State = (*state6)(nil)
func load6(store adt.Store, root cid.Cid) (State, error) {
out := state6{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
func make6(store adt.Store) (State, error) {
out := state6{store: store}
out.State = paych6.State{}
return &out, nil
}
type state6 struct {
paych6.State
store adt.Store
lsAmt *adt6.Array
}
// Channel owner, who has funded the actor
func (s *state6) From() (address.Address, error) {
return s.State.From, nil
}
// Recipient of payouts from channel
func (s *state6) To() (address.Address, error) {
return s.State.To, nil
}
// Height at which the channel can be `Collected`
func (s *state6) SettlingAt() (abi.ChainEpoch, error) {
return s.State.SettlingAt, nil
}
// Amount successfully redeemed through the payment channel, paid out on `Collect()`
func (s *state6) ToSend() (abi.TokenAmount, error) {
return s.State.ToSend, nil
}
func (s *state6) getOrLoadLsAmt() (*adt6.Array, error) {
if s.lsAmt != nil {
return s.lsAmt, nil
}
// Get the lane state from the chain
lsamt, err := adt6.AsArray(s.store, s.State.LaneStates, paych6.LaneStatesAmtBitwidth)
if err != nil {
return nil, err
}
s.lsAmt = lsamt
return lsamt, nil
}
// Get total number of lanes
func (s *state6) LaneCount() (uint64, error) {
lsamt, err := s.getOrLoadLsAmt()
if err != nil {
return 0, err
}
return lsamt.Length(), nil
}
func (s *state6) GetState() interface{} {
return &s.State
}
// Iterate lane states
func (s *state6) 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 paych6.LaneState
return lsamt.ForEach(&ls, func(i int64) error {
return cb(uint64(i), &laneState6{ls})
})
}
type laneState6 struct {
paych6.LaneState
}
func (ls *laneState6) Redeemed() (big.Int, error) {
return ls.LaneState.Redeemed, nil
}
func (ls *laneState6) Nonce() (uint64, error) {
return ls.LaneState.Nonce, nil
}

View File

@ -24,6 +24,8 @@ import (
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
)
func init() {
@ -47,11 +49,15 @@ func init() {
builtin.RegisterActorState(builtin5.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load5(store, root)
})
builtin.RegisterActorState(builtin6.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load6(store, root)
})
}
var (
Address = builtin5.StoragePowerActorAddr
Methods = builtin5.MethodsPower
Address = builtin6.StoragePowerActorAddr
Methods = builtin6.MethodsPower
)
func Load(store adt.Store, act *types.Actor) (State, error) {
@ -72,6 +78,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
case builtin5.StoragePowerActorCodeID:
return load5(store, act.Head)
case builtin6.StoragePowerActorCodeID:
return load6(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@ -94,6 +103,9 @@ func MakeState(store adt.Store, av actors.Version) (State, error) {
case actors.Version5:
return make5(store)
case actors.Version6:
return make6(store)
}
return nil, xerrors.Errorf("unknown actor version %d", av)
}
@ -116,6 +128,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) {
case actors.Version5:
return builtin5.StoragePowerActorCodeID, nil
case actors.Version6:
return builtin6.StoragePowerActorCodeID, nil
}
return cid.Undef, xerrors.Errorf("unknown actor version %d", av)

View File

@ -0,0 +1,187 @@
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"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
power6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/power"
adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt"
)
var _ State = (*state6)(nil)
func load6(store adt.Store, root cid.Cid) (State, error) {
out := state6{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
func make6(store adt.Store) (State, error) {
out := state6{store: store}
s, err := power6.ConstructState(store)
if err != nil {
return nil, err
}
out.State = *s
return &out, nil
}
type state6 struct {
power6.State
store adt.Store
}
func (s *state6) TotalLocked() (abi.TokenAmount, error) {
return s.TotalPledgeCollateral, nil
}
func (s *state6) 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 *state6) TotalCommitted() (Claim, error) {
return Claim{
RawBytePower: s.TotalBytesCommitted,
QualityAdjPower: s.TotalQABytesCommitted,
}, nil
}
func (s *state6) MinerPower(addr address.Address) (Claim, bool, error) {
claims, err := s.claims()
if err != nil {
return Claim{}, false, err
}
var claim power6.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 *state6) MinerNominalPowerMeetsConsensusMinimum(a address.Address) (bool, error) {
return s.State.MinerNominalPowerMeetsConsensusMinimum(s.store, a)
}
func (s *state6) TotalPowerSmoothed() (builtin.FilterEstimate, error) {
return builtin.FromV6FilterEstimate(s.State.ThisEpochQAPowerSmoothed), nil
}
func (s *state6) MinerCounts() (uint64, uint64, error) {
return uint64(s.State.MinerAboveMinPowerCount), uint64(s.State.MinerCount), nil
}
func (s *state6) 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 *state6) ForEachClaim(cb func(miner address.Address, claim Claim) error) error {
claims, err := s.claims()
if err != nil {
return err
}
var claim power6.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 *state6) ClaimsChanged(other State) (bool, error) {
other6, ok := other.(*state6)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.Claims.Equals(other6.State.Claims), nil
}
func (s *state6) SetTotalQualityAdjPower(p abi.StoragePower) error {
s.State.TotalQualityAdjPower = p
return nil
}
func (s *state6) SetTotalRawBytePower(p abi.StoragePower) error {
s.State.TotalRawBytePower = p
return nil
}
func (s *state6) SetThisEpochQualityAdjPower(p abi.StoragePower) error {
s.State.ThisEpochQualityAdjPower = p
return nil
}
func (s *state6) SetThisEpochRawBytePower(p abi.StoragePower) error {
s.State.ThisEpochRawBytePower = p
return nil
}
func (s *state6) GetState() interface{} {
return &s.State
}
func (s *state6) claims() (adt.Map, error) {
return adt6.AsMap(s.store, s.Claims, builtin6.DefaultHamtBitwidth)
}
func (s *state6) decodeClaim(val *cbg.Deferred) (Claim, error) {
var ci power6.Claim
if err := ci.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return Claim{}, err
}
return fromV6Claim(ci), nil
}
func fromV6Claim(v6 power6.Claim) Claim {
return Claim{
RawBytePower: v6.RawBytePower,
QualityAdjPower: v6.QualityAdjPower,
}
}

View File

@ -19,6 +19,8 @@ import (
builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin"
builtin6 "github.com/filecoin-project/specs-actors/v6/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"
@ -45,11 +47,15 @@ func init() {
builtin.RegisterActorState(builtin5.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load5(store, root)
})
builtin.RegisterActorState(builtin6.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load6(store, root)
})
}
var (
Address = builtin5.RewardActorAddr
Methods = builtin5.MethodsReward
Address = builtin6.RewardActorAddr
Methods = builtin6.MethodsReward
)
func Load(store adt.Store, act *types.Actor) (State, error) {
@ -70,6 +76,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
case builtin5.RewardActorCodeID:
return load5(store, act.Head)
case builtin6.RewardActorCodeID:
return load6(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@ -92,6 +101,9 @@ func MakeState(store adt.Store, av actors.Version, currRealizedPower abi.Storage
case actors.Version5:
return make5(store, currRealizedPower)
case actors.Version6:
return make6(store, currRealizedPower)
}
return nil, xerrors.Errorf("unknown actor version %d", av)
}
@ -114,6 +126,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) {
case actors.Version5:
return builtin5.RewardActorCodeID, nil
case actors.Version6:
return builtin6.RewardActorCodeID, nil
}
return cid.Undef, xerrors.Errorf("unknown actor version %d", av)

View File

@ -0,0 +1,98 @@
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"
miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner"
reward6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/reward"
smoothing6 "github.com/filecoin-project/specs-actors/v6/actors/util/smoothing"
)
var _ State = (*state6)(nil)
func load6(store adt.Store, root cid.Cid) (State, error) {
out := state6{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
func make6(store adt.Store, currRealizedPower abi.StoragePower) (State, error) {
out := state6{store: store}
out.State = *reward6.ConstructState(currRealizedPower)
return &out, nil
}
type state6 struct {
reward6.State
store adt.Store
}
func (s *state6) ThisEpochReward() (abi.TokenAmount, error) {
return s.State.ThisEpochReward, nil
}
func (s *state6) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) {
return builtin.FilterEstimate{
PositionEstimate: s.State.ThisEpochRewardSmoothed.PositionEstimate,
VelocityEstimate: s.State.ThisEpochRewardSmoothed.VelocityEstimate,
}, nil
}
func (s *state6) ThisEpochBaselinePower() (abi.StoragePower, error) {
return s.State.ThisEpochBaselinePower, nil
}
func (s *state6) TotalStoragePowerReward() (abi.TokenAmount, error) {
return s.State.TotalStoragePowerReward, nil
}
func (s *state6) EffectiveBaselinePower() (abi.StoragePower, error) {
return s.State.EffectiveBaselinePower, nil
}
func (s *state6) EffectiveNetworkTime() (abi.ChainEpoch, error) {
return s.State.EffectiveNetworkTime, nil
}
func (s *state6) CumsumBaseline() (reward6.Spacetime, error) {
return s.State.CumsumBaseline, nil
}
func (s *state6) CumsumRealized() (reward6.Spacetime, error) {
return s.State.CumsumRealized, nil
}
func (s *state6) InitialPledgeForPower(qaPower abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) {
return miner6.InitialPledgeForPower(
qaPower,
s.State.ThisEpochBaselinePower,
s.State.ThisEpochRewardSmoothed,
smoothing6.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
},
circSupply,
), nil
}
func (s *state6) PreCommitDepositForPower(networkQAPower builtin.FilterEstimate, sectorWeight abi.StoragePower) (abi.TokenAmount, error) {
return miner6.PreCommitDepositForPower(s.State.ThisEpochRewardSmoothed,
smoothing6.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
},
sectorWeight), nil
}
func (s *state6) GetState() interface{} {
return &s.State
}

View File

@ -15,10 +15,12 @@ import (
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
)
var (
Address = builtin5.SystemActorAddr
Address = builtin6.SystemActorAddr
)
func MakeState(store adt.Store, av actors.Version) (State, error) {
@ -39,6 +41,9 @@ func MakeState(store adt.Store, av actors.Version) (State, error) {
case actors.Version5:
return make5(store)
case actors.Version6:
return make6(store)
}
return nil, xerrors.Errorf("unknown actor version %d", av)
}
@ -61,6 +66,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) {
case actors.Version5:
return builtin5.SystemActorCodeID, nil
case actors.Version6:
return builtin6.SystemActorCodeID, nil
}
return cid.Undef, xerrors.Errorf("unknown actor version %d", av)

View File

@ -0,0 +1,35 @@
package system
import (
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/chain/actors/adt"
system6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/system"
)
var _ State = (*state6)(nil)
func load6(store adt.Store, root cid.Cid) (State, error) {
out := state6{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
func make6(store adt.Store) (State, error) {
out := state6{store: store}
out.State = system6.State{}
return &out, nil
}
type state6 struct {
system6.State
store adt.Store
}
func (s *state6) GetState() interface{} {
return &s.State
}

View File

@ -0,0 +1,75 @@
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"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
verifreg6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/verifreg"
adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt"
)
var _ State = (*state6)(nil)
func load6(store adt.Store, root cid.Cid) (State, error) {
out := state6{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
func make6(store adt.Store, rootKeyAddress address.Address) (State, error) {
out := state6{store: store}
s, err := verifreg6.ConstructState(store, rootKeyAddress)
if err != nil {
return nil, err
}
out.State = *s
return &out, nil
}
type state6 struct {
verifreg6.State
store adt.Store
}
func (s *state6) RootKey() (address.Address, error) {
return s.State.RootKey, nil
}
func (s *state6) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) {
return getDataCap(s.store, actors.Version6, s.verifiedClients, addr)
}
func (s *state6) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) {
return getDataCap(s.store, actors.Version6, s.verifiers, addr)
}
func (s *state6) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error {
return forEachCap(s.store, actors.Version6, s.verifiers, cb)
}
func (s *state6) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error {
return forEachCap(s.store, actors.Version6, s.verifiedClients, cb)
}
func (s *state6) verifiedClients() (adt.Map, error) {
return adt6.AsMap(s.store, s.VerifiedClients, builtin6.DefaultHamtBitwidth)
}
func (s *state6) verifiers() (adt.Map, error) {
return adt6.AsMap(s.store, s.Verifiers, builtin6.DefaultHamtBitwidth)
}
func (s *state6) GetState() interface{} {
return &s.State
}

View File

@ -19,6 +19,8 @@ import (
builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin"
builtin6 "github.com/filecoin-project/specs-actors/v6/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"
@ -47,11 +49,15 @@ func init() {
return load5(store, root)
})
builtin.RegisterActorState(builtin6.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load6(store, root)
})
}
var (
Address = builtin5.VerifiedRegistryActorAddr
Methods = builtin5.MethodsVerifiedRegistry
Address = builtin6.VerifiedRegistryActorAddr
Methods = builtin6.MethodsVerifiedRegistry
)
func Load(store adt.Store, act *types.Actor) (State, error) {
@ -72,6 +78,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
case builtin5.VerifiedRegistryActorCodeID:
return load5(store, act.Head)
case builtin6.VerifiedRegistryActorCodeID:
return load6(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@ -94,6 +103,9 @@ func MakeState(store adt.Store, av actors.Version, rootKeyAddress address.Addres
case actors.Version5:
return make5(store, rootKeyAddress)
case actors.Version6:
return make6(store, rootKeyAddress)
}
return nil, xerrors.Errorf("unknown actor version %d", av)
}
@ -116,6 +128,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) {
case actors.Version5:
return builtin5.VerifiedRegistryActorCodeID, nil
case actors.Version6:
return builtin6.VerifiedRegistryActorCodeID, nil
}
return cid.Undef, xerrors.Errorf("unknown actor version %d", av)

View File

@ -35,14 +35,19 @@ import (
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"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
market6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/market"
miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner"
verifreg6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/verifreg"
paych6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/paych"
)
const (
ChainFinality = miner5.ChainFinality
ChainFinality = miner6.ChainFinality
SealRandomnessLookback = ChainFinality
PaychSettleDelay = paych5.SettleDelay
MaxPreCommitRandomnessLookback = builtin5.EpochsInDay + SealRandomnessLookback
PaychSettleDelay = paych6.SettleDelay
MaxPreCommitRandomnessLookback = builtin6.EpochsInDay + SealRandomnessLookback
)
// SetSupportedProofTypes sets supported proof types, across all actor versions.
@ -65,6 +70,8 @@ func SetSupportedProofTypes(types ...abi.RegisteredSealProof) {
miner5.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types))
miner6.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types))
AddSupportedProofTypes(types...)
}
@ -103,6 +110,15 @@ func AddSupportedProofTypes(types ...abi.RegisteredSealProof) {
miner5.WindowPoStProofTypes[wpp] = struct{}{}
miner6.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
wpp, err = t.RegisteredWindowPoStProof()
if err != nil {
// Fine to panic, this is a test-only method
panic(err)
}
miner6.WindowPoStProofTypes[wpp] = struct{}{}
}
}
@ -121,11 +137,13 @@ func SetPreCommitChallengeDelay(delay abi.ChainEpoch) {
miner5.PreCommitChallengeDelay = delay
miner6.PreCommitChallengeDelay = delay
}
// TODO: this function shouldn't really exist. Instead, the API should expose the precommit delay.
func GetPreCommitChallengeDelay() abi.ChainEpoch {
return miner5.PreCommitChallengeDelay
return miner6.PreCommitChallengeDelay
}
// SetConsensusMinerMinPower sets the minimum power of an individual miner must
@ -151,6 +169,10 @@ func SetConsensusMinerMinPower(p abi.StoragePower) {
policy.ConsensusMinerMinPower = p
}
for _, policy := range builtin6.PoStProofPolicies {
policy.ConsensusMinerMinPower = p
}
}
// SetMinVerifiedDealSize sets the minimum size of a verified deal. This should
@ -167,6 +189,8 @@ func SetMinVerifiedDealSize(size abi.StoragePower) {
verifreg5.MinVerifiedDealSize = size
verifreg6.MinVerifiedDealSize = size
}
func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) (abi.ChainEpoch, error) {
@ -192,6 +216,10 @@ func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) (a
return miner5.MaxProveCommitDuration[t], nil
case actors.Version6:
return miner6.MaxProveCommitDuration[t], nil
default:
return 0, xerrors.Errorf("unsupported actors version")
}
@ -222,6 +250,11 @@ func SetProviderCollateralSupplyTarget(num, denom big.Int) {
Denominator: denom,
}
market6.ProviderCollateralSupplyTarget = builtin6.BigFrac{
Numerator: num,
Denominator: denom,
}
}
func DealProviderCollateralBounds(
@ -260,13 +293,18 @@ func DealProviderCollateralBounds(
min, max := market5.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil)
return min, max, nil
case actors.Version6:
min, max := market6.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil)
return min, max, nil
default:
return big.Zero(), big.Zero(), xerrors.Errorf("unsupported actors version")
}
}
func DealDurationBounds(pieceSize abi.PaddedPieceSize) (min, max abi.ChainEpoch) {
return market5.DealDurationBounds(pieceSize)
return market6.DealDurationBounds(pieceSize)
}
// Sets the challenge window and scales the proving period to match (such that
@ -300,6 +338,13 @@ func SetWPoStChallengeWindow(period abi.ChainEpoch) {
// scale it if we're scaling the challenge period.
miner5.WPoStDisputeWindow = period * 30
miner6.WPoStChallengeWindow = period
miner6.WPoStProvingPeriod = period * abi.ChainEpoch(miner6.WPoStPeriodDeadlines)
// by default, this is 2x finality which is 30 periods.
// scale it if we're scaling the challenge period.
miner6.WPoStDisputeWindow = period * 30
}
func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch {
@ -312,15 +357,15 @@ func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch {
}
func GetMaxSectorExpirationExtension() abi.ChainEpoch {
return miner5.MaxSectorExpirationExtension
return miner6.MaxSectorExpirationExtension
}
func GetMinSectorExpiration() abi.ChainEpoch {
return miner5.MinSectorExpiration
return miner6.MinSectorExpiration
}
func GetMaxPoStPartitions(nv network.Version, p abi.RegisteredPoStProof) (int, error) {
sectorsPerPart, err := builtin5.PoStProofWindowPoStPartitionSectors(p)
sectorsPerPart, err := builtin6.PoStProofWindowPoStPartitionSectors(p)
if err != nil {
return 0, err
}
@ -333,8 +378,8 @@ func GetMaxPoStPartitions(nv network.Version, p abi.RegisteredPoStProof) (int, e
func GetDefaultSectorSize() abi.SectorSize {
// supported sector sizes are the same across versions.
szs := make([]abi.SectorSize, 0, len(miner5.PreCommitSealProofTypesV8))
for spt := range miner5.PreCommitSealProofTypesV8 {
szs := make([]abi.SectorSize, 0, len(miner6.PreCommitSealProofTypesV8))
for spt := range miner6.PreCommitSealProofTypesV8 {
ss, err := spt.SectorSize()
if err != nil {
panic(err)
@ -359,7 +404,7 @@ func GetSectorMaxLifetime(proof abi.RegisteredSealProof, nwVer network.Version)
return builtin4.SealProofPoliciesV0[proof].SectorMaxLifetime
}
return builtin5.SealProofPoliciesV11[proof].SectorMaxLifetime
return builtin6.SealProofPoliciesV11[proof].SectorMaxLifetime
}
func GetAddressedSectorsMax(nwVer network.Version) (int, error) {
@ -384,6 +429,9 @@ func GetAddressedSectorsMax(nwVer network.Version) (int, error) {
case actors.Version5:
return miner5.AddressedSectorsMax, nil
case actors.Version6:
return miner6.AddressedSectorsMax, nil
default:
return 0, xerrors.Errorf("unsupported network version")
}
@ -417,12 +465,16 @@ func GetDeclarationsMax(nwVer network.Version) (int, error) {
return miner5.DeclarationsMax, nil
case actors.Version6:
return miner6.DeclarationsMax, nil
default:
return 0, xerrors.Errorf("unsupported network version")
}
}
func AggregateNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.TokenAmount) (abi.TokenAmount, error) {
func AggregateProveCommitNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.TokenAmount) (abi.TokenAmount, error) {
v, err := actors.VersionForNetwork(nwVer)
if err != nil {
return big.Zero(), err
@ -449,6 +501,46 @@ func AggregateNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.T
return miner5.AggregateNetworkFee(aggregateSize, baseFee), nil
case actors.Version6:
return miner6.AggregateProveCommitNetworkFee(aggregateSize, baseFee), nil
default:
return big.Zero(), xerrors.Errorf("unsupported network version")
}
}
func AggregatePreCommitNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.TokenAmount) (abi.TokenAmount, error) {
v, err := actors.VersionForNetwork(nwVer)
if err != nil {
return big.Zero(), err
}
switch v {
case actors.Version0:
return big.Zero(), nil
case actors.Version2:
return big.Zero(), nil
case actors.Version3:
return big.Zero(), nil
case actors.Version4:
return big.Zero(), nil
case actors.Version5:
return big.Zero(), nil
case actors.Version6:
return miner6.AggregatePreCommitNetworkFee(aggregateSize, baseFee), nil
default:
return big.Zero(), xerrors.Errorf("unsupported network version")
}

View File

@ -63,7 +63,7 @@ func AddSupportedProofTypes(types ...abi.RegisteredSealProof) {
miner{{.}}.PreCommitSealProofTypesV7[t] = struct{}{}
miner{{.}}.PreCommitSealProofTypesV7[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
miner{{.}}.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
{{else}}
{{else if (eq . 5)}}
miner{{.}}.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
wpp, err := t.RegisteredWindowPoStProof()
if err != nil {
@ -71,6 +71,15 @@ func AddSupportedProofTypes(types ...abi.RegisteredSealProof) {
panic(err)
}
miner{{.}}.WindowPoStProofTypes[wpp] = struct{}{}
{{else}}
miner{{.}}.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
wpp, err = t.RegisteredWindowPoStProof()
if err != nil {
// Fine to panic, this is a test-only method
panic(err)
}
miner{{.}}.WindowPoStProofTypes[wpp] = struct{}{}
{{end}}
{{end}}
@ -285,7 +294,7 @@ func GetDeclarationsMax(nwVer network.Version) (int, error) {
}
}
func AggregateNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.TokenAmount) (abi.TokenAmount, error) {
func AggregateProveCommitNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.TokenAmount) (abi.TokenAmount, error) {
v, err := actors.VersionForNetwork(nwVer)
if err != nil {
return big.Zero(), err
@ -293,10 +302,31 @@ func AggregateNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.T
switch v {
{{range .versions}}
case actors.Version{{.}}:
{{if (le . 4)}}
return big.Zero(), nil
{{else}}
{{if (ge . 6)}}
return miner{{.}}.AggregateProveCommitNetworkFee(aggregateSize, baseFee), nil
{{else if (eq . 5)}}
return miner{{.}}.AggregateNetworkFee(aggregateSize, baseFee), nil
{{else}}
return big.Zero(), nil
{{end}}
{{end}}
default:
return big.Zero(), xerrors.Errorf("unsupported network version")
}
}
func AggregatePreCommitNetworkFee(nwVer network.Version, aggregateSize int, baseFee abi.TokenAmount) (abi.TokenAmount, error) {
v, err := actors.VersionForNetwork(nwVer)
if err != nil {
return big.Zero(), err
}
switch v {
{{range .versions}}
case actors.Version{{.}}:
{{if (ge . 6)}}
return miner{{.}}.AggregatePreCommitNetworkFee(aggregateSize, baseFee), nil
{{else}}
return big.Zero(), nil
{{end}}
{{end}}
default:

View File

@ -8,9 +8,9 @@ import (
type Version int
var LatestVersion = 5
var LatestVersion = 6
var Versions = []int{0, 2, 3, 4, LatestVersion}
var Versions = []int{0, 2, 3, 4, 5, LatestVersion}
const (
Version0 Version = 0
@ -18,6 +18,7 @@ const (
Version3 Version = 3
Version4 Version = 4
Version5 Version = 5
Version6 Version = 6
)
// Converts a network version into an actors adt version.
@ -33,6 +34,8 @@ func VersionForNetwork(version network.Version) (Version, error) {
return Version4, nil
case network.Version13:
return Version5, nil
case network.Version14:
return Version6, nil
default:
return -1, fmt.Errorf("unsupported network version %d", version)
}

View File

@ -54,7 +54,8 @@ func (mb *mockBeacon) VerifyEntry(from types.BeaconEntry, to types.BeaconEntry)
}
func (mb *mockBeacon) MaxBeaconRoundForEpoch(epoch abi.ChainEpoch) uint64 {
return uint64(epoch)
// offset for better testing
return uint64(epoch + 100)
}
var _ RandomBeacon = (*mockBeacon)(nil)

View File

@ -4,6 +4,8 @@ import (
"context"
"sync/atomic"
"github.com/filecoin-project/lotus/chain/rand"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"go.opencensus.io/stats"
@ -19,6 +21,7 @@ import (
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"
exported6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/exported"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
@ -42,6 +45,7 @@ func NewActorRegistry() *vm.ActorRegistry {
inv.Register(vm.ActorsVersionPredicate(actors.Version3), exported3.BuiltinActors()...)
inv.Register(vm.ActorsVersionPredicate(actors.Version4), exported4.BuiltinActors()...)
inv.Register(vm.ActorsVersionPredicate(actors.Version5), exported5.BuiltinActors()...)
inv.Register(vm.ActorsVersionPredicate(actors.Version6), exported6.BuiltinActors()...)
return inv
}
@ -278,7 +282,7 @@ func (t *TipSetExecutor) ExecuteTipSet(ctx context.Context, sm *stmgr.StateManag
parentEpoch = parent.Height
}
r := store.NewChainRand(sm.ChainStore(), ts.Cids())
r := rand.NewStateRand(sm.ChainStore(), ts.Cids(), sm.Beacon())
blkmsgs, err := sm.ChainStore().BlockMsgsForTipset(ts)
if err != nil {

View File

@ -9,6 +9,8 @@ import (
"strings"
"time"
"github.com/filecoin-project/lotus/chain/rand"
"github.com/hashicorp/go-multierror"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
@ -219,7 +221,7 @@ func (filec *FilecoinEC) ValidateBlock(ctx context.Context, b *types.FullBlock)
return xerrors.Errorf("failed to marshal miner address to cbor: %w", err)
}
vrfBase, err := store.DrawRandomness(rBeacon.Data, crypto.DomainSeparationTag_ElectionProofProduction, h.Height, buf.Bytes())
vrfBase, err := rand.DrawRandomness(rBeacon.Data, crypto.DomainSeparationTag_ElectionProofProduction, h.Height, buf.Bytes())
if err != nil {
return xerrors.Errorf("could not draw randomness: %w", err)
}
@ -283,7 +285,7 @@ func (filec *FilecoinEC) ValidateBlock(ctx context.Context, b *types.FullBlock)
beaconBase = h.BeaconEntries[len(h.BeaconEntries)-1]
}
vrfBase, err := store.DrawRandomness(beaconBase.Data, crypto.DomainSeparationTag_TicketProduction, h.Height-build.TicketRandomnessLookback, buf.Bytes())
vrfBase, err := rand.DrawRandomness(beaconBase.Data, crypto.DomainSeparationTag_TicketProduction, h.Height-build.TicketRandomnessLookback, buf.Bytes())
if err != nil {
return xerrors.Errorf("failed to compute vrf base for ticket: %w", err)
}
@ -388,7 +390,7 @@ func (filec *FilecoinEC) VerifyWinningPoStProof(ctx context.Context, nv network.
rbase = h.BeaconEntries[len(h.BeaconEntries)-1]
}
rand, err := store.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, h.Height, buf.Bytes())
rand, err := rand.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, h.Height, buf.Bytes())
if err != nil {
return xerrors.Errorf("failed to get randomness for verifying winning post proof: %w", err)
}
@ -530,6 +532,12 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
smArr := blockadt.MakeEmptyArray(tmpstore)
for i, m := range b.SecpkMessages {
if filec.sm.GetNtwkVersion(ctx, b.Header.Height) >= network.Version14 {
if m.Signature.Type != crypto.SigTypeSecp256k1 {
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
}
}
if err := checkMsg(m); err != nil {
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
}

View File

@ -5,6 +5,8 @@ import (
"runtime"
"time"
"github.com/filecoin-project/specs-actors/v6/actors/migration/nv14"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"golang.org/x/xerrors"
@ -137,7 +139,25 @@ func DefaultUpgradeSchedule() stmgr.UpgradeSchedule {
DontStartWithin: 15,
StopWithin: 5,
}},
Expensive: true}}
Expensive: true,
}, {
Height: build.UpgradeChocolateHeight,
Network: network.Version14,
Migration: UpgradeActorsV6,
PreMigrations: []stmgr.PreMigration{{
PreMigration: PreUpgradeActorsV6,
StartWithin: 120,
DontStartWithin: 60,
StopWithin: 35,
}, {
PreMigration: PreUpgradeActorsV6,
StartWithin: 30,
DontStartWithin: 15,
StopWithin: 5,
}},
Expensive: true,
},
}
for _, u := range updates {
if u.Height < 0 {
@ -1091,6 +1111,92 @@ func upgradeActorsV5Common(
return newRoot, nil
}
func UpgradeActorsV6(ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache, cb stmgr.ExecMonitor, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
// Use all the CPUs except 3.
workerCount := runtime.NumCPU() - 3
if workerCount <= 0 {
workerCount = 1
}
config := nv14.Config{
MaxWorkers: uint(workerCount),
JobQueueSize: 1000,
ResultQueueSize: 100,
ProgressLogPeriod: 10 * time.Second,
}
newRoot, err := upgradeActorsV6Common(ctx, sm, cache, root, epoch, ts, config)
if err != nil {
return cid.Undef, xerrors.Errorf("migrating actors v5 state: %w", err)
}
return newRoot, nil
}
func PreUpgradeActorsV6(ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) error {
// Use half the CPUs for pre-migration, but leave at least 3.
workerCount := runtime.NumCPU()
if workerCount <= 4 {
workerCount = 1
} else {
workerCount /= 2
}
config := nv14.Config{MaxWorkers: uint(workerCount)}
_, err := upgradeActorsV6Common(ctx, sm, cache, root, epoch, ts, config)
return err
}
func upgradeActorsV6Common(
ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache,
root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet,
config nv14.Config,
) (cid.Cid, error) {
buf := blockstore.NewTieredBstore(sm.ChainStore().StateBlockstore(), blockstore.NewMemorySync())
store := store.ActorStore(ctx, buf)
// Load the state root.
var stateRoot types.StateRoot
if err := store.Get(ctx, root, &stateRoot); err != nil {
return cid.Undef, xerrors.Errorf("failed to decode state root: %w", err)
}
if stateRoot.Version != types.StateTreeVersion4 {
return cid.Undef, xerrors.Errorf(
"expected state root version 4 for actors v6 upgrade, got %d",
stateRoot.Version,
)
}
// Perform the migration
newHamtRoot, err := nv14.MigrateStateTree(ctx, store, stateRoot.Actors, epoch, config, migrationLogger{}, cache)
if err != nil {
return cid.Undef, xerrors.Errorf("upgrading to actors v5: %w", err)
}
// Persist the result.
newRoot, err := store.Put(ctx, &types.StateRoot{
Version: types.StateTreeVersion4,
Actors: newHamtRoot,
Info: stateRoot.Info,
})
if err != nil {
return cid.Undef, xerrors.Errorf("failed to persist new state root: %w", err)
}
// Persist the new tree.
{
from := buf
to := buf.Read()
if err := vm.Copy(ctx, from, to, newRoot); err != nil {
return cid.Undef, xerrors.Errorf("copying migrated tree: %w", err)
}
}
return newRoot, nil
}
type migrationLogger struct{}
func (ml migrationLogger) Log(level rt.LogLevel, msg string, args ...interface{}) {

View File

@ -9,6 +9,8 @@ import (
"sync/atomic"
"time"
"github.com/filecoin-project/lotus/chain/rand"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/go-address"
@ -246,11 +248,6 @@ func NewGeneratorWithSectorsAndUpgradeSchedule(numSectors int, us stmgr.UpgradeS
mgen[genesis2.MinerAddress(uint64(i))] = &wppProvider{}
}
sm, err := stmgr.NewStateManager(cs, filcns.NewTipSetExecutor(), sys, us)
if err != nil {
return nil, xerrors.Errorf("initing stmgr: %w", err)
}
miners := []address.Address{maddr1, maddr2}
beac := beacon.Schedule{{Start: 0, Beacon: beacon.NewMockBeacon(time.Second)}}
@ -259,6 +256,11 @@ func NewGeneratorWithSectorsAndUpgradeSchedule(numSectors int, us stmgr.UpgradeS
//return nil, xerrors.Errorf("creating drand beacon: %w", err)
//}
sm, err := stmgr.NewStateManager(cs, filcns.NewTipSetExecutor(), sys, us, beac)
if err != nil {
return nil, xerrors.Errorf("initing stmgr: %w", err)
}
gen := &ChainGen{
bs: bs,
cs: cs,
@ -307,6 +309,10 @@ func (cg *ChainGen) ChainStore() *store.ChainStore {
return cg.cs
}
func (cg *ChainGen) BeaconSchedule() beacon.Schedule {
return cg.beacon
}
func (cg *ChainGen) Genesis() *types.BlockHeader {
return cg.genesis
}
@ -365,7 +371,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
buf.Write(pts.MinTicket().VRFProof)
}
ticketRand, err := store.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_TicketProduction, round-build.TicketRandomnessLookback, buf.Bytes())
ticketRand, err := rand.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_TicketProduction, round-build.TicketRandomnessLookback, buf.Bytes())
if err != nil {
return nil, nil, nil, err
}
@ -397,12 +403,15 @@ type MinedTipSet struct {
}
func (cg *ChainGen) NextTipSet() (*MinedTipSet, error) {
mts, err := cg.NextTipSetFromMiners(cg.CurTipset.TipSet(), cg.Miners, 0)
return cg.NextTipSetWithNulls(0)
}
func (cg *ChainGen) NextTipSetWithNulls(nulls abi.ChainEpoch) (*MinedTipSet, error) {
mts, err := cg.NextTipSetFromMiners(cg.CurTipset.TipSet(), cg.Miners, nulls)
if err != nil {
return nil, err
}
cg.CurTipset = mts.TipSet
return mts, nil
}
@ -586,29 +595,11 @@ type mca struct {
}
func (mca mca) StateGetRandomnessFromTickets(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) {
pts, err := mca.sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset key: %w", err)
}
if mca.sm.GetNtwkVersion(ctx, randEpoch) >= network.Version13 {
return mca.sm.ChainStore().GetChainRandomnessLookingForward(ctx, pts.Cids(), personalization, randEpoch, entropy)
}
return mca.sm.ChainStore().GetChainRandomnessLookingBack(ctx, pts.Cids(), personalization, randEpoch, entropy)
return mca.sm.GetRandomnessFromTickets(ctx, personalization, randEpoch, entropy, tsk)
}
func (mca mca) StateGetRandomnessFromBeacon(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) {
pts, err := mca.sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset key: %w", err)
}
if mca.sm.GetNtwkVersion(ctx, randEpoch) >= network.Version13 {
return mca.sm.ChainStore().GetBeaconRandomnessLookingForward(ctx, pts.Cids(), personalization, randEpoch, entropy)
}
return mca.sm.ChainStore().GetBeaconRandomnessLookingBack(ctx, pts.Cids(), personalization, randEpoch, entropy)
return mca.sm.GetRandomnessFromBeacon(ctx, personalization, randEpoch, entropy, tsk)
}
func (mca mca) MinerGetBaseInfo(ctx context.Context, maddr address.Address, epoch abi.ChainEpoch, tsk types.TipSetKey) (*api.MiningBaseInfo, error) {
@ -644,7 +635,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round abi.ChainEpoch,
return nil, xerrors.Errorf("failed to cbor marshal address: %w", err)
}
electionRand, err := store.DrawRandomness(brand.Data, crypto.DomainSeparationTag_ElectionProofProduction, round, buf.Bytes())
electionRand, err := rand.DrawRandomness(brand.Data, crypto.DomainSeparationTag_ElectionProofProduction, round, buf.Bytes())
if err != nil {
return nil, xerrors.Errorf("failed to draw randomness: %w", err)
}

View File

@ -6,6 +6,8 @@ import (
"fmt"
"math/rand"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen"
@ -193,12 +195,21 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sys vm.Syscal
if err != nil {
return xerrors.Errorf("failed to create genesis miner (publish deals): %w", err)
}
var ids market.PublishStorageDealsReturn
if err := ids.UnmarshalCBOR(bytes.NewReader(ret)); err != nil {
return xerrors.Errorf("unmarsahling publishStorageDeals result: %w", err)
retval, err := market.DecodePublishStorageDealsReturn(ret, nv)
if err != nil {
return xerrors.Errorf("failed to create genesis miner (decoding published deals): %w", err)
}
minerInfos[i].dealIDs = append(minerInfos[i].dealIDs, ids.IDs...)
ids, err := retval.DealIDs()
if err != nil {
return xerrors.Errorf("failed to create genesis miner (getting published dealIDs): %w", err)
}
if len(ids) != len(params.Deals) {
return xerrors.Errorf("failed to create genesis miner (at least one deal was invalid on publication")
}
minerInfos[i].dealIDs = append(minerInfos[i].dealIDs, ids...)
return nil
}
@ -389,11 +400,24 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sys vm.Syscal
}
// Commit one-by-one, otherwise pledge math tends to explode
confirmParams := &builtin0.ConfirmSectorProofsParams{
Sectors: []abi.SectorNumber{preseal.SectorID},
var paramBytes []byte
if av >= actors.Version6 {
// TODO: fixup
confirmParams := &builtin6.ConfirmSectorProofsParams{
Sectors: []abi.SectorNumber{preseal.SectorID},
}
paramBytes = mustEnc(confirmParams)
} else {
confirmParams := &builtin0.ConfirmSectorProofsParams{
Sectors: []abi.SectorNumber{preseal.SectorID},
}
paramBytes = mustEnc(confirmParams)
}
_, err = doExecValue(ctx, vm, minerInfos[i].maddr, power.Address, big.Zero(), miner.Methods.ConfirmSectorProofsValid, mustEnc(confirmParams))
_, err = doExecValue(ctx, vm, minerInfos[i].maddr, power.Address, big.Zero(), miner.Methods.ConfirmSectorProofsValid, paramBytes)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to confirm presealed sectors: %w", err)
}
@ -485,25 +509,31 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sys vm.Syscal
// TODO: copied from actors test harness, deduplicate or remove from here
type fakeRand struct{}
func (fr *fakeRand) GetChainRandomnessLookingForward(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (fr *fakeRand) GetChainRandomnessV2(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
out := make([]byte, 32)
_, _ = rand.New(rand.NewSource(int64(randEpoch * 1000))).Read(out) //nolint
return out, nil
}
func (fr *fakeRand) GetChainRandomnessLookingBack(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (fr *fakeRand) GetChainRandomnessV1(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
out := make([]byte, 32)
_, _ = rand.New(rand.NewSource(int64(randEpoch * 1000))).Read(out) //nolint
return out, nil
}
func (fr *fakeRand) GetBeaconRandomnessLookingForward(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (fr *fakeRand) GetBeaconRandomnessV3(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
out := make([]byte, 32)
_, _ = rand.New(rand.NewSource(int64(randEpoch))).Read(out) //nolint
return out, nil
}
func (fr *fakeRand) GetBeaconRandomnessLookingBack(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (fr *fakeRand) GetBeaconRandomnessV2(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
out := make([]byte, 32)
_, _ = rand.New(rand.NewSource(int64(randEpoch))).Read(out) //nolint
return out, nil
}
func (fr *fakeRand) GetBeaconRandomnessV1(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
out := make([]byte, 32)
_, _ = rand.New(rand.NewSource(int64(randEpoch))).Read(out) //nolint
return out, nil

202
chain/rand/rand.go Normal file
View File

@ -0,0 +1,202 @@
package rand
import (
"context"
"encoding/binary"
logging "github.com/ipfs/go-log/v2"
"github.com/filecoin-project/lotus/chain/beacon"
"github.com/ipfs/go-cid"
"github.com/minio/blake2b-simd"
"go.opencensus.io/trace"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)
var log = logging.Logger("rand")
func DrawRandomness(rbase []byte, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
h := blake2b.New256()
if err := binary.Write(h, binary.BigEndian, int64(pers)); err != nil {
return nil, xerrors.Errorf("deriving randomness: %w", err)
}
VRFDigest := blake2b.Sum256(rbase)
_, err := h.Write(VRFDigest[:])
if err != nil {
return nil, xerrors.Errorf("hashing VRFDigest: %w", err)
}
if err := binary.Write(h, binary.BigEndian, round); err != nil {
return nil, xerrors.Errorf("deriving randomness: %w", err)
}
_, err = h.Write(entropy)
if err != nil {
return nil, xerrors.Errorf("hashing entropy: %w", err)
}
return h.Sum(nil), nil
}
func (sr *stateRand) GetBeaconRandomnessTipset(ctx context.Context, round abi.ChainEpoch, lookback bool) (*types.TipSet, error) {
_, span := trace.StartSpan(ctx, "store.GetBeaconRandomness")
defer span.End()
span.AddAttributes(trace.Int64Attribute("round", int64(round)))
ts, err := sr.cs.LoadTipSet(types.NewTipSetKey(sr.blks...))
if err != nil {
return nil, err
}
if round > ts.Height() {
return nil, xerrors.Errorf("cannot draw randomness from the future")
}
searchHeight := round
if searchHeight < 0 {
searchHeight = 0
}
randTs, err := sr.cs.GetTipsetByHeight(ctx, searchHeight, ts, lookback)
if err != nil {
return nil, err
}
return randTs, nil
}
func (sr *stateRand) GetChainRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte, lookback bool) ([]byte, error) {
_, span := trace.StartSpan(ctx, "store.GetChainRandomness")
defer span.End()
span.AddAttributes(trace.Int64Attribute("round", int64(round)))
ts, err := sr.cs.LoadTipSet(types.NewTipSetKey(sr.blks...))
if err != nil {
return nil, err
}
if round > ts.Height() {
return nil, xerrors.Errorf("cannot draw randomness from the future")
}
searchHeight := round
if searchHeight < 0 {
searchHeight = 0
}
randTs, err := sr.cs.GetTipsetByHeight(ctx, searchHeight, ts, lookback)
if err != nil {
return nil, err
}
mtb := randTs.MinTicketBlock()
// if at (or just past -- for null epochs) appropriate epoch
// or at genesis (works for negative epochs)
return DrawRandomness(mtb.Ticket.VRFProof, pers, round, entropy)
}
type stateRand struct {
cs *store.ChainStore
blks []cid.Cid
beacon beacon.Schedule
}
func NewStateRand(cs *store.ChainStore, blks []cid.Cid, b beacon.Schedule) vm.Rand {
return &stateRand{
cs: cs,
blks: blks,
beacon: b,
}
}
// network v0-12
func (sr *stateRand) GetChainRandomnessV1(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return sr.GetChainRandomness(ctx, pers, round, entropy, true)
}
// network v13 and on
func (sr *stateRand) GetChainRandomnessV2(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return sr.GetChainRandomness(ctx, pers, round, entropy, false)
}
// network v0-12
func (sr *stateRand) GetBeaconRandomnessV1(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
randTs, err := sr.GetBeaconRandomnessTipset(ctx, round, true)
if err != nil {
return nil, err
}
be, err := sr.cs.GetLatestBeaconEntry(randTs)
if err != nil {
return nil, err
}
// if at (or just past -- for null epochs) appropriate epoch
// or at genesis (works for negative epochs)
return DrawRandomness(be.Data, pers, round, entropy)
}
// network v13
func (sr *stateRand) GetBeaconRandomnessV2(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
randTs, err := sr.GetBeaconRandomnessTipset(ctx, round, false)
if err != nil {
return nil, err
}
be, err := sr.cs.GetLatestBeaconEntry(randTs)
if err != nil {
return nil, err
}
// if at (or just past -- for null epochs) appropriate epoch
// or at genesis (works for negative epochs)
return DrawRandomness(be.Data, pers, round, entropy)
}
// network v14 and on
func (sr *stateRand) GetBeaconRandomnessV3(ctx context.Context, pers crypto.DomainSeparationTag, filecoinEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
if filecoinEpoch < 0 {
return sr.GetBeaconRandomnessV2(ctx, pers, filecoinEpoch, entropy)
}
be, err := sr.extractBeaconEntryForEpoch(ctx, filecoinEpoch)
if err != nil {
log.Errorf("failed to get beacon entry as expected: %w", err)
return nil, err
}
return DrawRandomness(be.Data, pers, filecoinEpoch, entropy)
}
func (sr *stateRand) extractBeaconEntryForEpoch(ctx context.Context, filecoinEpoch abi.ChainEpoch) (*types.BeaconEntry, error) {
randTs, err := sr.GetBeaconRandomnessTipset(ctx, filecoinEpoch, false)
if err != nil {
return nil, err
}
round := sr.beacon.BeaconForEpoch(filecoinEpoch).MaxBeaconRoundForEpoch(filecoinEpoch)
for i := 0; i < 20; i++ {
cbe := randTs.Blocks()[0].BeaconEntries
for _, v := range cbe {
if v.Round == round {
return &v, nil
}
}
next, err := sr.cs.LoadTipSet(randTs.Parents())
if err != nil {
return nil, xerrors.Errorf("failed to load parents when searching back for beacon entry: %w", err)
}
randTs = next
}
return nil, xerrors.Errorf("didn't find beacon for round %d (epoch %d)", round, filecoinEpoch)
}

238
chain/rand/rand_test.go Normal file
View File

@ -0,0 +1,238 @@
package rand_test
import (
"context"
"testing"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/consensus/filcns"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/rand"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/gen"
)
func init() {
policy.SetSupportedProofTypes(abi.RegisteredSealProof_StackedDrg2KiBV1)
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
}
// in v12 and before, if the tipset corresponding to round X is null, we fetch the latest beacon entry BEFORE X that's in a non-null ts
func TestNullRandomnessV1(t *testing.T) {
ctx := context.Background()
cg, err := gen.NewGenerator()
if err != nil {
t.Fatal(err)
}
for i := 0; i < 10; i++ {
_, err := cg.NextTipSet()
if err != nil {
t.Fatal(err)
}
}
offset := cg.CurTipset.Blocks[0].Header.BeaconEntries[len(cg.CurTipset.Blocks[0].Header.BeaconEntries)-1].Round - uint64(cg.CurTipset.TipSet().Height())
beforeNullHeight := cg.CurTipset.TipSet().Height()
ts, err := cg.NextTipSetWithNulls(5)
if err != nil {
t.Fatal(err)
}
entropy := []byte{0, 2, 3, 4}
// arbitrarily chosen
pers := crypto.DomainSeparationTag_WinningPoStChallengeSeed
randEpoch := ts.TipSet.TipSet().Height() - 2
rand1, err := cg.StateManager().GetRandomnessFromBeacon(ctx, pers, randEpoch, entropy, ts.TipSet.TipSet().Key())
if err != nil {
t.Fatal(err)
}
bch := cg.BeaconSchedule().BeaconForEpoch(randEpoch).Entry(ctx, uint64(beforeNullHeight)+offset)
select {
case resp := <-bch:
if resp.Err != nil {
t.Fatal(resp.Err)
}
rand2, err := rand.DrawRandomness(resp.Entry.Data, pers, randEpoch, entropy)
if err != nil {
t.Fatal(err)
}
require.Equal(t, rand1, abi.Randomness(rand2))
case <-ctx.Done():
t.Fatal("timed out")
}
}
// at v13, if the tipset corresponding to round X is null, we fetch the latest beacon in the first non-null ts after X
func TestNullRandomnessV2(t *testing.T) {
ctx := context.Background()
sched := stmgr.UpgradeSchedule{
{
// prepare for upgrade.
Network: network.Version9,
Height: 1,
Migration: filcns.UpgradeActorsV2,
}, {
Network: network.Version10,
Height: 2,
Migration: filcns.UpgradeActorsV3,
}, {
Network: network.Version12,
Height: 3,
Migration: filcns.UpgradeActorsV4,
}, {
Network: network.Version13,
Height: 4,
Migration: filcns.UpgradeActorsV5,
},
}
cg, err := gen.NewGeneratorWithUpgradeSchedule(sched)
if err != nil {
t.Fatal(err)
}
for i := 0; i < 10; i++ {
_, err := cg.NextTipSet()
if err != nil {
t.Fatal(err)
}
}
offset := cg.CurTipset.Blocks[0].Header.BeaconEntries[len(cg.CurTipset.Blocks[0].Header.BeaconEntries)-1].Round - uint64(cg.CurTipset.TipSet().Height())
ts, err := cg.NextTipSetWithNulls(5)
if err != nil {
t.Fatal(err)
}
entropy := []byte{0, 2, 3, 4}
// arbitrarily chosen
pers := crypto.DomainSeparationTag_WinningPoStChallengeSeed
randEpoch := ts.TipSet.TipSet().Height() - 2
rand1, err := cg.StateManager().GetRandomnessFromBeacon(ctx, pers, randEpoch, entropy, ts.TipSet.TipSet().Key())
if err != nil {
t.Fatal(err)
}
bch := cg.BeaconSchedule().BeaconForEpoch(randEpoch).Entry(ctx, uint64(ts.TipSet.TipSet().Height())+offset)
select {
case resp := <-bch:
if resp.Err != nil {
t.Fatal(resp.Err)
}
// note that the randEpoch passed to DrawRandomness is still randEpoch (not the latest ts height)
rand2, err := rand.DrawRandomness(resp.Entry.Data, pers, randEpoch, entropy)
if err != nil {
t.Fatal(err)
}
require.Equal(t, rand1, abi.Randomness(rand2))
case <-ctx.Done():
t.Fatal("timed out")
}
}
// after v14, if the tipset corresponding to round X is null, we still fetch the randomness for X (from the next non-null tipset)
func TestNullRandomnessV3(t *testing.T) {
ctx := context.Background()
sched := stmgr.UpgradeSchedule{
{
// prepare for upgrade.
Network: network.Version9,
Height: 1,
Migration: filcns.UpgradeActorsV2,
}, {
Network: network.Version10,
Height: 2,
Migration: filcns.UpgradeActorsV3,
}, {
Network: network.Version12,
Height: 3,
Migration: filcns.UpgradeActorsV4,
}, {
Network: network.Version13,
Height: 4,
Migration: filcns.UpgradeActorsV5,
}, {
Network: network.Version14,
Height: 5,
Migration: filcns.UpgradeActorsV6,
},
}
cg, err := gen.NewGeneratorWithUpgradeSchedule(sched)
if err != nil {
t.Fatal(err)
}
for i := 0; i < 10; i++ {
_, err := cg.NextTipSet()
if err != nil {
t.Fatal(err)
}
}
ts, err := cg.NextTipSetWithNulls(5)
if err != nil {
t.Fatal(err)
}
offset := cg.CurTipset.Blocks[0].Header.BeaconEntries[len(cg.CurTipset.Blocks[0].Header.BeaconEntries)-1].Round - uint64(cg.CurTipset.TipSet().Height())
entropy := []byte{0, 2, 3, 4}
// arbitrarily chosen
pers := crypto.DomainSeparationTag_WinningPoStChallengeSeed
randEpoch := ts.TipSet.TipSet().Height() - 2
rand1, err := cg.StateManager().GetRandomnessFromBeacon(ctx, pers, randEpoch, entropy, ts.TipSet.TipSet().Key())
if err != nil {
t.Fatal(err)
}
bch := cg.BeaconSchedule().BeaconForEpoch(randEpoch).Entry(ctx, uint64(randEpoch)+offset)
select {
case resp := <-bch:
if resp.Err != nil {
t.Fatal(resp.Err)
}
rand2, err := rand.DrawRandomness(resp.Entry.Data, pers, randEpoch, entropy)
if err != nil {
t.Fatal(err)
}
require.Equal(t, rand1, abi.Randomness(rand2))
case <-ctx.Done():
t.Fatal("timed out")
}
}

View File

@ -152,7 +152,7 @@ func VersionForNetwork(ver network.Version) (types.StateTreeVersion, error) {
return types.StateTreeVersion2, nil
case network.Version12:
return types.StateTreeVersion3, nil
case network.Version13:
case network.Version13, network.Version14:
return types.StateTreeVersion4, nil
default:
panic(fmt.Sprintf("unsupported network version %d", ver))

View File

@ -5,6 +5,8 @@ import (
"context"
"os"
"github.com/filecoin-project/lotus/chain/rand"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi"
@ -21,7 +23,6 @@ import (
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/beacon"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
@ -351,7 +352,7 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule
return nil, xerrors.Errorf("failed to marshal miner address: %w", err)
}
prand, err := store.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, round, buf.Bytes())
prand, err := rand.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, round, buf.Bytes())
if err != nil {
return nil, xerrors.Errorf("failed to get randomness for winning post: %w", err)
}

View File

@ -5,6 +5,8 @@ import (
"errors"
"fmt"
"github.com/filecoin-project/lotus/chain/rand"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
@ -14,7 +16,6 @@ import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)
@ -74,7 +75,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
vmopt := &vm.VMOpts{
StateBase: bstate,
Epoch: pheight + 1,
Rand: store.NewChainRand(sm.cs, ts.Cids()),
Rand: rand.NewStateRand(sm.cs, ts.Cids(), sm.beacon),
Bstore: sm.cs.StateBlockstore(),
Actors: sm.tsExec.NewActorRegistry(),
Syscalls: sm.Syscalls,
@ -185,7 +186,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
return nil, fmt.Errorf("failed to handle fork: %w", err)
}
r := store.NewChainRand(sm.cs, ts.Cids())
r := rand.NewStateRand(sm.cs, ts.Cids(), sm.beacon)
if span.IsRecordingEvents() {
span.AddAttributes(

View File

@ -158,7 +158,7 @@ func TestForkHeightTriggers(t *testing.T) {
}
return st.Flush(ctx)
}}})
}}}, cg.BeaconSchedule())
if err != nil {
t.Fatal(err)
}
@ -273,7 +273,7 @@ func testForkRefuseCall(t *testing.T, nullsBefore, nullsAfter int) {
root cid.Cid, height abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
migrationCount++
return root, nil
}}})
}}}, cg.BeaconSchedule())
if err != nil {
t.Fatal(err)
}
@ -488,7 +488,7 @@ func TestForkPreMigration(t *testing.T) {
return nil
},
}}},
})
}, cg.BeaconSchedule())
if err != nil {
t.Fatal(err)
}

View File

@ -4,6 +4,10 @@ import (
"context"
"sync"
"github.com/filecoin-project/lotus/chain/rand"
"github.com/filecoin-project/lotus/chain/beacon"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2"
@ -11,6 +15,7 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/network"
// Used for genesis.
@ -89,6 +94,7 @@ type StateManager struct {
tsExec Executor
tsExecMonitor ExecMonitor
beacon beacon.Schedule
}
// Caches a single state tree
@ -97,7 +103,7 @@ type treeCache struct {
tree *state.StateTree
}
func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder, us UpgradeSchedule) (*StateManager, error) {
func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder, us UpgradeSchedule, beacon beacon.Schedule) (*StateManager, error) {
// If we have upgrades, make sure they're in-order and make sense.
if err := us.Validate(); err != nil {
return nil, err
@ -106,7 +112,7 @@ func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder,
stateMigrations := make(map[abi.ChainEpoch]*migration, len(us))
expensiveUpgrades := make(map[abi.ChainEpoch]struct{}, len(us))
var networkVersions []versionSpec
lastVersion := network.Version0
lastVersion := build.GenesisNetworkVersion
if len(us) > 0 {
// If we have any upgrades, process them and create a version
// schedule.
@ -143,6 +149,7 @@ func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder,
cs: cs,
tsExec: exec,
stCache: make(map[string][]cid.Cid),
beacon: beacon,
tCache: treeCache{
root: cid.Undef,
tree: nil,
@ -151,8 +158,8 @@ func NewStateManager(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder,
}, nil
}
func NewStateManagerWithUpgradeScheduleAndMonitor(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder, us UpgradeSchedule, em ExecMonitor) (*StateManager, error) {
sm, err := NewStateManager(cs, exec, sys, us)
func NewStateManagerWithUpgradeScheduleAndMonitor(cs *store.ChainStore, exec Executor, sys vm.SyscallBuilder, us UpgradeSchedule, b beacon.Schedule, em ExecMonitor) (*StateManager, error) {
sm, err := NewStateManager(cs, exec, sys, us, b)
if err != nil {
return nil, err
}
@ -199,6 +206,10 @@ func (sm *StateManager) ChainStore() *store.ChainStore {
return sm.cs
}
func (sm *StateManager) Beacon() beacon.Schedule {
return sm.beacon
}
// ResolveToKeyAddress is similar to `vm.ResolveToKeyAddr` but does not allow `Actor` type of addresses.
// Uses the `TipSet` `ts` to generate the VM state.
func (sm *StateManager) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
@ -362,3 +373,38 @@ func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoc
func (sm *StateManager) VMSys() vm.SyscallBuilder {
return sm.Syscalls
}
func (sm *StateManager) GetRandomnessFromBeacon(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) {
pts, err := sm.ChainStore().GetTipSetFromKey(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
r := rand.NewStateRand(sm.ChainStore(), pts.Cids(), sm.beacon)
rnv := sm.GetNtwkVersion(ctx, randEpoch)
if rnv >= network.Version14 {
return r.GetBeaconRandomnessV3(ctx, personalization, randEpoch, entropy)
} else if rnv == network.Version13 {
return r.GetBeaconRandomnessV2(ctx, personalization, randEpoch, entropy)
}
return r.GetBeaconRandomnessV1(ctx, personalization, randEpoch, entropy)
}
func (sm *StateManager) GetRandomnessFromTickets(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) {
pts, err := sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset key: %w", err)
}
r := rand.NewStateRand(sm.ChainStore(), pts.Cids(), sm.beacon)
rnv := sm.GetNtwkVersion(ctx, randEpoch)
if rnv >= network.Version13 {
return r.GetChainRandomnessV2(ctx, personalization, randEpoch, entropy)
}
return r.GetChainRandomnessV1(ctx, personalization, randEpoch, entropy)
}

View File

@ -5,6 +5,8 @@ import (
"fmt"
"reflect"
"github.com/filecoin-project/lotus/chain/rand"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
@ -77,7 +79,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
// future. It's not guaranteed to be accurate... but that's fine.
}
r := store.NewChainRand(sm.cs, ts.Cids())
r := rand.NewStateRand(sm.cs, ts.Cids(), sm.beacon)
vmopt := &vm.VMOpts{
StateBase: base,
Epoch: height,

View File

@ -1,182 +0,0 @@
package store
import (
"context"
"encoding/binary"
"os"
"github.com/ipfs/go-cid"
"github.com/minio/blake2b-simd"
"go.opencensus.io/trace"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)
func DrawRandomness(rbase []byte, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
h := blake2b.New256()
if err := binary.Write(h, binary.BigEndian, int64(pers)); err != nil {
return nil, xerrors.Errorf("deriving randomness: %w", err)
}
VRFDigest := blake2b.Sum256(rbase)
_, err := h.Write(VRFDigest[:])
if err != nil {
return nil, xerrors.Errorf("hashing VRFDigest: %w", err)
}
if err := binary.Write(h, binary.BigEndian, round); err != nil {
return nil, xerrors.Errorf("deriving randomness: %w", err)
}
_, err = h.Write(entropy)
if err != nil {
return nil, xerrors.Errorf("hashing entropy: %w", err)
}
return h.Sum(nil), nil
}
func (cs *ChainStore) GetBeaconRandomnessLookingBack(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return cs.GetBeaconRandomness(ctx, blks, pers, round, entropy, true)
}
func (cs *ChainStore) GetBeaconRandomnessLookingForward(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return cs.GetBeaconRandomness(ctx, blks, pers, round, entropy, false)
}
func (cs *ChainStore) GetBeaconRandomness(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte, lookback bool) ([]byte, error) {
_, span := trace.StartSpan(ctx, "store.GetBeaconRandomness")
defer span.End()
span.AddAttributes(trace.Int64Attribute("round", int64(round)))
ts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
if err != nil {
return nil, err
}
if round > ts.Height() {
return nil, xerrors.Errorf("cannot draw randomness from the future")
}
searchHeight := round
if searchHeight < 0 {
searchHeight = 0
}
randTs, err := cs.GetTipsetByHeight(ctx, searchHeight, ts, lookback)
if err != nil {
return nil, err
}
be, err := cs.GetLatestBeaconEntry(randTs)
if err != nil {
return nil, err
}
// if at (or just past -- for null epochs) appropriate epoch
// or at genesis (works for negative epochs)
return DrawRandomness(be.Data, pers, round, entropy)
}
func (cs *ChainStore) GetChainRandomnessLookingBack(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return cs.GetChainRandomness(ctx, blks, pers, round, entropy, true)
}
func (cs *ChainStore) GetChainRandomnessLookingForward(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return cs.GetChainRandomness(ctx, blks, pers, round, entropy, false)
}
func (cs *ChainStore) GetChainRandomness(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte, lookback bool) ([]byte, error) {
_, span := trace.StartSpan(ctx, "store.GetChainRandomness")
defer span.End()
span.AddAttributes(trace.Int64Attribute("round", int64(round)))
ts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
if err != nil {
return nil, err
}
if round > ts.Height() {
return nil, xerrors.Errorf("cannot draw randomness from the future")
}
searchHeight := round
if searchHeight < 0 {
searchHeight = 0
}
randTs, err := cs.GetTipsetByHeight(ctx, searchHeight, ts, lookback)
if err != nil {
return nil, err
}
mtb := randTs.MinTicketBlock()
// if at (or just past -- for null epochs) appropriate epoch
// or at genesis (works for negative epochs)
return DrawRandomness(mtb.Ticket.VRFProof, pers, round, entropy)
}
func (cs *ChainStore) GetLatestBeaconEntry(ts *types.TipSet) (*types.BeaconEntry, error) {
cur := ts
for i := 0; i < 20; i++ {
cbe := cur.Blocks()[0].BeaconEntries
if len(cbe) > 0 {
return &cbe[len(cbe)-1], nil
}
if cur.Height() == 0 {
return nil, xerrors.Errorf("made it back to genesis block without finding beacon entry")
}
next, err := cs.LoadTipSet(cur.Parents())
if err != nil {
return nil, xerrors.Errorf("failed to load parents when searching back for latest beacon entry: %w", err)
}
cur = next
}
if os.Getenv("LOTUS_IGNORE_DRAND") == "_yes_" {
return &types.BeaconEntry{
Data: []byte{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9},
}, nil
}
return nil, xerrors.Errorf("found NO beacon entries in the 20 latest tipsets")
}
type chainRand struct {
cs *ChainStore
blks []cid.Cid
}
func NewChainRand(cs *ChainStore, blks []cid.Cid) vm.Rand {
return &chainRand{
cs: cs,
blks: blks,
}
}
func (cr *chainRand) GetChainRandomnessLookingBack(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return cr.cs.GetChainRandomnessLookingBack(ctx, cr.blks, pers, round, entropy)
}
func (cr *chainRand) GetChainRandomnessLookingForward(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return cr.cs.GetChainRandomnessLookingForward(ctx, cr.blks, pers, round, entropy)
}
func (cr *chainRand) GetBeaconRandomnessLookingBack(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return cr.cs.GetBeaconRandomnessLookingBack(ctx, cr.blks, pers, round, entropy)
}
func (cr *chainRand) GetBeaconRandomnessLookingForward(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return cr.cs.GetBeaconRandomnessLookingForward(ctx, cr.blks, pers, round, entropy)
}
func (cs *ChainStore) GetTipSetFromKey(tsk types.TipSetKey) (*types.TipSet, error) {
if tsk.IsEmpty() {
return cs.GetHeaviestTipSet(), nil
}
return cs.LoadTipSet(tsk)
}

View File

@ -424,7 +424,13 @@ func (cs *ChainStore) MaybeTakeHeavierTipSet(ctx context.Context, ts *types.TipS
return err
}
if w.GreaterThan(heaviestW) {
heavier := w.GreaterThan(heaviestW)
if w.Equals(heaviestW) && !ts.Equals(cs.heaviest) {
log.Errorw("weight draw", "currTs", cs.heaviest, "ts", ts)
heavier = breakWeightTie(ts, cs.heaviest)
}
if heavier {
// TODO: don't do this for initial sync. Now that we don't have a
// difference between 'bootstrap sync' and 'caught up' sync, we need
// some other heuristic.
@ -438,9 +444,8 @@ func (cs *ChainStore) MaybeTakeHeavierTipSet(ctx context.Context, ts *types.TipS
}
return cs.takeHeaviestTipSet(ctx, ts)
} else if w.Equals(heaviestW) && !ts.Equals(cs.heaviest) {
log.Errorw("weight draw", "currTs", cs.heaviest, "ts", ts)
}
return nil
}
@ -1165,3 +1170,57 @@ func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h abi.ChainEpoch, t
func (cs *ChainStore) Weight(ctx context.Context, hts *types.TipSet) (types.BigInt, error) { // todo remove
return cs.weight(ctx, cs.StateBlockstore(), hts)
}
// true if ts1 wins according to the filecoin tie-break rule
func breakWeightTie(ts1, ts2 *types.TipSet) bool {
s := len(ts1.Blocks())
if s > len(ts2.Blocks()) {
s = len(ts2.Blocks())
}
// blocks are already sorted by ticket
for i := 0; i < s; i++ {
if ts1.Blocks()[i].Ticket.Less(ts2.Blocks()[i].Ticket) {
log.Infof("weight tie broken in favour of %s", ts1.Key())
return true
}
}
log.Infof("weight tie left unbroken, default to %s", ts2.Key())
return false
}
func (cs *ChainStore) GetTipSetFromKey(tsk types.TipSetKey) (*types.TipSet, error) {
if tsk.IsEmpty() {
return cs.GetHeaviestTipSet(), nil
}
return cs.LoadTipSet(tsk)
}
func (cs *ChainStore) GetLatestBeaconEntry(ts *types.TipSet) (*types.BeaconEntry, error) {
cur := ts
for i := 0; i < 20; i++ {
cbe := cur.Blocks()[0].BeaconEntries
if len(cbe) > 0 {
return &cbe[len(cbe)-1], nil
}
if cur.Height() == 0 {
return nil, xerrors.Errorf("made it back to genesis block without finding beacon entry")
}
next, err := cs.LoadTipSet(cur.Parents())
if err != nil {
return nil, xerrors.Errorf("failed to load parents when searching back for latest beacon entry: %w", err)
}
cur = next
}
if os.Getenv("LOTUS_IGNORE_DRAND") == "_yes_" {
return &types.BeaconEntry{
Data: []byte{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9},
}, nil
}
return nil, xerrors.Errorf("found NO beacon entries in the 20 latest tipsets")
}

View File

@ -77,7 +77,7 @@ func BenchmarkGetRandomness(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := cs.GetChainRandomnessLookingBack(context.TODO(), last.Cids(), crypto.DomainSeparationTag_SealRandomness, 500, nil)
_, err := cg.StateManager().GetRandomnessFromTickets(context.TODO(), crypto.DomainSeparationTag_SealRandomness, 500, nil, last.Key())
if err != nil {
b.Fatal(err)
}
@ -158,7 +158,7 @@ func TestChainExportImportFull(t *testing.T) {
t.Fatal("imported chain differed from exported chain")
}
sm, err := stmgr.NewStateManager(cs, filcns.NewTipSetExecutor(), nil, filcns.DefaultUpgradeSchedule())
sm, err := stmgr.NewStateManager(cs, filcns.NewTipSetExecutor(), nil, filcns.DefaultUpgradeSchedule(), cg.BeaconSchedule())
if err != nil {
t.Fatal(err)
}

View File

@ -7,8 +7,6 @@ import (
"testing"
"time"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/stmgr"
@ -139,6 +137,10 @@ func prepSyncTestWithV5Height(t testing.TB, h int, v5height abi.ChainEpoch) *syn
Network: network.Version13,
Height: v5height,
Migration: filcns.UpgradeActorsV5,
}, {
Network: network.Version14,
Height: v5height + 10,
Migration: filcns.UpgradeActorsV6,
}}
g, err := gen.NewGeneratorWithUpgradeSchedule(sched)
@ -1033,81 +1035,6 @@ func TestSyncCheckpointEarlierThanHead(t *testing.T) {
require.True(tu.t, p1Head.Equals(b.TipSet()))
}
func TestDrandNull(t *testing.T) {
H := 10
v5h := abi.ChainEpoch(50)
ov5h := build.UpgradeHyperdriveHeight
build.UpgradeHyperdriveHeight = v5h
tu := prepSyncTestWithV5Height(t, H, v5h)
p0 := tu.addClientNode()
p1 := tu.addClientNode()
tu.loadChainToNode(p0)
tu.loadChainToNode(p1)
entropy := []byte{0, 2, 3, 4}
// arbitrarily chosen
pers := crypto.DomainSeparationTag_WinningPoStChallengeSeed
beforeNull := tu.g.CurTipset
afterNull := tu.mineOnBlock(beforeNull, p0, nil, false, false, nil, 2, true)
nullHeight := beforeNull.TipSet().Height() + 1
if afterNull.TipSet().Height() == nullHeight {
t.Fatal("didn't inject nulls as expected")
}
rand, err := tu.nds[p0].StateGetRandomnessFromBeacon(tu.ctx, pers, nullHeight, entropy, afterNull.TipSet().Key())
require.NoError(t, err)
// calculate the expected randomness based on the beacon BEFORE the null
expectedBE := beforeNull.Blocks[0].Header.BeaconEntries
expectedRand, err := store.DrawRandomness(expectedBE[len(expectedBE)-1].Data, pers, nullHeight, entropy)
require.NoError(t, err)
require.Equal(t, []byte(rand), expectedRand)
// zoom zoom to past the v5 upgrade by injecting many many nulls
postUpgrade := tu.mineOnBlock(afterNull, p0, nil, false, false, nil, v5h, true)
nv, err := tu.nds[p0].StateNetworkVersion(tu.ctx, postUpgrade.TipSet().Key())
require.NoError(t, err)
if nv != network.Version13 {
t.Fatal("expect to be v13 by now")
}
afterNull = tu.mineOnBlock(postUpgrade, p0, nil, false, false, nil, 2, true)
nullHeight = postUpgrade.TipSet().Height() + 1
if afterNull.TipSet().Height() == nullHeight {
t.Fatal("didn't inject nulls as expected")
}
rand0, err := tu.nds[p0].StateGetRandomnessFromBeacon(tu.ctx, pers, nullHeight, entropy, afterNull.TipSet().Key())
require.NoError(t, err)
// calculate the expected randomness based on the beacon AFTER the null
expectedBE = afterNull.Blocks[0].Header.BeaconEntries
expectedRand, err = store.DrawRandomness(expectedBE[len(expectedBE)-1].Data, pers, nullHeight, entropy)
require.NoError(t, err)
require.Equal(t, []byte(rand0), expectedRand)
// Introduce p1 to friendly p0 who has all the blocks
require.NoError(t, tu.mn.LinkAll())
tu.connect(p0, p1)
tu.waitUntilNodeHasTs(p1, afterNull.TipSet().Key())
p1Head := tu.getHead(p1)
// Yes, p1 syncs well to p0's chain
require.Equal(tu.t, p1Head.Key(), afterNull.TipSet().Key())
// Yes, p1 sources the same randomness as p0
rand1, err := tu.nds[p1].StateGetRandomnessFromBeacon(tu.ctx, pers, nullHeight, entropy, afterNull.TipSet().Key())
require.NoError(t, err)
require.Equal(t, rand0, rand1)
build.UpgradeHyperdriveHeight = ov5h
}
func TestInvalidHeight(t *testing.T) {
H := 50
tu := prepSyncTest(t, H)

View File

@ -15,7 +15,7 @@ const (
StateTreeVersion2
// StateTreeVersion3 corresponds to actors v4.
StateTreeVersion3
// StateTreeVersion4 corresponds to actors v5.
// StateTreeVersion4 corresponds to actors v5, v6.
StateTreeVersion4
)

View File

@ -19,6 +19,7 @@ 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"
builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
@ -113,6 +114,8 @@ func newAccountActor(ver actors.Version) *types.Actor {
code = builtin4.AccountActorCodeID
case actors.Version5:
code = builtin5.AccountActorCodeID
case actors.Version6:
code = builtin6.AccountActorCodeID
default:
panic("unsupported actors version")
}

View File

@ -17,6 +17,7 @@ import (
rtt "github.com/filecoin-project/go-state-types/rt"
rt0 "github.com/filecoin-project/specs-actors/actors/runtime"
rt5 "github.com/filecoin-project/specs-actors/v5/actors/runtime"
rt6 "github.com/filecoin-project/specs-actors/v6/actors/runtime"
"github.com/ipfs/go-cid"
ipldcbor "github.com/ipfs/go-ipld-cbor"
"go.opencensus.io/trace"
@ -141,6 +142,7 @@ func (rt *Runtime) StorePut(x cbor.Marshaler) cid.Cid {
var _ rt0.Runtime = (*Runtime)(nil)
var _ rt5.Runtime = (*Runtime)(nil)
var _ rt6.Runtime = (*Runtime)(nil)
func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) {
defer func() {
@ -216,10 +218,11 @@ func (rt *Runtime) GetRandomnessFromTickets(personalization crypto.DomainSeparat
var res []byte
rnv := rt.vm.ntwkVersion(rt.ctx, randEpoch)
if rnv >= network.Version13 {
res, err = rt.vm.rand.GetChainRandomnessLookingForward(rt.ctx, personalization, randEpoch, entropy)
res, err = rt.vm.rand.GetChainRandomnessV2(rt.ctx, personalization, randEpoch, entropy)
} else {
res, err = rt.vm.rand.GetChainRandomnessLookingBack(rt.ctx, personalization, randEpoch, entropy)
res, err = rt.vm.rand.GetChainRandomnessV1(rt.ctx, personalization, randEpoch, entropy)
}
if err != nil {
@ -233,10 +236,12 @@ func (rt *Runtime) GetRandomnessFromBeacon(personalization crypto.DomainSeparati
var res []byte
rnv := rt.vm.ntwkVersion(rt.ctx, randEpoch)
if rnv >= network.Version13 {
res, err = rt.vm.rand.GetBeaconRandomnessLookingForward(rt.ctx, personalization, randEpoch, entropy)
if rnv >= network.Version14 {
res, err = rt.vm.rand.GetBeaconRandomnessV3(rt.ctx, personalization, randEpoch, entropy)
} else if rnv == network.Version13 {
res, err = rt.vm.rand.GetBeaconRandomnessV2(rt.ctx, personalization, randEpoch, entropy)
} else {
res, err = rt.vm.rand.GetBeaconRandomnessLookingBack(rt.ctx, personalization, randEpoch, entropy)
res, err = rt.vm.rand.GetBeaconRandomnessV1(rt.ctx, personalization, randEpoch, entropy)
}
if err != nil {

View File

@ -256,10 +256,11 @@ func NewVM(ctx context.Context, opts *VMOpts) (*VM, error) {
}
type Rand interface {
GetChainRandomnessLookingBack(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error)
GetChainRandomnessLookingForward(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error)
GetBeaconRandomnessLookingBack(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error)
GetBeaconRandomnessLookingForward(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error)
GetChainRandomnessV1(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error)
GetChainRandomnessV2(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error)
GetBeaconRandomnessV1(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error)
GetBeaconRandomnessV2(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error)
GetBeaconRandomnessV3(ctx context.Context, pers crypto.DomainSeparationTag, filecoinEpoch abi.ChainEpoch, entropy []byte) ([]byte, error)
}
type ApplyRet struct {

View File

@ -2,6 +2,7 @@ package cli
import (
"bufio"
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
@ -9,6 +10,8 @@ import (
"os"
"strings"
"github.com/filecoin-project/lotus/build"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
@ -528,6 +531,11 @@ var walletMarketWithdraw = &cli.Command{
Usage: "Market address to withdraw from (account or miner actor address, defaults to --wallet address)",
Aliases: []string{"a"},
},
&cli.IntFlag{
Name: "confidence",
Usage: "number of block confirmations to wait for",
Value: int(build.MessageConfidence),
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
@ -614,6 +622,28 @@ var walletMarketWithdraw = &cli.Command{
fmt.Printf("WithdrawBalance message cid: %s\n", smsg)
// wait for it to get mined into a block
wait, err := api.StateWaitMsg(ctx, smsg, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
// check it executed successfully
if wait.Receipt.ExitCode != 0 {
fmt.Println(cctx.App.Writer, "withdrawal failed!")
return err
}
var withdrawn abi.TokenAmount
if err := withdrawn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)); err != nil {
return err
}
fmt.Printf("Successfully withdrew %s FIL\n", withdrawn)
if withdrawn != amt {
fmt.Printf("Note that this is less than the requested amount of %s FIL\n", amt)
}
return nil
},
}

View File

@ -257,7 +257,8 @@ var importBenchCmd = &cli.Command{
cs := store.NewChainStore(bs, bs, metadataDs, filcns.Weight, nil)
defer cs.Close() //nolint:errcheck
stm, err := stmgr.NewStateManager(cs, filcns.NewTipSetExecutor(), vm.Syscalls(verifier), filcns.DefaultUpgradeSchedule())
// TODO: We need to supply the actual beacon after v14
stm, err := stmgr.NewStateManager(cs, filcns.NewTipSetExecutor(), vm.Syscalls(verifier), filcns.DefaultUpgradeSchedule(), nil)
if err != nil {
return err
}

View File

@ -1,6 +1,7 @@
package main
import (
"bytes"
"fmt"
"os"
"strings"
@ -207,6 +208,13 @@ var actorWithdrawCmd = &cli.Command{
Name: "withdraw",
Usage: "withdraw available balance",
ArgsUsage: "[amount (FIL)]",
Flags: []cli.Flag{
&cli.IntFlag{
Name: "confidence",
Usage: "number of block confirmations to wait for",
Value: int(build.MessageConfidence),
},
},
Action: func(cctx *cli.Context) error {
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
if err != nil {
@ -271,6 +279,28 @@ var actorWithdrawCmd = &cli.Command{
fmt.Printf("Requested rewards withdrawal in message %s\n", smsg.Cid())
// wait for it to get mined into a block
wait, err := api.StateWaitMsg(ctx, smsg.Cid(), uint64(cctx.Int("confidence")))
if err != nil {
return err
}
// check it executed successfully
if wait.Receipt.ExitCode != 0 {
fmt.Println(cctx.App.Writer, "withdrawal failed!")
return err
}
var withdrawn abi.TokenAmount
if err := withdrawn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)); err != nil {
return err
}
fmt.Printf("Successfully withdrew %s FIL\n", withdrawn)
if withdrawn != amount {
fmt.Printf("Note that this is less than the requested amount of %s FIL\n", amount)
}
return nil
},
}

View File

@ -1,6 +1,7 @@
package main
import (
"bytes"
"fmt"
"os"
@ -44,6 +45,11 @@ var actorWithdrawCmd = &cli.Command{
Name: "actor",
Usage: "specify the address of miner actor",
},
&cli.IntFlag{
Name: "confidence",
Usage: "number of block confirmations to wait for",
Value: int(build.MessageConfidence),
},
},
Action: func(cctx *cli.Context) error {
var maddr address.Address
@ -120,6 +126,28 @@ var actorWithdrawCmd = &cli.Command{
fmt.Printf("Requested rewards withdrawal in message %s\n", smsg.Cid())
// wait for it to get mined into a block
wait, err := nodeAPI.StateWaitMsg(ctx, smsg.Cid(), uint64(cctx.Int("confidence")))
if err != nil {
return err
}
// check it executed successfully
if wait.Receipt.ExitCode != 0 {
fmt.Println(cctx.App.Writer, "withdrawal failed!")
return err
}
var withdrawn abi.TokenAmount
if err := withdrawn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)); err != nil {
return err
}
fmt.Printf("Successfully withdrew %s FIL\n", withdrawn)
if withdrawn != amount {
fmt.Printf("Note that this is less than the requested amount of %s FIL\n", amount)
}
return nil
},
}

View File

@ -517,7 +517,7 @@ var chainBalanceStateCmd = &cli.Command{
cst := cbor.NewCborStore(bs)
store := adt.WrapStore(ctx, cst)
sm, err := stmgr.NewStateManager(cs, filcns.NewTipSetExecutor(), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule())
sm, err := stmgr.NewStateManager(cs, filcns.NewTipSetExecutor(), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil)
if err != nil {
return err
}
@ -741,7 +741,7 @@ var chainPledgeCmd = &cli.Command{
cst := cbor.NewCborStore(bs)
store := adt.WrapStore(ctx, cst)
sm, err := stmgr.NewStateManager(cs, filcns.NewTipSetExecutor(), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule())
sm, err := stmgr.NewStateManager(cs, filcns.NewTipSetExecutor(), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil)
if err != nil {
return err
}

View File

@ -7,11 +7,12 @@ import (
"os"
"strings"
miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/types"
miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner"
)
var mathCmd = &cli.Command{
@ -19,7 +20,8 @@ var mathCmd = &cli.Command{
Usage: "utility commands around doing math on a list of numbers",
Subcommands: []*cli.Command{
mathSumCmd,
mathAggFeesCmd,
mathPreCommitAggFeesCmd,
mathProveCommitAggFeesCmd,
},
}
@ -105,8 +107,8 @@ var mathSumCmd = &cli.Command{
},
}
var mathAggFeesCmd = &cli.Command{
Name: "agg-fees",
var mathProveCommitAggFeesCmd = &cli.Command{
Name: "agg-fees-commit",
Flags: []cli.Flag{
&cli.IntFlag{
Name: "size",
@ -117,6 +119,11 @@ var mathAggFeesCmd = &cli.Command{
Usage: "baseFee aFIL",
Required: true,
},
&cli.StringFlag{
Name: "base-fee",
Usage: "baseFee aFIL",
Required: true,
},
},
Action: func(cctx *cli.Context) error {
as := cctx.Int("size")
@ -126,7 +133,39 @@ var mathAggFeesCmd = &cli.Command{
return xerrors.Errorf("parsing basefee: %w", err)
}
fmt.Println(types.FIL(miner5.AggregateNetworkFee(as, bf)))
fmt.Println(types.FIL(miner6.AggregateProveCommitNetworkFee(as, bf)))
return nil
},
}
var mathPreCommitAggFeesCmd = &cli.Command{
Name: "agg-fees-precommit",
Flags: []cli.Flag{
&cli.IntFlag{
Name: "size",
Required: true,
},
&cli.StringFlag{
Name: "base-fee",
Usage: "baseFee aFIL",
Required: true,
},
&cli.StringFlag{
Name: "base-fee",
Usage: "baseFee aFIL",
Required: true,
},
},
Action: func(cctx *cli.Context) error {
as := cctx.Int("size")
bf, err := types.BigFromString(cctx.String("base-fee"))
if err != nil {
return xerrors.Errorf("parsing basefee: %w", err)
}
fmt.Println(types.FIL(miner6.AggregatePreCommitNetworkFee(as, bf)))
return nil
},

View File

@ -17,10 +17,11 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/account"
lrand "github.com/filecoin-project/lotus/chain/rand"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)
@ -78,7 +79,7 @@ func NewBlockBuilder(ctx context.Context, logger *zap.SugaredLogger, sm *stmgr.S
// 1. We don't charge a fee.
// 2. The runtime has "fake" proof logic.
// 3. We don't actually save any of the results.
r := store.NewChainRand(sm.ChainStore(), parentTs.Cids())
r := lrand.NewStateRand(sm.ChainStore(), parentTs.Cids(), sm.Beacon())
vmopt := &vm.VMOpts{
StateBase: parentState,
Epoch: parentTs.Height() + 1,

View File

@ -106,7 +106,7 @@ func (nd *Node) LoadSim(ctx context.Context, name string) (*Simulation, error) {
if err != nil {
return nil, xerrors.Errorf("failed to create upgrade schedule for simulation %s: %w", name, err)
}
sim.StateManager, err = stmgr.NewStateManager(nd.Chainstore, filcns.NewTipSetExecutor(), vm.Syscalls(mock.Verifier), us)
sim.StateManager, err = stmgr.NewStateManager(nd.Chainstore, filcns.NewTipSetExecutor(), vm.Syscalls(mock.Verifier), us, nil)
if err != nil {
return nil, xerrors.Errorf("failed to create state manager for simulation %s: %w", name, err)
}
@ -125,7 +125,7 @@ func (nd *Node) CreateSim(ctx context.Context, name string, head *types.TipSet)
if err != nil {
return nil, err
}
sm, err := stmgr.NewStateManager(nd.Chainstore, filcns.NewTipSetExecutor(), vm.Syscalls(mock.Verifier), filcns.DefaultUpgradeSchedule())
sm, err := stmgr.NewStateManager(nd.Chainstore, filcns.NewTipSetExecutor(), vm.Syscalls(mock.Verifier), filcns.DefaultUpgradeSchedule(), nil)
if err != nil {
return nil, xerrors.Errorf("creating state manager: %w", err)
}

View File

@ -201,7 +201,7 @@ func (sim *Simulation) SetUpgradeHeight(nv network.Version, epoch abi.ChainEpoch
if err != nil {
return err
}
sm, err := stmgr.NewStateManager(sim.Node.Chainstore, filcns.NewTipSetExecutor(), vm.Syscalls(mock.Verifier), newUpgradeSchedule)
sm, err := stmgr.NewStateManager(sim.Node.Chainstore, filcns.NewTipSetExecutor(), vm.Syscalls(mock.Verifier), newUpgradeSchedule, nil)
if err != nil {
return err
}

View File

@ -44,8 +44,7 @@ func sectorsFromClaim(sectorSize abi.SectorSize, c power.Claim) int64 {
}
func postChainCommitInfo(ctx context.Context, bb *blockbuilder.BlockBuilder, epoch abi.ChainEpoch) (abi.Randomness, error) {
cs := bb.StateManager().ChainStore()
ts := bb.ParentTipSet()
commitRand, err := cs.GetChainRandomness(ctx, ts.Cids(), crypto.DomainSeparationTag_PoStChainCommit, epoch, nil, true)
commitRand, err := bb.StateManager().GetRandomnessFromTickets(ctx, crypto.DomainSeparationTag_PoStChainCommit, epoch, nil, ts.Key())
return commitRand, err
}

View File

@ -520,7 +520,8 @@ func ImportChain(ctx context.Context, r repo.Repo, fname string, snapshot bool)
return err
}
stm, err := stmgr.NewStateManager(cst, filcns.NewTipSetExecutor(), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule())
// TODO: We need to supply the actual beacon after v14
stm, err := stmgr.NewStateManager(cst, filcns.NewTipSetExecutor(), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil)
if err != nil {
return err
}

View File

@ -104,7 +104,7 @@ func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, params
cs = store.NewChainStore(bs, bs, ds, filcns.Weight, nil)
tse = filcns.NewTipSetExecutor()
sm, err = stmgr.NewStateManager(cs, tse, syscalls, filcns.DefaultUpgradeSchedule())
sm, err = stmgr.NewStateManager(cs, tse, syscalls, filcns.DefaultUpgradeSchedule(), nil)
)
if err != nil {
return nil, err
@ -204,7 +204,7 @@ func (d *Driver) ExecuteMessage(bs blockstore.Blockstore, params ExecuteMessageP
// dummy state manager; only to reference the GetNetworkVersion method,
// which does not depend on state.
sm, err := stmgr.NewStateManager(nil, filcns.NewTipSetExecutor(), nil, filcns.DefaultUpgradeSchedule())
sm, err := stmgr.NewStateManager(nil, filcns.NewTipSetExecutor(), nil, filcns.DefaultUpgradeSchedule(), nil)
if err != nil {
return nil, cid.Cid{}, err
}

View File

@ -19,18 +19,22 @@ func NewFixedRand() vm.Rand {
return &fixedRand{}
}
func (r *fixedRand) GetChainRandomnessLookingForward(_ context.Context, _ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) ([]byte, error) {
func (r *fixedRand) GetChainRandomnessV1(_ context.Context, _ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) ([]byte, error) {
return []byte("i_am_random_____i_am_random_____"), nil // 32 bytes.
}
func (r *fixedRand) GetChainRandomnessLookingBack(_ context.Context, _ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) ([]byte, error) {
func (r *fixedRand) GetChainRandomnessV2(_ context.Context, _ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) ([]byte, error) {
return []byte("i_am_random_____i_am_random_____"), nil // 32 bytes.
}
func (r *fixedRand) GetBeaconRandomnessLookingForward(_ context.Context, _ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) ([]byte, error) {
func (r *fixedRand) GetBeaconRandomnessV3(_ context.Context, _ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) ([]byte, error) {
return []byte("i_am_random_____i_am_random_____"), nil // 32 bytes.
}
func (r *fixedRand) GetBeaconRandomnessLookingBack(_ context.Context, _ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) ([]byte, error) {
func (r *fixedRand) GetBeaconRandomnessV1(_ context.Context, _ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) ([]byte, error) {
return []byte("i_am_random_____i_am_random_____"), nil // 32 bytes.
}
func (r *fixedRand) GetBeaconRandomnessV2(_ context.Context, _ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) ([]byte, error) {
return []byte("i_am_random_____i_am_random_____"), nil // 32 bytes.
}

View File

@ -45,11 +45,11 @@ func (r *RecordingRand) loadHead() {
r.head = head.Key()
}
func (r *RecordingRand) GetChainRandomnessLookingForward(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (r *RecordingRand) GetChainRandomnessV2(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return r.getChainRandomness(ctx, pers, round, entropy)
}
func (r *RecordingRand) GetChainRandomnessLookingBack(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (r *RecordingRand) GetChainRandomnessV1(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return r.getChainRandomness(ctx, pers, round, entropy)
}
@ -79,17 +79,21 @@ func (r *RecordingRand) getChainRandomness(ctx context.Context, pers crypto.Doma
return ret, err
}
func (r *RecordingRand) GetBeaconRandomnessLookingForward(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (r *RecordingRand) GetBeaconRandomnessV3(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return r.getBeaconRandomness(ctx, pers, round, entropy)
}
func (r *RecordingRand) GetBeaconRandomnessLookingBack(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (r *RecordingRand) GetBeaconRandomnessV1(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return r.getBeaconRandomness(ctx, pers, round, entropy)
}
func (r *RecordingRand) GetBeaconRandomnessV2(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return r.getBeaconRandomness(ctx, pers, round, entropy)
}
func (r *RecordingRand) getBeaconRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
r.once.Do(r.loadHead)
ret, err := r.api.ChainGetRandomnessFromBeacon(ctx, r.head, pers, round, entropy)
ret, err := r.api.StateGetRandomnessFromBeacon(ctx, pers, round, entropy, r.head)
if err != nil {
return ret, err
}

View File

@ -43,11 +43,11 @@ func (r *ReplayingRand) match(requested schema.RandomnessRule) ([]byte, bool) {
return nil, false
}
func (r *ReplayingRand) GetChainRandomnessLookingForward(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (r *ReplayingRand) GetChainRandomnessV1(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return r.getChainRandomness(ctx, pers, round, entropy, false)
}
func (r *ReplayingRand) GetChainRandomnessLookingBack(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (r *ReplayingRand) GetChainRandomnessV2(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return r.getChainRandomness(ctx, pers, round, entropy, true)
}
@ -67,17 +67,21 @@ func (r *ReplayingRand) getChainRandomness(ctx context.Context, pers crypto.Doma
r.reporter.Logf("returning fallback chain randomness: dst=%d, epoch=%d, entropy=%x", pers, round, entropy)
if lookback {
return r.fallback.GetChainRandomnessLookingBack(ctx, pers, round, entropy)
return r.fallback.GetChainRandomnessV1(ctx, pers, round, entropy)
}
return r.fallback.GetChainRandomnessLookingForward(ctx, pers, round, entropy)
return r.fallback.GetChainRandomnessV2(ctx, pers, round, entropy)
}
func (r *ReplayingRand) GetBeaconRandomnessLookingForward(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (r *ReplayingRand) GetBeaconRandomnessV3(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return r.getBeaconRandomness(ctx, pers, round, entropy, false)
}
func (r *ReplayingRand) GetBeaconRandomnessLookingBack(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (r *ReplayingRand) GetBeaconRandomnessV1(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return r.getBeaconRandomness(ctx, pers, round, entropy, true)
}
func (r *ReplayingRand) GetBeaconRandomnessV2(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return r.getBeaconRandomness(ctx, pers, round, entropy, true)
}
@ -97,8 +101,8 @@ func (r *ReplayingRand) getBeaconRandomness(ctx context.Context, pers crypto.Dom
r.reporter.Logf("returning fallback beacon randomness: dst=%d, epoch=%d, entropy=%x", pers, round, entropy)
if lookback {
return r.fallback.GetBeaconRandomnessLookingBack(ctx, pers, round, entropy)
return r.fallback.GetBeaconRandomnessV1(ctx, pers, round, entropy)
}
return r.fallback.GetBeaconRandomnessLookingForward(ctx, pers, round, entropy)
return r.fallback.GetBeaconRandomnessV3(ctx, pers, round, entropy)
}

View File

@ -7,7 +7,7 @@ USAGE:
lotus-miner [global options] command [command options] [arguments...]
VERSION:
1.11.4-dev
1.13.0-dev
COMMANDS:
init Initialize a lotus miner repo
@ -278,7 +278,8 @@ USAGE:
lotus-miner actor withdraw [command options] [amount (FIL)]
OPTIONS:
--help, -h show help (default: false)
--confidence value number of block confirmations to wait for (default: 5)
--help, -h show help (default: false)
```

View File

@ -7,7 +7,7 @@ USAGE:
lotus-worker [global options] command [command options] [arguments...]
VERSION:
1.11.4-dev
1.13.0-dev
COMMANDS:
run Start lotus worker

View File

@ -7,7 +7,7 @@ USAGE:
lotus [global options] command [command options] [arguments...]
VERSION:
1.11.4-dev
1.13.0-dev
COMMANDS:
daemon Start a lotus daemon process
@ -388,6 +388,7 @@ USAGE:
OPTIONS:
--wallet value, -w value Specify address to withdraw funds to, otherwise it will use the default wallet address
--address value, -a value Market address to withdraw from (account or miner actor address, defaults to --wallet address)
--confidence value number of block confirmations to wait for (default: 5)
--help, -h show help (default: false)
```

View File

@ -361,12 +361,19 @@
# env var: LOTUS_SEALING_COMMITBATCHSLACK
#CommitBatchSlack = "1h0m0s"
# network BaseFee below which to stop doing precommit batching, instead
# sending precommit messages to the chain individually
#
# type: types.FIL
# env var: LOTUS_SEALING_BATCHPRECOMMITABOVEBASEFEE
#BatchPreCommitAboveBaseFee = "0.00000000032 FIL"
# network BaseFee below which to stop doing commit aggregation, instead
# submitting proofs to the chain individually
#
# type: types.FIL
# env var: LOTUS_SEALING_AGGREGATEABOVEBASEFEE
#AggregateAboveBaseFee = "0.00000000015 FIL"
#AggregateAboveBaseFee = "0.00000000032 FIL"
# type: uint64
# env var: LOTUS_SEALING_TERMINATEBATCHMAX

View File

@ -347,11 +347,12 @@ func (b *CommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.CommitBa
return []sealiface.CommitBatchRes{res}, xerrors.Errorf("getting network version: %s", err)
}
aggFeeRaw, err := policy.AggregateNetworkFee(nv, len(infos), bf)
aggFeeRaw, err := policy.AggregateProveCommitNetworkFee(nv, len(infos), bf)
if err != nil {
log.Errorf("getting aggregate network fee: %s", err)
return []sealiface.CommitBatchRes{res}, xerrors.Errorf("getting aggregate network fee: %s", err)
log.Errorf("getting aggregate commit network fee: %s", err)
return []sealiface.CommitBatchRes{res}, xerrors.Errorf("getting aggregate commit network fee: %s", err)
}
aggFee := big.Div(big.Mul(aggFeeRaw, aggFeeNum), aggFeeDen)
needFunds := big.Add(collateral, aggFee)

View File

@ -59,7 +59,8 @@ func TestCommitBatcher(t *testing.T) {
CommitBatchWait: 24 * time.Hour,
CommitBatchSlack: 1 * time.Hour,
AggregateAboveBaseFee: types.BigMul(types.PicoFil, types.NewInt(150)), // 0.15 nFIL
AggregateAboveBaseFee: types.BigMul(types.PicoFil, types.NewInt(150)), // 0.15 nFIL
BatchPreCommitAboveBaseFee: types.BigMul(types.PicoFil, types.NewInt(150)), // 0.15 nFIL
TerminateBatchMin: 1,
TerminateBatchMax: 100,

View File

@ -4,6 +4,8 @@ import (
"bytes"
"context"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/exitcode"
@ -20,6 +22,7 @@ type CurrentDealInfoAPI interface {
StateLookupID(context.Context, address.Address, TipSetToken) (address.Address, error)
StateMarketStorageDeal(context.Context, abi.DealID, TipSetToken) (*api.MarketDeal, error)
StateSearchMsg(context.Context, cid.Cid) (*MsgLookup, error)
StateNetworkVersion(ctx context.Context, tok TipSetToken) (network.Version, error)
}
type CurrentDealInfo struct {
@ -77,27 +80,38 @@ func (mgr *CurrentDealInfoManager) dealIDFromPublishDealsMsg(ctx context.Context
return dealID, nil, xerrors.Errorf("looking for publish deal message %s: non-ok exit code: %s", publishCid, lookup.Receipt.ExitCode)
}
var retval market.PublishStorageDealsReturn
if err := retval.UnmarshalCBOR(bytes.NewReader(lookup.Receipt.Return)); err != nil {
return dealID, nil, xerrors.Errorf("looking for publish deal message %s: unmarshalling message return: %w", publishCid, err)
nv, err := mgr.CDAPI.StateNetworkVersion(ctx, lookup.TipSetTok)
if err != nil {
return dealID, nil, xerrors.Errorf("getting network version: %w", err)
}
retval, err := market.DecodePublishStorageDealsReturn(lookup.Receipt.Return, nv)
if err != nil {
return dealID, nil, xerrors.Errorf("looking for publish deal message %s: decoding message return: %w", publishCid, err)
}
dealIDs, err := retval.DealIDs()
if err != nil {
return dealID, nil, xerrors.Errorf("looking for publish deal message %s: getting dealIDs: %w", publishCid, err)
}
// TODO: Can we delete this? We're well past the point when we first introduced the proposals into sealing deal info
// Previously, publish deals messages contained a single deal, and the
// deal proposal was not included in the sealing deal info.
// So check if the proposal is nil and check the number of deals published
// in the message.
if proposal == nil {
if len(retval.IDs) > 1 {
if len(dealIDs) > 1 {
return dealID, nil, xerrors.Errorf(
"getting deal ID from publish deal message %s: "+
"no deal proposal supplied but message return value has more than one deal (%d deals)",
publishCid, len(retval.IDs))
publishCid, len(dealIDs))
}
// There is a single deal in this publish message and no deal proposal
// was supplied, so we have nothing to compare against. Just assume
// the deal ID is correct.
return retval.IDs[0], lookup.TipSetTok, nil
// the deal ID is correct and that it was valid
return dealIDs[0], lookup.TipSetTok, nil
}
// Get the parameters to the publish deals message
@ -129,13 +143,22 @@ func (mgr *CurrentDealInfoManager) dealIDFromPublishDealsMsg(ctx context.Context
return dealID, nil, xerrors.Errorf("could not find deal in publish deals message %s", publishCid)
}
if dealIdx >= len(retval.IDs) {
if dealIdx >= len(dealIDs) {
return dealID, nil, xerrors.Errorf(
"deal index %d out of bounds of deals (len %d) in publish deals message %s",
dealIdx, len(retval.IDs), publishCid)
dealIdx, len(dealIDs), publishCid)
}
return retval.IDs[dealIdx], lookup.TipSetTok, nil
valid, err := retval.IsDealValid(uint64(dealIdx))
if err != nil {
return dealID, nil, xerrors.Errorf("determining deal validity: %w", err)
}
if !valid {
return dealID, nil, xerrors.New("deal was invalid at publication")
}
return dealIDs[dealIdx], lookup.TipSetTok, nil
}
func (mgr *CurrentDealInfoManager) CheckDealEquality(ctx context.Context, tok TipSetToken, p1, p2 market.DealProposal) (bool, error) {
@ -165,6 +188,7 @@ type CurrentDealInfoTskAPI interface {
StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error)
StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error)
StateSearchMsg(ctx context.Context, from types.TipSetKey, msg cid.Cid, limit abi.ChainEpoch, allowReplaced bool) (*api.MsgLookup, error)
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
}
type CurrentDealInfoAPIAdapter struct {
@ -210,4 +234,13 @@ func (c *CurrentDealInfoAPIAdapter) StateSearchMsg(ctx context.Context, k cid.Ci
}, nil
}
func (c *CurrentDealInfoAPIAdapter) StateNetworkVersion(ctx context.Context, tok TipSetToken) (network.Version, error) {
tsk, err := types.TipSetKeyFromBytes(tok)
if err != nil {
return network.VersionMax, xerrors.Errorf("failed to unmarshal TipSetToken to TipSetKey: %w", err)
}
return c.CurrentDealInfoTskAPI.StateNetworkVersion(ctx, tsk)
}
var _ CurrentDealInfoAPI = (*CurrentDealInfoAPIAdapter)(nil)

View File

@ -8,6 +8,10 @@ import (
"testing"
"time"
"github.com/filecoin-project/go-state-types/network"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
"golang.org/x/net/context"
"golang.org/x/xerrors"
@ -207,7 +211,7 @@ func TestGetCurrentDealInfo(t *testing.T) {
},
targetProposal: &proposal,
expectedDealID: zeroDealID,
expectedError: xerrors.Errorf("looking for publish deal message %s: unmarshalling message return: cbor input should be of type array", dummyCid),
expectedError: xerrors.Errorf("looking for publish deal message %s: decoding message return: failed to unmarshal PublishStorageDealsReturn: cbor input should be of type array", dummyCid),
},
}
runTestCase := func(testCase string, data testCaseData) {
@ -305,9 +309,13 @@ func (mapi *CurrentDealInfoMockAPI) StateSearchMsg(ctx context.Context, c cid.Ci
return mapi.SearchMessageLookup, mapi.SearchMessageErr
}
func (mapi *CurrentDealInfoMockAPI) StateNetworkVersion(ctx context.Context, tok TipSetToken) (network.Version, error) {
return network.Version0, nil
}
func makePublishDealsReturnBytes(t *testing.T, dealIDs []abi.DealID) []byte {
buf := new(bytes.Buffer)
dealsReturn := market.PublishStorageDealsReturn{
dealsReturn := market0.PublishStorageDealsReturn{
IDs: dealIDs,
}
err := dealsReturn.MarshalCBOR(buf)

View File

@ -11,6 +11,7 @@ import (
address "github.com/filecoin-project/go-address"
abi "github.com/filecoin-project/go-state-types/abi"
big "github.com/filecoin-project/go-state-types/big"
network "github.com/filecoin-project/go-state-types/network"
miner "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
gomock "github.com/golang/mock/gomock"
@ -40,6 +41,21 @@ func (m *MockPreCommitBatcherApi) EXPECT() *MockPreCommitBatcherApiMockRecorder
return m.recorder
}
// ChainBaseFee mocks base method.
func (m *MockPreCommitBatcherApi) ChainBaseFee(arg0 context.Context, arg1 sealing.TipSetToken) (big.Int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChainBaseFee", arg0, arg1)
ret0, _ := ret[0].(big.Int)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ChainBaseFee indicates an expected call of ChainBaseFee.
func (mr *MockPreCommitBatcherApiMockRecorder) ChainBaseFee(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainBaseFee", reflect.TypeOf((*MockPreCommitBatcherApi)(nil).ChainBaseFee), arg0, arg1)
}
// ChainHead mocks base method.
func (m *MockPreCommitBatcherApi) ChainHead(arg0 context.Context) (sealing.TipSetToken, abi.ChainEpoch, error) {
m.ctrl.T.Helper()
@ -100,3 +116,18 @@ func (mr *MockPreCommitBatcherApiMockRecorder) StateMinerInfo(arg0, arg1, arg2 i
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateMinerInfo", reflect.TypeOf((*MockPreCommitBatcherApi)(nil).StateMinerInfo), arg0, arg1, arg2)
}
// StateNetworkVersion mocks base method.
func (m *MockPreCommitBatcherApi) StateNetworkVersion(arg0 context.Context, arg1 sealing.TipSetToken) (network.Version, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateNetworkVersion", arg0, arg1)
ret0, _ := ret[0].(network.Version)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateNetworkVersion indicates an expected call of StateNetworkVersion.
func (mr *MockPreCommitBatcherApiMockRecorder) StateNetworkVersion(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateNetworkVersion", reflect.TypeOf((*MockPreCommitBatcherApi)(nil).StateNetworkVersion), arg0, arg1)
}

View File

@ -7,6 +7,8 @@ import (
"sync"
"time"
"github.com/filecoin-project/go-state-types/network"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
@ -20,6 +22,7 @@ import (
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/extern/storage-sealing/sealiface"
"github.com/filecoin-project/lotus/node/config"
)
@ -31,6 +34,8 @@ type PreCommitBatcherApi interface {
StateMinerInfo(context.Context, address.Address, TipSetToken) (miner.MinerInfo, error)
StateMinerAvailableBalance(context.Context, address.Address, TipSetToken) (big.Int, error)
ChainHead(ctx context.Context) (TipSetToken, abi.ChainEpoch, error)
ChainBaseFee(context.Context, TipSetToken) (abi.TokenAmount, error)
StateNetworkVersion(ctx context.Context, tok TipSetToken) (network.Version, error)
}
type preCommitEntry struct {
@ -185,8 +190,34 @@ func (b *PreCommitBatcher) maybeStartBatch(notif bool) ([]sealiface.PreCommitBat
return nil, nil
}
tok, _, err := b.api.ChainHead(b.mctx)
if err != nil {
return nil, err
}
bf, err := b.api.ChainBaseFee(b.mctx, tok)
if err != nil {
return nil, xerrors.Errorf("couldn't get base fee: %w", err)
}
// TODO: Drop this once nv14 has come and gone
nv, err := b.api.StateNetworkVersion(b.mctx, tok)
if err != nil {
return nil, xerrors.Errorf("couldn't get network version: %w", err)
}
individual := false
if !cfg.BatchPreCommitAboveBaseFee.Equals(big.Zero()) && bf.LessThan(cfg.BatchPreCommitAboveBaseFee) && nv >= network.Version14 {
individual = true
}
// todo support multiple batches
res, err := b.processBatch(cfg)
var res []sealiface.PreCommitBatchRes
if !individual {
res, err = b.processBatch(cfg, tok, bf, nv)
} else {
res, err = b.processIndividually(cfg)
}
if err != nil && len(res) == 0 {
return nil, err
}
@ -210,7 +241,83 @@ func (b *PreCommitBatcher) maybeStartBatch(notif bool) ([]sealiface.PreCommitBat
return res, nil
}
func (b *PreCommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.PreCommitBatchRes, error) {
func (b *PreCommitBatcher) processIndividually(cfg sealiface.Config) ([]sealiface.PreCommitBatchRes, error) {
mi, err := b.api.StateMinerInfo(b.mctx, b.maddr, nil)
if err != nil {
return nil, xerrors.Errorf("couldn't get miner info: %w", err)
}
avail := types.TotalFilecoinInt
if cfg.CollateralFromMinerBalance && !cfg.DisableCollateralFallback {
avail, err = b.api.StateMinerAvailableBalance(b.mctx, b.maddr, nil)
if err != nil {
return nil, xerrors.Errorf("getting available miner balance: %w", err)
}
avail = big.Sub(avail, cfg.AvailableBalanceBuffer)
if avail.LessThan(big.Zero()) {
avail = big.Zero()
}
}
var res []sealiface.PreCommitBatchRes
for sn, info := range b.todo {
r := sealiface.PreCommitBatchRes{
Sectors: []abi.SectorNumber{sn},
}
mcid, err := b.processSingle(cfg, mi, &avail, info)
if err != nil {
r.Error = err.Error()
} else {
r.Msg = &mcid
}
res = append(res, r)
}
return res, nil
}
func (b *PreCommitBatcher) processSingle(cfg sealiface.Config, mi miner.MinerInfo, avail *abi.TokenAmount, params *preCommitEntry) (cid.Cid, error) {
enc := new(bytes.Buffer)
if err := params.pci.MarshalCBOR(enc); err != nil {
return cid.Undef, xerrors.Errorf("marshaling precommit params: %w", err)
}
deposit := params.deposit
if cfg.CollateralFromMinerBalance {
c := big.Sub(deposit, *avail)
*avail = big.Sub(*avail, deposit)
deposit = c
if deposit.LessThan(big.Zero()) {
deposit = big.Zero()
}
if (*avail).LessThan(big.Zero()) {
*avail = big.Zero()
}
}
goodFunds := big.Add(deposit, big.Int(b.feeCfg.MaxPreCommitGasFee))
from, _, err := b.addrSel(b.mctx, mi, api.PreCommitAddr, goodFunds, deposit)
if err != nil {
return cid.Undef, xerrors.Errorf("no good address to send precommit message from: %w", err)
}
mcid, err := b.api.SendMsg(b.mctx, from, b.maddr, miner.Methods.PreCommitSector, deposit, big.Int(b.feeCfg.MaxPreCommitGasFee), enc.Bytes())
if err != nil {
return cid.Undef, xerrors.Errorf("pushing message to mpool: %w", err)
}
return mcid, nil
}
func (b *PreCommitBatcher) processBatch(cfg sealiface.Config, tok TipSetToken, bf abi.TokenAmount, nv network.Version) ([]sealiface.PreCommitBatchRes, error) {
params := miner5.PreCommitSectorBatchParams{}
deposit := big.Zero()
var res sealiface.PreCommitBatchRes
@ -226,11 +333,6 @@ func (b *PreCommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.PreCo
deposit = big.Add(deposit, p.deposit)
}
deposit, err := collateralSendAmount(b.mctx, b.api, b.maddr, cfg, deposit)
if err != nil {
return []sealiface.PreCommitBatchRes{res}, err
}
enc := new(bytes.Buffer)
if err := params.MarshalCBOR(enc); err != nil {
return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("couldn't serialize PreCommitSectorBatchParams: %w", err)
@ -242,14 +344,29 @@ func (b *PreCommitBatcher) processBatch(cfg sealiface.Config) ([]sealiface.PreCo
}
maxFee := b.feeCfg.MaxPreCommitBatchGasFee.FeeForSectors(len(params.Sectors))
goodFunds := big.Add(deposit, maxFee)
aggFeeRaw, err := policy.AggregatePreCommitNetworkFee(nv, len(params.Sectors), bf)
if err != nil {
log.Errorf("getting aggregate precommit network fee: %s", err)
return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("getting aggregate precommit network fee: %s", err)
}
aggFee := big.Div(big.Mul(aggFeeRaw, aggFeeNum), aggFeeDen)
needFunds := big.Add(deposit, aggFee)
needFunds, err = collateralSendAmount(b.mctx, b.api, b.maddr, cfg, needFunds)
if err != nil {
return []sealiface.PreCommitBatchRes{res}, err
}
goodFunds := big.Add(maxFee, needFunds)
from, _, err := b.addrSel(b.mctx, mi, api.PreCommitAddr, goodFunds, deposit)
if err != nil {
return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("no good address found: %w", err)
}
mcid, err := b.api.SendMsg(b.mctx, from, b.maddr, miner.Methods.PreCommitSectorBatch, deposit, maxFee, enc.Bytes())
mcid, err := b.api.SendMsg(b.mctx, from, b.maddr, miner.Methods.PreCommitSectorBatch, needFunds, maxFee, enc.Bytes())
if err != nil {
return []sealiface.PreCommitBatchRes{res}, xerrors.Errorf("sending message failed: %w", err)
}

View File

@ -8,13 +8,16 @@ import (
"testing"
"time"
miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner"
"github.com/filecoin-project/go-state-types/network"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
@ -44,7 +47,7 @@ func TestPrecommitBatcher(t *testing.T) {
return t0123, big.Zero(), nil
}
maxBatch := miner5.PreCommitSectorBatchMaxSize
maxBatch := miner6.PreCommitSectorBatchMaxSize
cfg := func() (sealiface.Config, error) {
return sealiface.Config{
@ -54,14 +57,15 @@ func TestPrecommitBatcher(t *testing.T) {
WaitDealsDelay: time.Hour * 6,
AlwaysKeepUnsealedCopy: true,
BatchPreCommits: true,
MaxPreCommitBatch: maxBatch,
PreCommitBatchWait: 24 * time.Hour,
PreCommitBatchSlack: 3 * time.Hour,
BatchPreCommits: true,
MaxPreCommitBatch: maxBatch,
PreCommitBatchWait: 24 * time.Hour,
PreCommitBatchSlack: 3 * time.Hour,
BatchPreCommitAboveBaseFee: big.NewInt(10000),
AggregateCommits: true,
MinCommitBatch: miner5.MinAggregatedSectors,
MaxCommitBatch: miner5.MaxAggregatedSectors,
MinCommitBatch: miner6.MinAggregatedSectors,
MaxCommitBatch: miner6.MaxAggregatedSectors,
CommitBatchWait: 24 * time.Hour,
CommitBatchSlack: 1 * time.Hour,
@ -149,10 +153,14 @@ func TestPrecommitBatcher(t *testing.T) {
expectSend := func(expect []abi.SectorNumber) action {
return func(t *testing.T, s *mocks.MockPreCommitBatcherApi, pcb *sealing.PreCommitBatcher) promise {
s.EXPECT().ChainHead(gomock.Any()).Return(nil, abi.ChainEpoch(1), nil)
s.EXPECT().ChainBaseFee(gomock.Any(), gomock.Any()).Return(big.NewInt(10001), nil)
s.EXPECT().StateNetworkVersion(gomock.Any(), gomock.Any()).Return(network.Version14, nil)
s.EXPECT().StateMinerInfo(gomock.Any(), gomock.Any(), gomock.Any()).Return(miner.MinerInfo{Owner: t0123, Worker: t0123}, nil)
s.EXPECT().SendMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), funMatcher(func(i interface{}) bool {
b := i.([]byte)
var params miner5.PreCommitSectorBatchParams
var params miner6.PreCommitSectorBatchParams
require.NoError(t, params.UnmarshalCBOR(bytes.NewReader(b)))
for s, number := range expect {
require.Equal(t, number, params.Sectors[s].SectorNumber)
@ -163,6 +171,27 @@ func TestPrecommitBatcher(t *testing.T) {
}
}
expectSendsSingle := func(expect []abi.SectorNumber) action {
return func(t *testing.T, s *mocks.MockPreCommitBatcherApi, pcb *sealing.PreCommitBatcher) promise {
s.EXPECT().ChainHead(gomock.Any()).Return(nil, abi.ChainEpoch(1), nil)
s.EXPECT().ChainBaseFee(gomock.Any(), gomock.Any()).Return(big.NewInt(9999), nil)
s.EXPECT().StateNetworkVersion(gomock.Any(), gomock.Any()).Return(network.Version14, nil)
s.EXPECT().StateMinerInfo(gomock.Any(), gomock.Any(), gomock.Any()).Return(miner.MinerInfo{Owner: t0123, Worker: t0123}, nil)
for _, number := range expect {
numClone := number
s.EXPECT().SendMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), funMatcher(func(i interface{}) bool {
b := i.([]byte)
var params miner6.PreCommitSectorParams
require.NoError(t, params.UnmarshalCBOR(bytes.NewReader(b)))
require.Equal(t, numClone, params.SectorNumber)
return true
}))
}
return nil
}
}
flush := func(expect []abi.SectorNumber) action {
return func(t *testing.T, s *mocks.MockPreCommitBatcherApi, pcb *sealing.PreCommitBatcher) promise {
_ = expectSend(expect)(t, s, pcb)
@ -211,6 +240,12 @@ func TestPrecommitBatcher(t *testing.T) {
addSectors(getSectors(maxBatch)),
},
},
"addMax-belowBaseFee": {
actions: []action{
expectSendsSingle(getSectors(maxBatch)),
addSectors(getSectors(maxBatch)),
},
},
}
for name, tc := range tcs {

View File

@ -43,7 +43,8 @@ type Config struct {
CommitBatchWait time.Duration
CommitBatchSlack time.Duration
AggregateAboveBaseFee abi.TokenAmount
AggregateAboveBaseFee abi.TokenAmount
BatchPreCommitAboveBaseFee abi.TokenAmount
TerminateBatchMax uint64
TerminateBatchMin uint64

View File

@ -3,9 +3,12 @@ package sealing_test
import (
"bytes"
"context"
"errors"
"testing"
"github.com/filecoin-project/go-state-types/network"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/golang/mock/gomock"
"github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"
@ -21,64 +24,6 @@ import (
"github.com/filecoin-project/lotus/extern/storage-sealing/mocks"
)
func TestStateRecoverDealIDsErredDealInfo(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
ctx := context.Background()
api := mocks.NewMockSealingAPI(mockCtrl)
fakeSealing := &sealing.Sealing{
Api: api,
DealInfo: &sealing.CurrentDealInfoManager{CDAPI: api},
}
sctx := mocks.NewMockContext(mockCtrl)
sctx.EXPECT().Context().AnyTimes().Return(ctx)
api.EXPECT().ChainHead(ctx).Times(1).Return(nil, abi.ChainEpoch(10), nil)
var dealId abi.DealID = 12
dealProposal := market.DealProposal{
PieceCID: idCid("newPieceCID"),
}
api.EXPECT().StateMarketStorageDealProposal(ctx, dealId, nil).Return(dealProposal, nil)
pc := idCid("publishCID")
// expect GetCurrentDealInfo
{
api.EXPECT().StateSearchMsg(ctx, pc).Return(&sealing.MsgLookup{
Receipt: sealing.MessageReceipt{
ExitCode: exitcode.Ok,
Return: cborRet(&market.PublishStorageDealsReturn{
IDs: []abi.DealID{dealId},
}),
},
}, nil)
api.EXPECT().StateMarketStorageDeal(ctx, dealId, nil).Return(nil, errors.New("deal may not have completed sealing or slashed"))
}
sctx.EXPECT().Send(sealing.SectorRemove{}).Return(nil)
err := fakeSealing.HandleRecoverDealIDs(sctx, sealing.SectorInfo{
Pieces: []sealing.Piece{
{
DealInfo: &api2.PieceDealInfo{
DealID: dealId,
PublishCid: &pc,
},
Piece: abi.PieceInfo{
PieceCID: idCid("oldPieceCID"),
},
},
},
})
require.NoError(t, err)
}
func TestStateRecoverDealIDs(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
@ -111,11 +56,12 @@ func TestStateRecoverDealIDs(t *testing.T) {
api.EXPECT().StateSearchMsg(ctx, pc).Return(&sealing.MsgLookup{
Receipt: sealing.MessageReceipt{
ExitCode: exitcode.Ok,
Return: cborRet(&market.PublishStorageDealsReturn{
Return: cborRet(&market0.PublishStorageDealsReturn{
IDs: []abi.DealID{dealId},
}),
},
}, nil)
api.EXPECT().StateNetworkVersion(ctx, nil).Return(network.Version0, nil)
api.EXPECT().StateMarketStorageDeal(ctx, dealId, nil).Return(&api2.MarketDeal{
Proposal: dealProposal,
}, nil)

3
go.mod
View File

@ -40,7 +40,7 @@ require (
github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec
github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1
github.com/filecoin-project/go-paramfetch v0.0.2
github.com/filecoin-project/go-state-types v0.1.1-0.20210810190654-139e0e79e69e
github.com/filecoin-project/go-state-types v0.1.1-0.20210915140513-d354ccf10379
github.com/filecoin-project/go-statemachine v1.0.1
github.com/filecoin-project/go-statestore v0.1.1
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b
@ -49,6 +49,7 @@ require (
github.com/filecoin-project/specs-actors/v3 v3.1.1
github.com/filecoin-project/specs-actors/v4 v4.0.1
github.com/filecoin-project/specs-actors/v5 v5.0.4
github.com/filecoin-project/specs-actors/v6 v6.0.0-20211001193936-c3afe7fa3c5c
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

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