diff --git a/.circleci/config.yml b/.circleci/config.yml index 41b18b048..c50b26173 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -201,6 +201,8 @@ jobs: <<: *test test-window-post: <<: *test + test-window-post-dispute: + <<: *test test-terminate: <<: *test test-conformance: @@ -591,6 +593,11 @@ workflows: go-test-flags: "-run=TestWindowedPost" winpost-test: "1" test-suite-name: window-post + - test-window-post-dispute: + codecov-upload: true + go-test-flags: "-run=TestWindowPostDispute" + winpost-test: "1" + test-suite-name: window-post-dispute - test-terminate: codecov-upload: true go-test-flags: "-run=TestTerminate" diff --git a/api/test/ccupgrade.go b/api/test/ccupgrade.go index eedcec6ca..606b9f22b 100644 --- a/api/test/ccupgrade.go +++ b/api/test/ccupgrade.go @@ -17,9 +17,9 @@ import ( func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) { for _, height := range []abi.ChainEpoch{ - 1, // before + 2, // before 162, // while sealing - 520, // after upgrade deal + 530, // after upgrade deal 5000, // after } { height := height // make linters happy by copying @@ -31,7 +31,7 @@ func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) { func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeHeight abi.ChainEpoch) { ctx := context.Background() - n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV2At(upgradeHeight)}, OneMiner) + n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV3At(upgradeHeight)}, OneMiner) client := n[0].FullNode.(*impl.FullNodeAPI) miner := sn[0] diff --git a/api/test/test.go b/api/test/test.go index a1b82c590..f498cb974 100644 --- a/api/test/test.go +++ b/api/test/test.go @@ -48,6 +48,7 @@ type TestStorageNode struct { ListenAddr multiaddr.Multiaddr MineOne func(context.Context, miner.MineReq) error + Stop func(context.Context) error } var PresealGenesis = -1 @@ -109,14 +110,19 @@ var OneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}} var OneFull = DefaultFullOpts(1) var TwoFull = DefaultFullOpts(2) -var FullNodeWithActorsV2At = func(upgradeHeight abi.ChainEpoch) FullNodeOpts { +var FullNodeWithActorsV3At = func(upgradeHeight abi.ChainEpoch) FullNodeOpts { return FullNodeOpts{ Opts: func(nodes []TestNode) node.Option { return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{ - // Skip directly to tape height so precommits work. - Network: network.Version5, - Height: upgradeHeight, + // prepare for upgrade. + Network: network.Version9, + Height: 1, Migration: stmgr.UpgradeActorsV2, + }, { + // Skip directly to tape height so precommits work. + Network: network.Version10, + Height: upgradeHeight, + Migration: stmgr.UpgradeActorsV3, }}) }, } diff --git a/api/test/window_post.go b/api/test/window_post.go index 84d668c76..f8ab9412d 100644 --- a/api/test/window_post.go +++ b/api/test/window_post.go @@ -16,13 +16,18 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/lotus/extern/sector-storage/mock" sealing "github.com/filecoin-project/lotus/extern/storage-sealing" + proof3 "github.com/filecoin-project/specs-actors/v3/actors/runtime/proof" "github.com/filecoin-project/specs-storage/storage" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/types" bminer "github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/node/impl" @@ -201,7 +206,7 @@ func pledgeSectors(t *testing.T, ctx context.Context, miner TestStorageNode, n, func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) { for _, height := range []abi.ChainEpoch{ - 1, // before + 2, // before 162, // while sealing 5000, // while proving } { @@ -218,7 +223,7 @@ func testWindowPostUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, ctx, cancel := context.WithCancel(context.Background()) defer cancel() - n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV2At(upgradeHeight)}, OneMiner) + n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV3At(upgradeHeight)}, OneMiner) client := n[0].FullNode.(*impl.FullNodeAPI) miner := sn[0] @@ -437,7 +442,7 @@ func TestTerminate(t *testing.T, b APIBuilder, blocktime time.Duration) { nSectors := uint64(2) - n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV2At(1)}, []StorageMiner{{Full: 0, Preseal: int(nSectors)}}) + n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV3At(2)}, []StorageMiner{{Full: 0, Preseal: int(nSectors)}}) client := n[0].FullNode.(*impl.FullNodeAPI) miner := sn[0] @@ -602,3 +607,292 @@ loop: require.Equal(t, p.MinerPower, p.TotalPower) require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)*(nSectors-1))) } + +func TestWindowPostDispute(t *testing.T, b APIBuilder, blocktime time.Duration) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // First, we configure two miners. After sealing, we're going to turn off the first miner so + // it doesn't submit proofs. + /// + // Then we're going to manually submit bad proofs. + n, sn := b(t, []FullNodeOpts{ + FullNodeWithActorsV3At(2), + }, []StorageMiner{ + {Full: 0, Preseal: PresealGenesis}, + {Full: 0}, + }) + + client := n[0].FullNode.(*impl.FullNodeAPI) + chainMiner := sn[0] + evilMiner := sn[1] + + { + addrinfo, err := client.NetAddrsListen(ctx) + if err != nil { + t.Fatal(err) + } + + if err := chainMiner.NetConnect(ctx, addrinfo); err != nil { + t.Fatal(err) + } + + if err := evilMiner.NetConnect(ctx, addrinfo); err != nil { + t.Fatal(err) + } + } + + defaultFrom, err := client.WalletDefaultAddress(ctx) + require.NoError(t, err) + + build.Clock.Sleep(time.Second) + + // Mine with the _second_ node (the good one). + done := make(chan struct{}) + go func() { + defer close(done) + for ctx.Err() == nil { + build.Clock.Sleep(blocktime) + if err := chainMiner.MineOne(ctx, MineNext); err != nil { + if ctx.Err() != nil { + // context was canceled, ignore the error. + return + } + t.Error(err) + } + } + }() + defer func() { + cancel() + <-done + }() + + // Give the chain miner enough sectors to win every block. + pledgeSectors(t, ctx, chainMiner, 10, 0, nil) + // And the evil one 1 sector. No cookie for you. + pledgeSectors(t, ctx, evilMiner, 1, 0, nil) + + // Let the evil miner's sectors gain power. + evilMinerAddr, err := evilMiner.ActorAddress(ctx) + require.NoError(t, err) + + di, err := client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK) + require.NoError(t, err) + + fmt.Printf("Running one proving period\n") + fmt.Printf("End for head.Height > %d\n", di.PeriodStart+di.WPoStProvingPeriod*2) + + for { + head, err := client.ChainHead(ctx) + require.NoError(t, err) + + if head.Height() > di.PeriodStart+di.WPoStProvingPeriod*2 { + fmt.Printf("Now head.Height = %d\n", head.Height()) + break + } + build.Clock.Sleep(blocktime) + } + + p, err := client.StateMinerPower(ctx, evilMinerAddr, types.EmptyTSK) + require.NoError(t, err) + + ssz, err := evilMiner.ActorSectorSize(ctx, evilMinerAddr) + require.NoError(t, err) + + // make sure it has gained power. + require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz))) + + evilSectors, err := evilMiner.SectorsList(ctx) + require.NoError(t, err) + evilSectorNo := evilSectors[0] // only one. + evilSectorLoc, err := client.StateSectorPartition(ctx, evilMinerAddr, evilSectorNo, types.EmptyTSK) + require.NoError(t, err) + + fmt.Println("evil miner stopping") + + // Now stop the evil miner, and start manually submitting bad proofs. + require.NoError(t, evilMiner.Stop(ctx)) + + fmt.Println("evil miner stopped") + + // Wait until we need to prove our sector. + for { + di, err = client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK) + require.NoError(t, err) + if di.Index == evilSectorLoc.Deadline { + break + } + build.Clock.Sleep(blocktime) + } + + err = submitBadProof(ctx, client, evilMinerAddr, di, evilSectorLoc.Deadline, evilSectorLoc.Partition) + require.NoError(t, err, "evil proof not accepted") + + // Wait until after the proving period. + for { + di, err = client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK) + require.NoError(t, err) + if di.Index != evilSectorLoc.Deadline { + break + } + build.Clock.Sleep(blocktime) + } + + fmt.Println("accepted evil proof") + + // Make sure the evil node didn't lose any power. + p, err = client.StateMinerPower(ctx, evilMinerAddr, types.EmptyTSK) + require.NoError(t, err) + require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz))) + + // OBJECTION! The good miner files a DISPUTE!!!! + { + params := &miner.DisputeWindowedPoStParams{ + Deadline: evilSectorLoc.Deadline, + PoStIndex: 0, + } + + enc, aerr := actors.SerializeParams(params) + require.NoError(t, aerr) + + msg := &types.Message{ + To: evilMinerAddr, + Method: miner.Methods.DisputeWindowedPoSt, + Params: enc, + Value: types.NewInt(0), + From: defaultFrom, + } + sm, err := client.MpoolPushMessage(ctx, msg, nil) + require.NoError(t, err) + + fmt.Println("waiting dispute") + rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence) + require.NoError(t, err) + require.Zero(t, rec.Receipt.ExitCode, "dispute not accepted: %s", rec.Receipt.ExitCode.Error()) + fmt.Println("GASS!!!: ", rec.Receipt.GasUsed) + } + + // Objection SUSTAINED! + // Make sure the evil node lost power. + p, err = client.StateMinerPower(ctx, evilMinerAddr, types.EmptyTSK) + require.NoError(t, err) + require.True(t, p.MinerPower.RawBytePower.IsZero()) + + // Now we begin the redemption arc. + require.True(t, p.MinerPower.RawBytePower.IsZero()) + + // First, recover the sector. + + { + minerInfo, err := client.StateMinerInfo(ctx, evilMinerAddr, types.EmptyTSK) + require.NoError(t, err) + + params := &miner.DeclareFaultsRecoveredParams{ + Recoveries: []miner.RecoveryDeclaration{{ + Deadline: evilSectorLoc.Deadline, + Partition: evilSectorLoc.Partition, + Sectors: bitfield.NewFromSet([]uint64{uint64(evilSectorNo)}), + }}, + } + + enc, aerr := actors.SerializeParams(params) + require.NoError(t, aerr) + + msg := &types.Message{ + To: evilMinerAddr, + Method: miner.Methods.DeclareFaultsRecovered, + Params: enc, + Value: types.FromFil(30), // repay debt. + From: minerInfo.Owner, + } + sm, err := client.MpoolPushMessage(ctx, msg, nil) + require.NoError(t, err) + + rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence) + require.NoError(t, err) + require.Zero(t, rec.Receipt.ExitCode, "recovery not accepted: %s", rec.Receipt.ExitCode.Error()) + } + + // Then wait for the deadline. + for { + di, err = client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK) + require.NoError(t, err) + if di.Index == evilSectorLoc.Deadline { + break + } + build.Clock.Sleep(blocktime) + } + + // Now try to be evil again + err = submitBadProof(ctx, client, evilMinerAddr, di, evilSectorLoc.Deadline, evilSectorLoc.Partition) + require.Error(t, err) + require.Contains(t, err.Error(), "message execution failed: exit 16, reason: window post failed: invalid PoSt") + + // It didn't work because we're recovering. +} + +func submitBadProof( + ctx context.Context, + client api.FullNode, maddr address.Address, + di *dline.Info, dlIdx, partIdx uint64, +) error { + head, err := client.ChainHead(ctx) + if err != nil { + return err + } + + from, err := client.WalletDefaultAddress(ctx) + if err != nil { + return err + } + + minerInfo, err := client.StateMinerInfo(ctx, maddr, head.Key()) + if err != nil { + return err + } + + commEpoch := di.Open + commRand, err := client.ChainGetRandomnessFromTickets( + ctx, head.Key(), crypto.DomainSeparationTag_PoStChainCommit, + commEpoch, nil, + ) + if err != nil { + return err + } + params := &miner.SubmitWindowedPoStParams{ + ChainCommitEpoch: commEpoch, + ChainCommitRand: commRand, + Deadline: dlIdx, + Partitions: []miner.PoStPartition{{Index: partIdx}}, + Proofs: []proof3.PoStProof{{ + PoStProof: minerInfo.WindowPoStProofType, + ProofBytes: []byte("I'm soooo very evil."), + }}, + } + + enc, aerr := actors.SerializeParams(params) + if aerr != nil { + return aerr + } + + msg := &types.Message{ + To: maddr, + Method: miner.Methods.SubmitWindowedPoSt, + Params: enc, + Value: types.NewInt(0), + From: from, + } + sm, err := client.MpoolPushMessage(ctx, msg, nil) + if err != nil { + return err + } + + rec, err := client.StateWaitMsg(ctx, sm.Cid(), build.MessageConfidence) + if err != nil { + return err + } + if rec.Receipt.ExitCode.IsError() { + return rec.Receipt.ExitCode + } + return nil +} diff --git a/build/params_2k.go b/build/params_2k.go index ecac86983..63f7e70b4 100644 --- a/build/params_2k.go +++ b/build/params_2k.go @@ -27,6 +27,8 @@ const UpgradePersianHeight = 25 const UpgradeOrangeHeight = 27 const UpgradeClausHeight = 30 +const UpgradeActorsV3Height = 35 + var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, } diff --git a/build/params_calibnet.go b/build/params_calibnet.go index 670efa776..a102823db 100644 --- a/build/params_calibnet.go +++ b/build/params_calibnet.go @@ -44,6 +44,9 @@ const UpgradeClausHeight = 161386 // 2021-01-17T19:00:00Z const UpgradeOrangeHeight = 250666 +// TODO +var UpgradeActorsV3Height = 99999999 + func init() { policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 30)) policy.SetSupportedProofTypes( diff --git a/build/params_mainnet.go b/build/params_mainnet.go index a4c3ab04f..bf322a744 100644 --- a/build/params_mainnet.go +++ b/build/params_mainnet.go @@ -50,6 +50,9 @@ const UpgradeOrangeHeight = 336458 // 2020-12-22T02:00:00Z const UpgradeClausHeight = 343200 +// TODO +const UpgradeActorsV3Height = 999999999 + func init() { policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40)) diff --git a/build/params_testground.go b/build/params_testground.go index 8537ba33f..759b29692 100644 --- a/build/params_testground.go +++ b/build/params_testground.go @@ -90,8 +90,9 @@ var ( UpgradeKumquatHeight abi.ChainEpoch = -6 UpgradeCalicoHeight abi.ChainEpoch = -7 UpgradePersianHeight abi.ChainEpoch = -8 - UpgradeClausHeight abi.ChainEpoch = -9 - UpgradeOrangeHeight abi.ChainEpoch = -10 + UpgradeOrangeHeight abi.ChainEpoch = -9 + UpgradeClausHeight abi.ChainEpoch = -10 + UpgradeActorsV3Height abi.ChainEpoch = -11 DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, diff --git a/chain/actors/adt/adt.go b/chain/actors/adt/adt.go index 6a454ac26..084471bb8 100644 --- a/chain/actors/adt/adt.go +++ b/chain/actors/adt/adt.go @@ -2,16 +2,9 @@ package adt import ( "github.com/ipfs/go-cid" - "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/cbor" - "github.com/filecoin-project/go-state-types/network" - - "github.com/filecoin-project/lotus/chain/actors" - - adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" - adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" ) type Map interface { @@ -24,26 +17,6 @@ type Map interface { ForEach(v cbor.Unmarshaler, fn func(key string) error) error } -func AsMap(store Store, root cid.Cid, version actors.Version) (Map, error) { - switch version { - case actors.Version0: - return adt0.AsMap(store, root) - case actors.Version2: - return adt2.AsMap(store, root) - } - return nil, xerrors.Errorf("unknown network version: %d", version) -} - -func NewMap(store Store, version actors.Version) (Map, error) { - switch version { - case actors.Version0: - return adt0.MakeEmptyMap(store), nil - case actors.Version2: - return adt2.MakeEmptyMap(store), nil - } - return nil, xerrors.Errorf("unknown network version: %d", version) -} - type Array interface { Root() (cid.Cid, error) @@ -54,23 +27,3 @@ type Array interface { ForEach(v cbor.Unmarshaler, fn func(idx int64) error) error } - -func AsArray(store Store, root cid.Cid, version network.Version) (Array, error) { - switch actors.VersionForNetwork(version) { - case actors.Version0: - return adt0.AsArray(store, root) - case actors.Version2: - return adt2.AsArray(store, root) - } - return nil, xerrors.Errorf("unknown network version: %d", version) -} - -func NewArray(store Store, version actors.Version) (Array, error) { - switch version { - case actors.Version0: - return adt0.MakeEmptyArray(store), nil - case actors.Version2: - return adt2.MakeEmptyArray(store), nil - } - return nil, xerrors.Errorf("unknown network version: %d", version) -} diff --git a/chain/actors/builtin/account/account.go b/chain/actors/builtin/account/account.go index 38ed2654b..53a03e6f3 100644 --- a/chain/actors/builtin/account/account.go +++ b/chain/actors/builtin/account/account.go @@ -13,6 +13,7 @@ import ( builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" ) func init() { @@ -22,9 +23,12 @@ func init() { builtin.RegisterActorState(builtin2.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load2(store, root) }) + builtin.RegisterActorState(builtin3.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load3(store, root) + }) } -var Methods = builtin2.MethodsAccount +var Methods = builtin3.MethodsAccount func Load(store adt.Store, act *types.Actor) (State, error) { switch act.Code { @@ -32,6 +36,8 @@ func Load(store adt.Store, act *types.Actor) (State, error) { return load0(store, act.Head) case builtin2.AccountActorCodeID: return load2(store, act.Head) + case builtin3.AccountActorCodeID: + return load3(store, act.Head) } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/builtin/account/v3.go b/chain/actors/builtin/account/v3.go new file mode 100644 index 000000000..16b489a3e --- /dev/null +++ b/chain/actors/builtin/account/v3.go @@ -0,0 +1,30 @@ +package account + +import ( + "github.com/filecoin-project/go-address" + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/lotus/chain/actors/adt" + + account3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/account" +) + +var _ State = (*state3)(nil) + +func load3(store adt.Store, root cid.Cid) (State, error) { + out := state3{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state3 struct { + account3.State + store adt.Store +} + +func (s *state3) PubkeyAddress() (address.Address, error) { + return s.Address, nil +} diff --git a/chain/actors/builtin/builtin.go b/chain/actors/builtin/builtin.go index afba8efe8..1e535dca4 100644 --- a/chain/actors/builtin/builtin.go +++ b/chain/actors/builtin/builtin.go @@ -2,12 +2,12 @@ package builtin import ( "github.com/filecoin-project/go-address" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" - smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing" "github.com/ipfs/go-cid" "golang.org/x/xerrors" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/cbor" @@ -15,9 +15,12 @@ import ( "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" + smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing" + smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing" + smoothing3 "github.com/filecoin-project/specs-actors/v3/actors/util/smoothing" + miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof" - smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing" ) var SystemActorAddr = builtin0.SystemActorAddr @@ -38,11 +41,12 @@ const ( ) const ( - MethodSend = builtin2.MethodSend - MethodConstructor = builtin2.MethodConstructor + MethodSend = builtin3.MethodSend + MethodConstructor = builtin3.MethodConstructor ) -// TODO: Why does actors have 2 different versions of this? +// These are all just type aliases across actor versions 0, 2, & 3. In the future, that might change +// and we might need to do something fancier. type SectorInfo = proof0.SectorInfo type PoStProof = proof0.PoStProof type FilterEstimate = smoothing0.FilterEstimate @@ -51,13 +55,17 @@ func FromV0FilterEstimate(v0 smoothing0.FilterEstimate) FilterEstimate { return (FilterEstimate)(v0) } -// Doesn't change between actors v0 and v1 +// Doesn't change between actors v0, v2, and v3. func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower { return miner0.QAPowerForWeight(size, duration, dealWeight, verifiedWeight) } -func FromV2FilterEstimate(v1 smoothing2.FilterEstimate) FilterEstimate { - return (FilterEstimate)(v1) +func FromV2FilterEstimate(v2 smoothing2.FilterEstimate) FilterEstimate { + return (FilterEstimate)(v2) +} + +func FromV3FilterEstimate(v3 smoothing3.FilterEstimate) FilterEstimate { + return (FilterEstimate)(v3) } type ActorStateLoader func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) @@ -82,30 +90,42 @@ func ActorNameByCode(c cid.Cid) string { return builtin0.ActorNameByCode(c) case builtin2.IsBuiltinActor(c): return builtin2.ActorNameByCode(c) + case builtin3.IsBuiltinActor(c): + return builtin3.ActorNameByCode(c) default: return "" } } func IsBuiltinActor(c cid.Cid) bool { - return builtin0.IsBuiltinActor(c) || builtin2.IsBuiltinActor(c) + return builtin0.IsBuiltinActor(c) || + builtin2.IsBuiltinActor(c) || + builtin3.IsBuiltinActor(c) } func IsAccountActor(c cid.Cid) bool { - return c == builtin0.AccountActorCodeID || c == builtin2.AccountActorCodeID + return c == builtin0.AccountActorCodeID || + c == builtin2.AccountActorCodeID || + c == builtin3.AccountActorCodeID } func IsStorageMinerActor(c cid.Cid) bool { - return c == builtin0.StorageMinerActorCodeID || c == builtin2.StorageMinerActorCodeID + return c == builtin0.StorageMinerActorCodeID || + c == builtin2.StorageMinerActorCodeID || + c == builtin3.StorageMinerActorCodeID } func IsMultisigActor(c cid.Cid) bool { - return c == builtin0.MultisigActorCodeID || c == builtin2.MultisigActorCodeID + return c == builtin0.MultisigActorCodeID || + c == builtin2.MultisigActorCodeID || + c == builtin3.MultisigActorCodeID } func IsPaymentChannelActor(c cid.Cid) bool { - return c == builtin0.PaymentChannelActorCodeID || c == builtin2.PaymentChannelActorCodeID + return c == builtin0.PaymentChannelActorCodeID || + c == builtin2.PaymentChannelActorCodeID || + c == builtin3.PaymentChannelActorCodeID } func makeAddress(addr string) address.Address { diff --git a/chain/actors/builtin/cron/cron.go b/chain/actors/builtin/cron/cron.go index 65bfd992f..284aad82e 100644 --- a/chain/actors/builtin/cron/cron.go +++ b/chain/actors/builtin/cron/cron.go @@ -1,10 +1,10 @@ package cron import ( - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" ) var ( - Address = builtin2.CronActorAddr - Methods = builtin2.MethodsCron + Address = builtin3.CronActorAddr + Methods = builtin3.MethodsCron ) diff --git a/chain/actors/builtin/init/init.go b/chain/actors/builtin/init/init.go index 466af6a6c..f9e912768 100644 --- a/chain/actors/builtin/init/init.go +++ b/chain/actors/builtin/init/init.go @@ -15,6 +15,7 @@ import ( builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" ) func init() { @@ -24,11 +25,14 @@ func init() { builtin.RegisterActorState(builtin2.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load2(store, root) }) + builtin.RegisterActorState(builtin3.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load3(store, root) + }) } var ( - Address = builtin2.InitActorAddr - Methods = builtin2.MethodsInit + Address = builtin3.InitActorAddr + Methods = builtin3.MethodsInit ) func Load(store adt.Store, act *types.Actor) (State, error) { @@ -37,6 +41,8 @@ func Load(store adt.Store, act *types.Actor) (State, error) { return load0(store, act.Head) case builtin2.InitActorCodeID: return load2(store, act.Head) + case builtin3.InitActorCodeID: + return load3(store, act.Head) } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/builtin/init/v3.go b/chain/actors/builtin/init/v3.go new file mode 100644 index 000000000..e586b3b11 --- /dev/null +++ b/chain/actors/builtin/init/v3.go @@ -0,0 +1,86 @@ +package init + +import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + "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" + + init3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/init" + adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" +) + +var _ State = (*state3)(nil) + +func load3(store adt.Store, root cid.Cid) (State, error) { + out := state3{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state3 struct { + init3.State + store adt.Store +} + +func (s *state3) ResolveAddress(address address.Address) (address.Address, bool, error) { + return s.State.ResolveAddress(s.store, address) +} + +func (s *state3) MapAddressToNewID(address address.Address) (address.Address, error) { + return s.State.MapAddressToNewID(s.store, address) +} + +func (s *state3) ForEachActor(cb func(id abi.ActorID, address address.Address) error) error { + addrs, err := adt3.AsMap(s.store, s.State.AddressMap, builtin3.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 *state3) NetworkName() (dtypes.NetworkName, error) { + return dtypes.NetworkName(s.State.NetworkName), nil +} + +func (s *state3) SetNetworkName(name string) error { + s.State.NetworkName = name + return nil +} + +func (s *state3) Remove(addrs ...address.Address) (err error) { + m, err := adt3.AsMap(s.store, s.State.AddressMap, builtin3.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 *state3) addressMap() (adt.Map, error) { + return adt3.AsMap(s.store, s.AddressMap, builtin3.DefaultHamtBitwidth) +} diff --git a/chain/actors/builtin/market/market.go b/chain/actors/builtin/market/market.go index 8bb31f2b4..628b27e08 100644 --- a/chain/actors/builtin/market/market.go +++ b/chain/actors/builtin/market/market.go @@ -12,6 +12,7 @@ import ( builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -25,11 +26,14 @@ func init() { builtin.RegisterActorState(builtin2.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load2(store, root) }) + builtin.RegisterActorState(builtin3.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load3(store, root) + }) } var ( - Address = builtin2.StorageMarketActorAddr - Methods = builtin2.MethodsMarket + Address = builtin3.StorageMarketActorAddr + Methods = builtin3.MethodsMarket ) func Load(store adt.Store, act *types.Actor) (st State, err error) { @@ -38,6 +42,8 @@ func Load(store adt.Store, act *types.Actor) (st State, err error) { return load0(store, act.Head) case builtin2.StorageMarketActorCodeID: return load2(store, act.Head) + case builtin3.StorageMarketActorCodeID: + return load3(store, act.Head) } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/builtin/market/v3.go b/chain/actors/builtin/market/v3.go new file mode 100644 index 000000000..3309d37a7 --- /dev/null +++ b/chain/actors/builtin/market/v3.go @@ -0,0 +1,205 @@ +package market + +import ( + "bytes" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/types" + + market3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/market" + adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" +) + +var _ State = (*state3)(nil) + +func load3(store adt.Store, root cid.Cid) (State, error) { + out := state3{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state3 struct { + market3.State + store adt.Store +} + +func (s *state3) TotalLocked() (abi.TokenAmount, error) { + fml := types.BigAdd(s.TotalClientLockedCollateral, s.TotalProviderLockedCollateral) + fml = types.BigAdd(fml, s.TotalClientStorageFee) + return fml, nil +} + +func (s *state3) BalancesChanged(otherState State) (bool, error) { + otherState2, ok := otherState.(*state3) + 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(otherState2.State.EscrowTable) || !s.State.LockedTable.Equals(otherState2.State.LockedTable), nil +} + +func (s *state3) StatesChanged(otherState State) (bool, error) { + otherState2, ok := otherState.(*state3) + 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(otherState2.State.States), nil +} + +func (s *state3) States() (DealStates, error) { + stateArray, err := adt3.AsArray(s.store, s.State.States, market3.StatesAmtBitwidth) + if err != nil { + return nil, err + } + return &dealStates3{stateArray}, nil +} + +func (s *state3) ProposalsChanged(otherState State) (bool, error) { + otherState2, ok := otherState.(*state3) + 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(otherState2.State.Proposals), nil +} + +func (s *state3) Proposals() (DealProposals, error) { + proposalArray, err := adt3.AsArray(s.store, s.State.Proposals, market3.ProposalsAmtBitwidth) + if err != nil { + return nil, err + } + return &dealProposals3{proposalArray}, nil +} + +func (s *state3) EscrowTable() (BalanceTable, error) { + bt, err := adt3.AsBalanceTable(s.store, s.State.EscrowTable) + if err != nil { + return nil, err + } + return &balanceTable3{bt}, nil +} + +func (s *state3) LockedTable() (BalanceTable, error) { + bt, err := adt3.AsBalanceTable(s.store, s.State.LockedTable) + if err != nil { + return nil, err + } + return &balanceTable3{bt}, nil +} + +func (s *state3) VerifyDealsForActivation( + minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch, +) (weight, verifiedWeight abi.DealWeight, err error) { + w, vw, _, err := market3.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch) + return w, vw, err +} + +type balanceTable3 struct { + *adt3.BalanceTable +} + +func (bt *balanceTable3) ForEach(cb func(address.Address, abi.TokenAmount) error) error { + asMap := (*adt3.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 dealStates3 struct { + adt.Array +} + +func (s *dealStates3) Get(dealID abi.DealID) (*DealState, bool, error) { + var deal2 market3.DealState + found, err := s.Array.Get(uint64(dealID), &deal2) + if err != nil { + return nil, false, err + } + if !found { + return nil, false, nil + } + deal := fromV3DealState(deal2) + return &deal, true, nil +} + +func (s *dealStates3) ForEach(cb func(dealID abi.DealID, ds DealState) error) error { + var ds1 market3.DealState + return s.Array.ForEach(&ds1, func(idx int64) error { + return cb(abi.DealID(idx), fromV3DealState(ds1)) + }) +} + +func (s *dealStates3) decode(val *cbg.Deferred) (*DealState, error) { + var ds1 market3.DealState + if err := ds1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return nil, err + } + ds := fromV3DealState(ds1) + return &ds, nil +} + +func (s *dealStates3) array() adt.Array { + return s.Array +} + +func fromV3DealState(v1 market3.DealState) DealState { + return (DealState)(v1) +} + +type dealProposals3 struct { + adt.Array +} + +func (s *dealProposals3) Get(dealID abi.DealID) (*DealProposal, bool, error) { + var proposal2 market3.DealProposal + found, err := s.Array.Get(uint64(dealID), &proposal2) + if err != nil { + return nil, false, err + } + if !found { + return nil, false, nil + } + proposal := fromV3DealProposal(proposal2) + return &proposal, true, nil +} + +func (s *dealProposals3) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error { + var dp1 market3.DealProposal + return s.Array.ForEach(&dp1, func(idx int64) error { + return cb(abi.DealID(idx), fromV3DealProposal(dp1)) + }) +} + +func (s *dealProposals3) decode(val *cbg.Deferred) (*DealProposal, error) { + var dp1 market3.DealProposal + if err := dp1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return nil, err + } + dp := fromV3DealProposal(dp1) + return &dp, nil +} + +func (s *dealProposals3) array() adt.Array { + return s.Array +} + +func fromV3DealProposal(v1 market3.DealProposal) DealProposal { + return (DealProposal)(v1) +} diff --git a/chain/actors/builtin/miner/miner.go b/chain/actors/builtin/miner/miner.go index 066dc9bfd..38a5085db 100644 --- a/chain/actors/builtin/miner/miner.go +++ b/chain/actors/builtin/miner/miner.go @@ -2,6 +2,7 @@ package miner import ( "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/go-state-types/network" "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p-core/peer" cbg "github.com/whyrusleeping/cbor-gen" @@ -21,6 +22,8 @@ import ( miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner" ) func init() { @@ -30,11 +33,14 @@ func init() { builtin.RegisterActorState(builtin2.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load2(store, root) }) + builtin.RegisterActorState(builtin3.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load3(store, root) + }) } -var Methods = builtin2.MethodsMiner +var Methods = builtin3.MethodsMiner -// Unchanged between v0 and v2 actors +// Unchanged between v0, v2, and v3 actors var WPoStProvingPeriod = miner0.WPoStProvingPeriod var WPoStPeriodDeadlines = miner0.WPoStPeriodDeadlines var WPoStChallengeWindow = miner0.WPoStChallengeWindow @@ -53,6 +59,8 @@ func Load(store adt.Store, act *types.Actor) (st State, err error) { return load0(store, act.Head) case builtin2.StorageMinerActorCodeID: return load2(store, act.Head) + case builtin3.StorageMinerActorCodeID: + return load3(store, act.Head) } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } @@ -96,7 +104,7 @@ type State interface { type Deadline interface { LoadPartition(idx uint64) (Partition, error) ForEachPartition(cb func(idx uint64, part Partition) error) error - PostSubmissions() (bitfield.BitField, error) + PartitionsPoSted() (bitfield.BitField, error) PartitionsChanged(Deadline) (bool, error) } @@ -142,6 +150,60 @@ type DeclareFaultsParams = miner0.DeclareFaultsParams type DeclareFaultsRecoveredParams = miner0.DeclareFaultsRecoveredParams type SubmitWindowedPoStParams = miner0.SubmitWindowedPoStParams type ProveCommitSectorParams = miner0.ProveCommitSectorParams +type DisputeWindowedPoStParams = miner3.DisputeWindowedPoStParams + +func PreferredSealProofTypeFromWindowPoStType(nver network.Version, proof abi.RegisteredPoStProof) (abi.RegisteredSealProof, error) { + // We added support for the new proofs in network version 7, and removed support for the old + // ones in network version 8. + if nver < network.Version7 { + switch proof { + case abi.RegisteredPoStProof_StackedDrgWindow2KiBV1: + return abi.RegisteredSealProof_StackedDrg2KiBV1, nil + case abi.RegisteredPoStProof_StackedDrgWindow8MiBV1: + return abi.RegisteredSealProof_StackedDrg8MiBV1, nil + case abi.RegisteredPoStProof_StackedDrgWindow512MiBV1: + return abi.RegisteredSealProof_StackedDrg512MiBV1, nil + case abi.RegisteredPoStProof_StackedDrgWindow32GiBV1: + return abi.RegisteredSealProof_StackedDrg32GiBV1, nil + case abi.RegisteredPoStProof_StackedDrgWindow64GiBV1: + return abi.RegisteredSealProof_StackedDrg64GiBV1, nil + default: + return -1, xerrors.Errorf("unrecognized window post type: %d", proof) + } + } + + switch proof { + case abi.RegisteredPoStProof_StackedDrgWindow2KiBV1: + return abi.RegisteredSealProof_StackedDrg2KiBV1_1, nil + case abi.RegisteredPoStProof_StackedDrgWindow8MiBV1: + return abi.RegisteredSealProof_StackedDrg8MiBV1_1, nil + case abi.RegisteredPoStProof_StackedDrgWindow512MiBV1: + return abi.RegisteredSealProof_StackedDrg512MiBV1_1, nil + case abi.RegisteredPoStProof_StackedDrgWindow32GiBV1: + return abi.RegisteredSealProof_StackedDrg32GiBV1_1, nil + case abi.RegisteredPoStProof_StackedDrgWindow64GiBV1: + return abi.RegisteredSealProof_StackedDrg64GiBV1_1, nil + default: + return -1, xerrors.Errorf("unrecognized window post type: %d", proof) + } +} + +func WinningPoStProofTypeFromWindowPoStProofType(nver network.Version, proof abi.RegisteredPoStProof) (abi.RegisteredPoStProof, error) { + switch proof { + case abi.RegisteredPoStProof_StackedDrgWindow2KiBV1: + return abi.RegisteredPoStProof_StackedDrgWinning2KiBV1, nil + case abi.RegisteredPoStProof_StackedDrgWindow8MiBV1: + return abi.RegisteredPoStProof_StackedDrgWinning8MiBV1, nil + case abi.RegisteredPoStProof_StackedDrgWindow512MiBV1: + return abi.RegisteredPoStProof_StackedDrgWinning512MiBV1, nil + case abi.RegisteredPoStProof_StackedDrgWindow32GiBV1: + return abi.RegisteredPoStProof_StackedDrgWinning32GiBV1, nil + case abi.RegisteredPoStProof_StackedDrgWindow64GiBV1: + return abi.RegisteredPoStProof_StackedDrgWinning64GiBV1, nil + default: + return -1, xerrors.Errorf("unknown proof type %d", proof) + } +} type MinerInfo struct { Owner address.Address // Must be an ID-address. @@ -151,7 +213,7 @@ type MinerInfo struct { WorkerChangeEpoch abi.ChainEpoch PeerId *peer.ID Multiaddrs []abi.Multiaddrs - SealProofType abi.RegisteredSealProof + WindowPoStProofType abi.RegisteredPoStProof SectorSize abi.SectorSize WindowPoStPartitionSectors uint64 ConsensusFaultElapsed abi.ChainEpoch diff --git a/chain/actors/builtin/miner/v0.go b/chain/actors/builtin/miner/v0.go index 69160e4e0..2795d6d70 100644 --- a/chain/actors/builtin/miner/v0.go +++ b/chain/actors/builtin/miner/v0.go @@ -297,6 +297,11 @@ func (s *state0) Info() (MinerInfo, error) { pid = &peerID } + wpp, err := info.SealProofType.RegisteredWindowPoStProof() + if err != nil { + return MinerInfo{}, err + } + mi := MinerInfo{ Owner: info.Owner, Worker: info.Worker, @@ -307,7 +312,7 @@ func (s *state0) Info() (MinerInfo, error) { PeerId: pid, Multiaddrs: info.Multiaddrs, - SealProofType: info.SealProofType, + WindowPoStProofType: wpp, SectorSize: info.SectorSize, WindowPoStPartitionSectors: info.WindowPoStPartitionSectors, ConsensusFaultElapsed: -1, @@ -382,7 +387,7 @@ func (d *deadline0) PartitionsChanged(other Deadline) (bool, error) { return !d.Deadline.Partitions.Equals(other0.Deadline.Partitions), nil } -func (d *deadline0) PostSubmissions() (bitfield.BitField, error) { +func (d *deadline0) PartitionsPoSted() (bitfield.BitField, error) { return d.Deadline.PostSubmissions, nil } diff --git a/chain/actors/builtin/miner/v2.go b/chain/actors/builtin/miner/v2.go index 2c67484ea..854aa6ab7 100644 --- a/chain/actors/builtin/miner/v2.go +++ b/chain/actors/builtin/miner/v2.go @@ -296,6 +296,11 @@ func (s *state2) Info() (MinerInfo, error) { pid = &peerID } + wpp, err := info.SealProofType.RegisteredWindowPoStProof() + if err != nil { + return MinerInfo{}, err + } + mi := MinerInfo{ Owner: info.Owner, Worker: info.Worker, @@ -306,7 +311,7 @@ func (s *state2) Info() (MinerInfo, error) { PeerId: pid, Multiaddrs: info.Multiaddrs, - SealProofType: info.SealProofType, + WindowPoStProofType: wpp, SectorSize: info.SectorSize, WindowPoStPartitionSectors: info.WindowPoStPartitionSectors, ConsensusFaultElapsed: info.ConsensusFaultElapsed, @@ -381,7 +386,7 @@ func (d *deadline2) PartitionsChanged(other Deadline) (bool, error) { return !d.Deadline.Partitions.Equals(other2.Deadline.Partitions), nil } -func (d *deadline2) PostSubmissions() (bitfield.BitField, error) { +func (d *deadline2) PartitionsPoSted() (bitfield.BitField, error) { return d.Deadline.PostSubmissions, nil } diff --git a/chain/actors/builtin/miner/v3.go b/chain/actors/builtin/miner/v3.go new file mode 100644 index 000000000..2d2ecacf4 --- /dev/null +++ b/chain/actors/builtin/miner/v3.go @@ -0,0 +1,425 @@ +package miner + +import ( + "bytes" + "errors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-bitfield" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/dline" + "github.com/ipfs/go-cid" + "github.com/libp2p/go-libp2p-core/peer" + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/chain/actors/adt" + + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner" + adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" +) + +var _ State = (*state3)(nil) + +func load3(store adt.Store, root cid.Cid) (State, error) { + out := state3{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state3 struct { + miner3.State + store adt.Store +} + +type deadline3 struct { + miner3.Deadline + store adt.Store +} + +type partition3 struct { + miner3.Partition + store adt.Store +} + +func (s *state3) 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 *state3) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) { + return s.CheckVestedFunds(s.store, epoch) +} + +func (s *state3) LockedFunds() (LockedFunds, error) { + return LockedFunds{ + VestingFunds: s.State.LockedFunds, + InitialPledgeRequirement: s.State.InitialPledge, + PreCommitDeposits: s.State.PreCommitDeposits, + }, nil +} + +func (s *state3) FeeDebt() (abi.TokenAmount, error) { + return s.State.FeeDebt, nil +} + +func (s *state3) InitialPledge() (abi.TokenAmount, error) { + return s.State.InitialPledge, nil +} + +func (s *state3) PreCommitDeposits() (abi.TokenAmount, error) { + return s.State.PreCommitDeposits, nil +} + +func (s *state3) GetSector(num abi.SectorNumber) (*SectorOnChainInfo, error) { + info, ok, err := s.State.GetSector(s.store, num) + if !ok || err != nil { + return nil, err + } + + ret := fromV3SectorOnChainInfo(*info) + return &ret, nil +} + +func (s *state3) 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 *state3) 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 *miner3.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 *state3) 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 *miner3.Deadline) error { + partitions, err := dl.PartitionsArray(s.store) + if err != nil { + return err + } + quant := s.State.QuantSpecForDeadline(dlIdx) + var part miner3.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 := miner3.LoadExpirationQueue(s.store, part.ExpirationsEpochs, quant, miner3.PartitionExpirationAmtBitwidth) + if err != nil { + return err + } + var exp miner3.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 *state3) GetPrecommittedSector(num abi.SectorNumber) (*SectorPreCommitOnChainInfo, error) { + info, ok, err := s.State.GetPrecommittedSector(s.store, num) + if !ok || err != nil { + return nil, err + } + + ret := fromV3SectorPreCommitOnChainInfo(*info) + + return &ret, nil +} + +func (s *state3) LoadSectors(snos *bitfield.BitField) ([]*SectorOnChainInfo, error) { + sectors, err := miner3.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 info2 miner3.SectorOnChainInfo + if err := sectors.ForEach(&info2, func(_ int64) error { + info := fromV3SectorOnChainInfo(info2) + infos = append(infos, &info) + return nil + }); err != nil { + return nil, err + } + return infos, nil + } + + // Otherwise, load selected. + infos2, err := sectors.Load(*snos) + if err != nil { + return nil, err + } + infos := make([]*SectorOnChainInfo, len(infos2)) + for i, info2 := range infos2 { + info := fromV3SectorOnChainInfo(*info2) + infos[i] = &info + } + return infos, nil +} + +func (s *state3) IsAllocated(num abi.SectorNumber) (bool, error) { + var allocatedSectors bitfield.BitField + if err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors); err != nil { + return false, err + } + + return allocatedSectors.IsSet(uint64(num)) +} + +func (s *state3) 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 &deadline3{*dl, s.store}, nil +} + +func (s *state3) 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 *miner3.Deadline) error { + return cb(i, &deadline3{*dl, s.store}) + }) +} + +func (s *state3) NumDeadlines() (uint64, error) { + return miner3.WPoStPeriodDeadlines, nil +} + +func (s *state3) DeadlinesChanged(other State) (bool, error) { + other2, ok := other.(*state3) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + + return !s.State.Deadlines.Equals(other2.Deadlines), nil +} + +func (s *state3) MinerInfoChanged(other State) (bool, error) { + other0, ok := other.(*state3) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + return !s.State.Info.Equals(other0.State.Info), nil +} + +func (s *state3) 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 *state3) DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error) { + return s.State.DeadlineInfo(epoch), nil +} + +func (s *state3) sectors() (adt.Array, error) { + return adt3.AsArray(s.store, s.Sectors, miner3.SectorsAmtBitwidth) +} + +func (s *state3) decodeSectorOnChainInfo(val *cbg.Deferred) (SectorOnChainInfo, error) { + var si miner3.SectorOnChainInfo + err := si.UnmarshalCBOR(bytes.NewReader(val.Raw)) + if err != nil { + return SectorOnChainInfo{}, err + } + + return fromV3SectorOnChainInfo(si), nil +} + +func (s *state3) precommits() (adt.Map, error) { + return adt3.AsMap(s.store, s.PreCommittedSectors, builtin3.DefaultHamtBitwidth) +} + +func (s *state3) decodeSectorPreCommitOnChainInfo(val *cbg.Deferred) (SectorPreCommitOnChainInfo, error) { + var sp miner3.SectorPreCommitOnChainInfo + err := sp.UnmarshalCBOR(bytes.NewReader(val.Raw)) + if err != nil { + return SectorPreCommitOnChainInfo{}, err + } + + return fromV3SectorPreCommitOnChainInfo(sp), nil +} + +func (d *deadline3) LoadPartition(idx uint64) (Partition, error) { + p, err := d.Deadline.LoadPartition(d.store, idx) + if err != nil { + return nil, err + } + return &partition3{*p, d.store}, nil +} + +func (d *deadline3) ForEachPartition(cb func(uint64, Partition) error) error { + ps, err := d.Deadline.PartitionsArray(d.store) + if err != nil { + return err + } + var part miner3.Partition + return ps.ForEach(&part, func(i int64) error { + return cb(uint64(i), &partition3{part, d.store}) + }) +} + +func (d *deadline3) PartitionsChanged(other Deadline) (bool, error) { + other2, ok := other.(*deadline3) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + + return !d.Deadline.Partitions.Equals(other2.Deadline.Partitions), nil +} + +func (d *deadline3) PartitionsPoSted() (bitfield.BitField, error) { + return d.Deadline.PartitionsPoSted, nil +} + +func (p *partition3) AllSectors() (bitfield.BitField, error) { + return p.Partition.Sectors, nil +} + +func (p *partition3) FaultySectors() (bitfield.BitField, error) { + return p.Partition.Faults, nil +} + +func (p *partition3) RecoveringSectors() (bitfield.BitField, error) { + return p.Partition.Recoveries, nil +} + +func fromV3SectorOnChainInfo(v3 miner3.SectorOnChainInfo) SectorOnChainInfo { + return SectorOnChainInfo{ + SectorNumber: v3.SectorNumber, + SealProof: v3.SealProof, + SealedCID: v3.SealedCID, + DealIDs: v3.DealIDs, + Activation: v3.Activation, + Expiration: v3.Expiration, + DealWeight: v3.DealWeight, + VerifiedDealWeight: v3.VerifiedDealWeight, + InitialPledge: v3.InitialPledge, + ExpectedDayReward: v3.ExpectedDayReward, + ExpectedStoragePledge: v3.ExpectedStoragePledge, + } +} + +func fromV3SectorPreCommitOnChainInfo(v3 miner3.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { + return SectorPreCommitOnChainInfo{ + Info: (SectorPreCommitInfo)(v3.Info), + PreCommitDeposit: v3.PreCommitDeposit, + PreCommitEpoch: v3.PreCommitEpoch, + DealWeight: v3.DealWeight, + VerifiedDealWeight: v3.VerifiedDealWeight, + } +} diff --git a/chain/actors/builtin/multisig/message.go b/chain/actors/builtin/multisig/message.go index 3d2c66e6b..a43b919aa 100644 --- a/chain/actors/builtin/multisig/message.go +++ b/chain/actors/builtin/multisig/message.go @@ -9,14 +9,14 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" - multisig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + multisig3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/multisig" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" ) -var Methods = builtin2.MethodsMultisig +var Methods = builtin3.MethodsMultisig func Message(version actors.Version, from address.Address) MessageBuilder { switch version { @@ -24,6 +24,8 @@ func Message(version actors.Version, from address.Address) MessageBuilder { return message0{from} case actors.Version2: return message2{message0{from}} + case actors.Version3: + return message3{message0{from}} default: panic(fmt.Sprintf("unsupported actors version: %d", version)) } @@ -47,11 +49,11 @@ type MessageBuilder interface { } // this type is the same between v0 and v2 -type ProposalHashData = multisig2.ProposalHashData -type ProposeReturn = multisig2.ProposeReturn +type ProposalHashData = multisig3.ProposalHashData +type ProposeReturn = multisig3.ProposeReturn func txnParams(id uint64, data *ProposalHashData) ([]byte, error) { - params := multisig2.TxnIDParams{ID: multisig2.TxnID(id)} + params := multisig3.TxnIDParams{ID: multisig3.TxnID(id)} if data != nil { if data.Requester.Protocol() != address.ID { return nil, xerrors.Errorf("proposer address must be an ID address, was %s", data.Requester) diff --git a/chain/actors/builtin/multisig/message3.go b/chain/actors/builtin/multisig/message3.go new file mode 100644 index 000000000..f5f6d8cdf --- /dev/null +++ b/chain/actors/builtin/multisig/message3.go @@ -0,0 +1,71 @@ +package multisig + +import ( + "golang.org/x/xerrors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + init3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/init" + multisig3 "github.com/filecoin-project/specs-actors/v3/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 message3 struct{ message0 } + +func (m message3) 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 := &multisig3.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 := &init3.ExecParams{ + CodeCID: builtin3.MultisigActorCodeID, + ConstructorParams: enc, + } + + enc, actErr = actors.SerializeParams(execParams) + if actErr != nil { + return nil, actErr + } + + return &types.Message{ + To: init_.Address, + From: m.from, + Method: builtin3.MethodsInit.Exec, + Params: enc, + Value: initialAmount, + }, nil +} diff --git a/chain/actors/builtin/multisig/state.go b/chain/actors/builtin/multisig/state.go index fea42ba5f..5f9fb6a52 100644 --- a/chain/actors/builtin/multisig/state.go +++ b/chain/actors/builtin/multisig/state.go @@ -12,6 +12,7 @@ import ( builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -25,6 +26,9 @@ func init() { builtin.RegisterActorState(builtin2.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load2(store, root) }) + builtin.RegisterActorState(builtin3.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load3(store, root) + }) } func Load(store adt.Store, act *types.Actor) (State, error) { @@ -33,6 +37,8 @@ func Load(store adt.Store, act *types.Actor) (State, error) { return load0(store, act.Head) case builtin2.MultisigActorCodeID: return load2(store, act.Head) + case builtin3.MultisigActorCodeID: + return load3(store, act.Head) } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/builtin/multisig/state0.go b/chain/actors/builtin/multisig/state0.go index e6f9a9c36..5548b0a5c 100644 --- a/chain/actors/builtin/multisig/state0.go +++ b/chain/actors/builtin/multisig/state0.go @@ -13,8 +13,8 @@ import ( "github.com/filecoin-project/lotus/chain/actors/adt" msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" + multisig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" - multisig0 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" ) var _ State = (*state0)(nil) diff --git a/chain/actors/builtin/multisig/state3.go b/chain/actors/builtin/multisig/state3.go new file mode 100644 index 000000000..7ade2ab64 --- /dev/null +++ b/chain/actors/builtin/multisig/state3.go @@ -0,0 +1,95 @@ +package multisig + +import ( + "bytes" + "encoding/binary" + + adt3 "github.com/filecoin-project/specs-actors/v3/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" + + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + msig3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/multisig" +) + +var _ State = (*state3)(nil) + +func load3(store adt.Store, root cid.Cid) (State, error) { + out := state3{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state3 struct { + msig3.State + store adt.Store +} + +func (s *state3) LockedBalance(currEpoch abi.ChainEpoch) (abi.TokenAmount, error) { + return s.State.AmountLocked(currEpoch - s.State.StartEpoch), nil +} + +func (s *state3) StartEpoch() (abi.ChainEpoch, error) { + return s.State.StartEpoch, nil +} + +func (s *state3) UnlockDuration() (abi.ChainEpoch, error) { + return s.State.UnlockDuration, nil +} + +func (s *state3) InitialBalance() (abi.TokenAmount, error) { + return s.State.InitialBalance, nil +} + +func (s *state3) Threshold() (uint64, error) { + return s.State.NumApprovalsThreshold, nil +} + +func (s *state3) Signers() ([]address.Address, error) { + return s.State.Signers, nil +} + +func (s *state3) ForEachPendingTxn(cb func(id int64, txn Transaction) error) error { + arr, err := adt3.AsMap(s.store, s.State.PendingTxns, builtin3.DefaultHamtBitwidth) + if err != nil { + return err + } + var out msig3.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)) + }) +} + +func (s *state3) PendingTxnChanged(other State) (bool, error) { + other2, ok := other.(*state3) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + return !s.State.PendingTxns.Equals(other2.PendingTxns), nil +} + +func (s *state3) transactions() (adt.Map, error) { + return adt3.AsMap(s.store, s.PendingTxns, builtin3.DefaultHamtBitwidth) +} + +func (s *state3) decodeTransaction(val *cbg.Deferred) (Transaction, error) { + var tx msig3.Transaction + if err := tx.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return Transaction{}, err + } + return tx, nil +} diff --git a/chain/actors/builtin/paych/message.go b/chain/actors/builtin/paych/message.go index 5709d4b23..39c091d45 100644 --- a/chain/actors/builtin/paych/message.go +++ b/chain/actors/builtin/paych/message.go @@ -8,10 +8,10 @@ import ( "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" ) -var Methods = builtin2.MethodsPaych +var Methods = builtin3.MethodsPaych func Message(version actors.Version, from address.Address) MessageBuilder { switch version { @@ -19,6 +19,8 @@ func Message(version actors.Version, from address.Address) MessageBuilder { return message0{from} case actors.Version2: return message2{from} + case actors.Version3: + return message3{from} default: panic(fmt.Sprintf("unsupported actors version: %d", version)) } diff --git a/chain/actors/builtin/paych/message3.go b/chain/actors/builtin/paych/message3.go new file mode 100644 index 000000000..50503a140 --- /dev/null +++ b/chain/actors/builtin/paych/message3.go @@ -0,0 +1,74 @@ +package paych + +import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + init3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/init" + paych3 "github.com/filecoin-project/specs-actors/v3/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 message3 struct{ from address.Address } + +func (m message3) Create(to address.Address, initialAmount abi.TokenAmount) (*types.Message, error) { + params, aerr := actors.SerializeParams(&paych3.ConstructorParams{From: m.from, To: to}) + if aerr != nil { + return nil, aerr + } + enc, aerr := actors.SerializeParams(&init3.ExecParams{ + CodeCID: builtin3.PaymentChannelActorCodeID, + ConstructorParams: params, + }) + if aerr != nil { + return nil, aerr + } + + return &types.Message{ + To: init_.Address, + From: m.from, + Value: initialAmount, + Method: builtin3.MethodsInit.Exec, + Params: enc, + }, nil +} + +func (m message3) Update(paych address.Address, sv *SignedVoucher, secret []byte) (*types.Message, error) { + params, aerr := actors.SerializeParams(&paych3.UpdateChannelStateParams{ + Sv: *sv, + Secret: secret, + }) + if aerr != nil { + return nil, aerr + } + + return &types.Message{ + To: paych, + From: m.from, + Value: abi.NewTokenAmount(0), + Method: builtin3.MethodsPaych.UpdateChannelState, + Params: params, + }, nil +} + +func (m message3) Settle(paych address.Address) (*types.Message, error) { + return &types.Message{ + To: paych, + From: m.from, + Value: abi.NewTokenAmount(0), + Method: builtin3.MethodsPaych.Settle, + }, nil +} + +func (m message3) Collect(paych address.Address) (*types.Message, error) { + return &types.Message{ + To: paych, + From: m.from, + Value: abi.NewTokenAmount(0), + Method: builtin3.MethodsPaych.Collect, + }, nil +} diff --git a/chain/actors/builtin/paych/state.go b/chain/actors/builtin/paych/state.go index 20c7a74b7..accb96244 100644 --- a/chain/actors/builtin/paych/state.go +++ b/chain/actors/builtin/paych/state.go @@ -15,6 +15,7 @@ import ( builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -28,6 +29,9 @@ func init() { builtin.RegisterActorState(builtin2.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load2(store, root) }) + builtin.RegisterActorState(builtin3.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load3(store, root) + }) } // Load returns an abstract copy of payment channel state, irregardless of actor version @@ -37,6 +41,8 @@ func Load(store adt.Store, act *types.Actor) (State, error) { return load0(store, act.Head) case builtin2.PaymentChannelActorCodeID: return load2(store, act.Head) + case builtin3.PaymentChannelActorCodeID: + return load3(store, act.Head) } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/builtin/paych/state3.go b/chain/actors/builtin/paych/state3.go new file mode 100644 index 000000000..14bb4cb61 --- /dev/null +++ b/chain/actors/builtin/paych/state3.go @@ -0,0 +1,104 @@ +package paych + +import ( + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" + + "github.com/filecoin-project/lotus/chain/actors/adt" + + paych3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/paych" + adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" +) + +var _ State = (*state3)(nil) + +func load3(store adt.Store, root cid.Cid) (State, error) { + out := state3{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state3 struct { + paych3.State + store adt.Store + lsAmt *adt3.Array +} + +// Channel owner, who has funded the actor +func (s *state3) From() (address.Address, error) { + return s.State.From, nil +} + +// Recipient of payouts from channel +func (s *state3) To() (address.Address, error) { + return s.State.To, nil +} + +// Height at which the channel can be `Collected` +func (s *state3) SettlingAt() (abi.ChainEpoch, error) { + return s.State.SettlingAt, nil +} + +// Amount successfully redeemed through the payment channel, paid out on `Collect()` +func (s *state3) ToSend() (abi.TokenAmount, error) { + return s.State.ToSend, nil +} + +func (s *state3) getOrLoadLsAmt() (*adt3.Array, error) { + if s.lsAmt != nil { + return s.lsAmt, nil + } + + // Get the lane state from the chain + lsamt, err := adt3.AsArray(s.store, s.State.LaneStates, paych3.LaneStatesAmtBitwidth) + if err != nil { + return nil, err + } + + s.lsAmt = lsamt + return lsamt, nil +} + +// Get total number of lanes +func (s *state3) LaneCount() (uint64, error) { + lsamt, err := s.getOrLoadLsAmt() + if err != nil { + return 0, err + } + return lsamt.Length(), nil +} + +// Iterate lane states +func (s *state3) 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 paych3.LaneState + return lsamt.ForEach(&ls, func(i int64) error { + return cb(uint64(i), &laneState3{ls}) + }) +} + +type laneState3 struct { + paych3.LaneState +} + +func (ls *laneState3) Redeemed() (big.Int, error) { + return ls.LaneState.Redeemed, nil +} + +func (ls *laneState3) Nonce() (uint64, error) { + return ls.LaneState.Nonce, nil +} diff --git a/chain/actors/builtin/power/power.go b/chain/actors/builtin/power/power.go index e0cf0d700..712fb0b98 100644 --- a/chain/actors/builtin/power/power.go +++ b/chain/actors/builtin/power/power.go @@ -16,6 +16,7 @@ import ( builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" ) func init() { @@ -25,11 +26,14 @@ func init() { builtin.RegisterActorState(builtin2.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load2(store, root) }) + builtin.RegisterActorState(builtin3.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load3(store, root) + }) } var ( - Address = builtin2.StoragePowerActorAddr - Methods = builtin2.MethodsPower + Address = builtin3.StoragePowerActorAddr + Methods = builtin3.MethodsPower ) func Load(store adt.Store, act *types.Actor) (st State, err error) { @@ -38,6 +42,8 @@ func Load(store adt.Store, act *types.Actor) (st State, err error) { return load0(store, act.Head) case builtin2.StoragePowerActorCodeID: return load2(store, act.Head) + case builtin3.StoragePowerActorCodeID: + return load3(store, act.Head) } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/builtin/power/v3.go b/chain/actors/builtin/power/v3.go new file mode 100644 index 000000000..fd161dda5 --- /dev/null +++ b/chain/actors/builtin/power/v3.go @@ -0,0 +1,149 @@ +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" + + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + power3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/power" + adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" +) + +var _ State = (*state3)(nil) + +func load3(store adt.Store, root cid.Cid) (State, error) { + out := state3{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state3 struct { + power3.State + store adt.Store +} + +func (s *state3) TotalLocked() (abi.TokenAmount, error) { + return s.TotalPledgeCollateral, nil +} + +func (s *state3) 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 *state3) TotalCommitted() (Claim, error) { + return Claim{ + RawBytePower: s.TotalBytesCommitted, + QualityAdjPower: s.TotalQABytesCommitted, + }, nil +} + +func (s *state3) MinerPower(addr address.Address) (Claim, bool, error) { + claims, err := s.claims() + if err != nil { + return Claim{}, false, err + } + var claim power3.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 *state3) MinerNominalPowerMeetsConsensusMinimum(a address.Address) (bool, error) { + return s.State.MinerNominalPowerMeetsConsensusMinimum(s.store, a) +} + +func (s *state3) TotalPowerSmoothed() (builtin.FilterEstimate, error) { + return builtin.FromV3FilterEstimate(s.State.ThisEpochQAPowerSmoothed), nil +} + +func (s *state3) MinerCounts() (uint64, uint64, error) { + return uint64(s.State.MinerAboveMinPowerCount), uint64(s.State.MinerCount), nil +} + +func (s *state3) 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 *state3) ForEachClaim(cb func(miner address.Address, claim Claim) error) error { + claims, err := s.claims() + if err != nil { + return err + } + + var claim power3.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 *state3) ClaimsChanged(other State) (bool, error) { + other2, ok := other.(*state3) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + return !s.State.Claims.Equals(other2.State.Claims), nil +} + +func (s *state3) claims() (adt.Map, error) { + return adt3.AsMap(s.store, s.Claims, builtin3.DefaultHamtBitwidth) +} + +func (s *state3) decodeClaim(val *cbg.Deferred) (Claim, error) { + var ci power3.Claim + if err := ci.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return Claim{}, err + } + return fromV3Claim(ci), nil +} + +func fromV3Claim(v3 power3.Claim) Claim { + return Claim{ + RawBytePower: v3.RawBytePower, + QualityAdjPower: v3.QualityAdjPower, + } +} diff --git a/chain/actors/builtin/reward/reward.go b/chain/actors/builtin/reward/reward.go index 952ca270b..156b3ec55 100644 --- a/chain/actors/builtin/reward/reward.go +++ b/chain/actors/builtin/reward/reward.go @@ -9,6 +9,7 @@ import ( "github.com/filecoin-project/go-state-types/cbor" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -22,11 +23,14 @@ func init() { builtin.RegisterActorState(builtin2.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load2(store, root) }) + builtin.RegisterActorState(builtin3.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load3(store, root) + }) } var ( - Address = builtin2.RewardActorAddr - Methods = builtin2.MethodsReward + Address = builtin3.RewardActorAddr + Methods = builtin3.MethodsReward ) func Load(store adt.Store, act *types.Actor) (st State, err error) { @@ -35,6 +39,8 @@ func Load(store adt.Store, act *types.Actor) (st State, err error) { return load0(store, act.Head) case builtin2.RewardActorCodeID: return load2(store, act.Head) + case builtin3.RewardActorCodeID: + return load3(store, act.Head) } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/builtin/reward/v3.go b/chain/actors/builtin/reward/v3.go new file mode 100644 index 000000000..18bd58f8e --- /dev/null +++ b/chain/actors/builtin/reward/v3.go @@ -0,0 +1,86 @@ +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" + + miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner" + reward3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/reward" + smoothing3 "github.com/filecoin-project/specs-actors/v3/actors/util/smoothing" +) + +var _ State = (*state3)(nil) + +func load3(store adt.Store, root cid.Cid) (State, error) { + out := state3{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state3 struct { + reward3.State + store adt.Store +} + +func (s *state3) ThisEpochReward() (abi.TokenAmount, error) { + return s.State.ThisEpochReward, nil +} + +func (s *state3) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) { + return builtin.FilterEstimate{ + PositionEstimate: s.State.ThisEpochRewardSmoothed.PositionEstimate, + VelocityEstimate: s.State.ThisEpochRewardSmoothed.VelocityEstimate, + }, nil +} + +func (s *state3) ThisEpochBaselinePower() (abi.StoragePower, error) { + return s.State.ThisEpochBaselinePower, nil +} + +func (s *state3) TotalStoragePowerReward() (abi.TokenAmount, error) { + return s.State.TotalStoragePowerReward, nil +} + +func (s *state3) EffectiveBaselinePower() (abi.StoragePower, error) { + return s.State.EffectiveBaselinePower, nil +} + +func (s *state3) EffectiveNetworkTime() (abi.ChainEpoch, error) { + return s.State.EffectiveNetworkTime, nil +} + +func (s *state3) CumsumBaseline() (reward3.Spacetime, error) { + return s.State.CumsumBaseline, nil +} + +func (s *state3) CumsumRealized() (reward3.Spacetime, error) { + return s.State.CumsumRealized, nil +} + +func (s *state3) InitialPledgeForPower(qaPower abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) { + return miner3.InitialPledgeForPower( + qaPower, + s.State.ThisEpochBaselinePower, + s.State.ThisEpochRewardSmoothed, + smoothing3.FilterEstimate{ + PositionEstimate: networkQAPower.PositionEstimate, + VelocityEstimate: networkQAPower.VelocityEstimate, + }, + circSupply, + ), nil +} + +func (s *state3) PreCommitDepositForPower(networkQAPower builtin.FilterEstimate, sectorWeight abi.StoragePower) (abi.TokenAmount, error) { + return miner3.PreCommitDepositForPower(s.State.ThisEpochRewardSmoothed, + smoothing3.FilterEstimate{ + PositionEstimate: networkQAPower.PositionEstimate, + VelocityEstimate: networkQAPower.VelocityEstimate, + }, + sectorWeight), nil +} diff --git a/chain/actors/builtin/verifreg/util.go b/chain/actors/builtin/verifreg/util.go index 4136c0c30..16e50c50a 100644 --- a/chain/actors/builtin/verifreg/util.go +++ b/chain/actors/builtin/verifreg/util.go @@ -6,16 +6,21 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/ipfs/go-cid" "golang.org/x/xerrors" ) -func getDataCap(store adt.Store, ver actors.Version, root cid.Cid, addr address.Address) (bool, abi.StoragePower, error) { +// taking this as a function instead of asking the caller to call it helps reduce some of the error +// checking boilerplate. +// +// "go made me do it" +type rootFunc func() (adt.Map, error) + +// Assumes that the bitwidth for v3 HAMTs is the DefaultHamtBitwidth +func getDataCap(store adt.Store, ver actors.Version, root rootFunc, addr address.Address) (bool, abi.StoragePower, error) { if addr.Protocol() != address.ID { return false, big.Zero(), xerrors.Errorf("can only look up ID addresses") } - - vh, err := adt.AsMap(store, root, ver) + vh, err := root() if err != nil { return false, big.Zero(), xerrors.Errorf("loading verifreg: %w", err) } @@ -30,8 +35,9 @@ func getDataCap(store adt.Store, ver actors.Version, root cid.Cid, addr address. return true, dcap, nil } -func forEachCap(store adt.Store, ver actors.Version, root cid.Cid, cb func(addr address.Address, dcap abi.StoragePower) error) error { - vh, err := adt.AsMap(store, root, ver) +// Assumes that the bitwidth for v3 HAMTs is the DefaultHamtBitwidth +func forEachCap(store adt.Store, ver actors.Version, root rootFunc, cb func(addr address.Address, dcap abi.StoragePower) error) error { + vh, err := root() if err != nil { return xerrors.Errorf("loading verified clients: %w", err) } diff --git a/chain/actors/builtin/verifreg/v0.go b/chain/actors/builtin/verifreg/v0.go index 64def4706..0dc4696f4 100644 --- a/chain/actors/builtin/verifreg/v0.go +++ b/chain/actors/builtin/verifreg/v0.go @@ -9,6 +9,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/adt" verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg" + adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" ) var _ State = (*state0)(nil) @@ -32,17 +33,25 @@ func (s *state0) RootKey() (address.Address, error) { } func (s *state0) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) { - return getDataCap(s.store, actors.Version0, s.State.VerifiedClients, addr) + return getDataCap(s.store, actors.Version0, s.verifiedClients, addr) } func (s *state0) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) { - return getDataCap(s.store, actors.Version0, s.State.Verifiers, addr) + return getDataCap(s.store, actors.Version0, s.verifiers, addr) } func (s *state0) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { - return forEachCap(s.store, actors.Version0, s.State.Verifiers, cb) + return forEachCap(s.store, actors.Version0, s.verifiers, cb) } func (s *state0) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error { - return forEachCap(s.store, actors.Version0, s.State.VerifiedClients, cb) + return forEachCap(s.store, actors.Version0, s.verifiedClients, cb) +} + +func (s *state0) verifiedClients() (adt.Map, error) { + return adt0.AsMap(s.store, s.VerifiedClients) +} + +func (s *state0) verifiers() (adt.Map, error) { + return adt0.AsMap(s.store, s.Verifiers) } diff --git a/chain/actors/builtin/verifreg/v2.go b/chain/actors/builtin/verifreg/v2.go index 5ee3bad05..a5ef84532 100644 --- a/chain/actors/builtin/verifreg/v2.go +++ b/chain/actors/builtin/verifreg/v2.go @@ -9,6 +9,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/adt" verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg" + adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" ) var _ State = (*state2)(nil) @@ -32,17 +33,25 @@ func (s *state2) RootKey() (address.Address, error) { } func (s *state2) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) { - return getDataCap(s.store, actors.Version2, s.State.VerifiedClients, addr) + return getDataCap(s.store, actors.Version2, s.verifiedClients, addr) } func (s *state2) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) { - return getDataCap(s.store, actors.Version2, s.State.Verifiers, addr) + return getDataCap(s.store, actors.Version2, s.verifiers, addr) } func (s *state2) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { - return forEachCap(s.store, actors.Version2, s.State.Verifiers, cb) + return forEachCap(s.store, actors.Version2, s.verifiers, cb) } func (s *state2) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error { - return forEachCap(s.store, actors.Version2, s.State.VerifiedClients, cb) + return forEachCap(s.store, actors.Version2, s.verifiedClients, cb) +} + +func (s *state2) verifiedClients() (adt.Map, error) { + return adt2.AsMap(s.store, s.VerifiedClients) +} + +func (s *state2) verifiers() (adt.Map, error) { + return adt2.AsMap(s.store, s.Verifiers) } diff --git a/chain/actors/builtin/verifreg/v3.go b/chain/actors/builtin/verifreg/v3.go new file mode 100644 index 000000000..fb0c46d0c --- /dev/null +++ b/chain/actors/builtin/verifreg/v3.go @@ -0,0 +1,58 @@ +package verifreg + +import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/actors/adt" + + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + verifreg3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/verifreg" + adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" +) + +var _ State = (*state3)(nil) + +func load3(store adt.Store, root cid.Cid) (State, error) { + out := state3{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +type state3 struct { + verifreg3.State + store adt.Store +} + +func (s *state3) RootKey() (address.Address, error) { + return s.State.RootKey, nil +} + +func (s *state3) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) { + return getDataCap(s.store, actors.Version3, s.verifiedClients, addr) +} + +func (s *state3) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) { + return getDataCap(s.store, actors.Version3, s.verifiers, addr) +} + +func (s *state3) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { + return forEachCap(s.store, actors.Version3, s.verifiers, cb) +} + +func (s *state3) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error { + return forEachCap(s.store, actors.Version3, s.verifiedClients, cb) +} + +func (s *state3) verifiedClients() (adt.Map, error) { + return adt3.AsMap(s.store, s.VerifiedClients, builtin3.DefaultHamtBitwidth) +} + +func (s *state3) verifiers() (adt.Map, error) { + return adt3.AsMap(s.store, s.Verifiers, builtin3.DefaultHamtBitwidth) +} diff --git a/chain/actors/builtin/verifreg/verifreg.go b/chain/actors/builtin/verifreg/verifreg.go index a4468d8a0..4e3f3559b 100644 --- a/chain/actors/builtin/verifreg/verifreg.go +++ b/chain/actors/builtin/verifreg/verifreg.go @@ -3,6 +3,7 @@ package verifreg import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" "github.com/ipfs/go-cid" "golang.org/x/xerrors" @@ -22,11 +23,14 @@ func init() { builtin.RegisterActorState(builtin2.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load2(store, root) }) + builtin.RegisterActorState(builtin3.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load3(store, root) + }) } var ( - Address = builtin2.VerifiedRegistryActorAddr - Methods = builtin2.MethodsVerifiedRegistry + Address = builtin3.VerifiedRegistryActorAddr + Methods = builtin3.MethodsVerifiedRegistry ) func Load(store adt.Store, act *types.Actor) (State, error) { @@ -35,6 +39,8 @@ func Load(store adt.Store, act *types.Actor) (State, error) { return load0(store, act.Head) case builtin2.VerifiedRegistryActorCodeID: return load2(store, act.Head) + case builtin3.VerifiedRegistryActorCodeID: + return load3(store, act.Head) } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } diff --git a/chain/actors/policy/policy.go b/chain/actors/policy/policy.go index 31d83cd3d..e32b36743 100644 --- a/chain/actors/policy/policy.go +++ b/chain/actors/policy/policy.go @@ -6,21 +6,28 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/lotus/chain/actors" + market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" power0 "github.com/filecoin-project/specs-actors/actors/builtin/power" verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" - paych2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/paych" verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg" + + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + market3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/market" + miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner" + paych3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/paych" + verifreg3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/verifreg" ) const ( - ChainFinality = miner0.ChainFinality + ChainFinality = miner3.ChainFinality SealRandomnessLookback = ChainFinality - PaychSettleDelay = paych2.SettleDelay + PaychSettleDelay = paych3.SettleDelay ) // SetSupportedProofTypes sets supported proof types, across all actor versions. @@ -31,6 +38,10 @@ func SetSupportedProofTypes(types ...abi.RegisteredSealProof) { miner2.PreCommitSealProofTypesV7 = make(map[abi.RegisteredSealProof]struct{}, len(types)*2) miner2.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types)) + miner3.PreCommitSealProofTypesV0 = make(map[abi.RegisteredSealProof]struct{}, len(types)) + miner3.PreCommitSealProofTypesV7 = make(map[abi.RegisteredSealProof]struct{}, len(types)*2) + miner3.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types)) + AddSupportedProofTypes(types...) } @@ -49,6 +60,13 @@ func AddSupportedProofTypes(types ...abi.RegisteredSealProof) { miner2.PreCommitSealProofTypesV7[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{} miner2.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{} + + miner3.PreCommitSealProofTypesV0[t] = struct{}{} + + miner3.PreCommitSealProofTypesV7[t] = struct{}{} + miner3.PreCommitSealProofTypesV7[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{} + + miner3.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{} } } @@ -58,6 +76,7 @@ func SetPreCommitChallengeDelay(delay abi.ChainEpoch) { // Set for all miner versions. miner0.PreCommitChallengeDelay = delay miner2.PreCommitChallengeDelay = delay + miner3.PreCommitChallengeDelay = delay } // TODO: this function shouldn't really exist. Instead, the API should expose the precommit delay. @@ -73,6 +92,10 @@ func SetConsensusMinerMinPower(p abi.StoragePower) { for _, policy := range builtin2.SealProofPolicies { policy.ConsensusMinerMinPower = p } + + for _, policy := range builtin3.PoStProofPolicies { + policy.ConsensusMinerMinPower = p + } } // SetMinVerifiedDealSize sets the minimum size of a verified deal. This should @@ -80,6 +103,7 @@ func SetConsensusMinerMinPower(p abi.StoragePower) { func SetMinVerifiedDealSize(size abi.StoragePower) { verifreg0.MinVerifiedDealSize = size verifreg2.MinVerifiedDealSize = size + verifreg3.MinVerifiedDealSize = size } func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) abi.ChainEpoch { @@ -88,6 +112,8 @@ func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) ab return miner0.MaxSealDuration[t] case actors.Version2: return miner2.MaxProveCommitDuration[t] + case actors.Version3: + return miner3.MaxProveCommitDuration[t] default: panic("unsupported actors version") } @@ -103,6 +129,8 @@ func DealProviderCollateralBounds( return market0.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil, nwVer) case actors.Version2: return market2.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil) + case actors.Version3: + return market3.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil) default: panic("unsupported network version") } @@ -116,6 +144,12 @@ func SetWPoStChallengeWindow(period abi.ChainEpoch) { miner2.WPoStChallengeWindow = period miner2.WPoStProvingPeriod = period * abi.ChainEpoch(miner2.WPoStPeriodDeadlines) + + miner3.WPoStChallengeWindow = period + miner3.WPoStProvingPeriod = period * abi.ChainEpoch(miner3.WPoStPeriodDeadlines) + // by default, this is 2x finality which is 30 periods. + // scale it if we're scaling the challenge period. + miner3.WPoStDisputeWindow = period * 30 } func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch { @@ -132,17 +166,17 @@ func GetMaxSectorExpirationExtension() abi.ChainEpoch { // TODO: we'll probably need to abstract over this better in the future. func GetMaxPoStPartitions(p abi.RegisteredPoStProof) (int, error) { - sectorsPerPart, err := builtin2.PoStProofWindowPoStPartitionSectors(p) + sectorsPerPart, err := builtin3.PoStProofWindowPoStPartitionSectors(p) if err != nil { return 0, err } - return int(miner2.AddressedSectorsMax / sectorsPerPart), nil + return int(miner3.AddressedSectorsMax / sectorsPerPart), nil } func GetDefaultSectorSize() abi.SectorSize { // supported sector sizes are the same across versions. - szs := make([]abi.SectorSize, 0, len(miner2.PreCommitSealProofTypesV8)) - for spt := range miner2.PreCommitSealProofTypesV8 { + szs := make([]abi.SectorSize, 0, len(miner3.PreCommitSealProofTypesV8)) + for spt := range miner3.PreCommitSealProofTypesV8 { ss, err := spt.SectorSize() if err != nil { panic(err) diff --git a/chain/actors/version.go b/chain/actors/version.go index 1d9f1f8a2..763c5a42c 100644 --- a/chain/actors/version.go +++ b/chain/actors/version.go @@ -11,6 +11,7 @@ type Version int const ( Version0 Version = 0 Version2 Version = 2 + Version3 Version = 3 ) // Converts a network version into an actors adt version. @@ -20,6 +21,8 @@ func VersionForNetwork(version network.Version) Version { return Version0 case network.Version4, network.Version5, network.Version6, network.Version7, network.Version8, network.Version9: return Version2 + case network.Version10: + return Version3 default: panic(fmt.Sprintf("unsupported network version %d", version)) } diff --git a/chain/state/statetree.go b/chain/state/statetree.go index 7fa55b31c..46a13ccc6 100644 --- a/chain/state/statetree.go +++ b/chain/state/statetree.go @@ -20,6 +20,10 @@ import ( "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" + + states0 "github.com/filecoin-project/specs-actors/actors/states" + states2 "github.com/filecoin-project/specs-actors/v2/actors/states" + states3 "github.com/filecoin-project/specs-actors/v3/actors/states" ) var log = logging.Logger("statetree") @@ -144,23 +148,12 @@ func VersionForNetwork(ver network.Version) types.StateTreeVersion { return types.StateTreeVersion1 } -func adtForSTVersion(ver types.StateTreeVersion) actors.Version { - switch ver { - case types.StateTreeVersion0: - return actors.Version0 - case types.StateTreeVersion1: - return actors.Version2 - default: - panic("unhandled state tree version") - } -} - func NewStateTree(cst cbor.IpldStore, ver types.StateTreeVersion) (*StateTree, error) { var info cid.Cid switch ver { case types.StateTreeVersion0: // info is undefined - case types.StateTreeVersion1: + case types.StateTreeVersion1, types.StateTreeVersion2: var err error info, err = cst.Put(context.TODO(), new(types.StateInfo0)) if err != nil { @@ -169,13 +162,34 @@ func NewStateTree(cst cbor.IpldStore, ver types.StateTreeVersion) (*StateTree, e default: return nil, xerrors.Errorf("unsupported state tree version: %d", ver) } - root, err := adt.NewMap(adt.WrapStore(context.TODO(), cst), adtForSTVersion(ver)) - if err != nil { - return nil, err + + store := adt.WrapStore(context.TODO(), cst) + var hamt adt.Map + switch ver { + case types.StateTreeVersion0: + tree, err := states0.NewTree(store) + if err != nil { + return nil, xerrors.Errorf("failed to create state tree: %w", err) + } + hamt = tree.Map + case types.StateTreeVersion1: + tree, err := states2.NewTree(store) + if err != nil { + return nil, xerrors.Errorf("failed to create state tree: %w", err) + } + hamt = tree.Map + case types.StateTreeVersion2: + tree, err := states3.NewTree(store) + if err != nil { + return nil, xerrors.Errorf("failed to create state tree: %w", err) + } + hamt = tree.Map + default: + return nil, xerrors.Errorf("unsupported state tree version: %d", ver) } s := &StateTree{ - root: root, + root: hamt, info: info, version: ver, Store: cst, @@ -194,30 +208,49 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) { root.Version = types.StateTreeVersion0 } - switch root.Version { - case types.StateTreeVersion0, types.StateTreeVersion1: - // Load the actual state-tree HAMT. - nd, err := adt.AsMap( - adt.WrapStore(context.TODO(), cst), root.Actors, - adtForSTVersion(root.Version), - ) - if err != nil { - log.Errorf("loading hamt node %s failed: %s", c, err) - return nil, err - } + store := adt.WrapStore(context.TODO(), cst) - s := &StateTree{ - root: nd, - info: root.Info, - version: root.Version, - Store: cst, - snaps: newStateSnaps(), + var ( + hamt adt.Map + err error + ) + switch root.Version { + case types.StateTreeVersion0: + var tree *states0.Tree + tree, err = states0.LoadTree(store, root.Actors) + if tree != nil { + hamt = tree.Map + } + case types.StateTreeVersion1: + var tree *states2.Tree + tree, err = states2.LoadTree(store, root.Actors) + if tree != nil { + hamt = tree.Map + } + case types.StateTreeVersion2: + var tree *states3.Tree + tree, err = states3.LoadTree(store, root.Actors) + if tree != nil { + hamt = tree.Map } - s.lookupIDFun = s.lookupIDinternal - return s, nil default: return nil, xerrors.Errorf("unsupported state tree version: %d", root.Version) } + if err != nil { + log.Errorf("failed to load state tree: %s", err) + return nil, xerrors.Errorf("failed to load state tree: %w", err) + } + + s := &StateTree{ + root: hamt, + info: root.Info, + version: root.Version, + Store: cst, + snaps: newStateSnaps(), + } + s.lookupIDFun = s.lookupIDinternal + + return s, nil } func (st *StateTree) SetActor(addr address.Address, act *types.Actor) error { diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go index 7fe12d2a8..e09744a67 100644 --- a/chain/stmgr/forks.go +++ b/chain/stmgr/forks.go @@ -4,7 +4,8 @@ import ( "bytes" "context" "encoding/binary" - "math" + + "github.com/filecoin-project/go-state-types/rt" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" @@ -29,6 +30,7 @@ import ( adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/v2/actors/migration/nv4" "github.com/filecoin-project/specs-actors/v2/actors/migration/nv7" + "github.com/filecoin-project/specs-actors/v3/actors/migration/nv10" "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" "golang.org/x/xerrors" @@ -52,6 +54,21 @@ type Upgrade struct { type UpgradeSchedule []Upgrade +type migrationLogger struct{} + +func (ml migrationLogger) Log(level rt.LogLevel, msg string, args ...interface{}) { + switch level { + case rt.DEBUG: + log.Debugf(msg, args...) + case rt.INFO: + log.Infof(msg, args...) + case rt.WARN: + log.Warnf(msg, args...) + case rt.ERROR: + log.Errorf(msg, args...) + } +} + func DefaultUpgradeSchedule() UpgradeSchedule { var us UpgradeSchedule @@ -100,32 +117,13 @@ func DefaultUpgradeSchedule() UpgradeSchedule { Height: build.UpgradeOrangeHeight, Network: network.Version9, Migration: nil, + }, { + Height: build.UpgradeActorsV3Height, + Network: network.Version10, + Migration: UpgradeActorsV3, + Expensive: true, }} - if build.UpgradeActorsV2Height == math.MaxInt64 { // disable actors upgrade - updates = []Upgrade{{ - Height: build.UpgradeBreezeHeight, - Network: network.Version1, - Migration: UpgradeFaucetBurnRecovery, - }, { - Height: build.UpgradeSmokeHeight, - Network: network.Version2, - Migration: nil, - }, { - Height: build.UpgradeIgnitionHeight, - Network: network.Version3, - Migration: UpgradeIgnition, - }, { - Height: build.UpgradeRefuelHeight, - Network: network.Version3, - Migration: UpgradeRefuel, - }, { - Height: build.UpgradeLiftoffHeight, - Network: network.Version3, - Migration: UpgradeLiftoff, - }} - } - for _, u := range updates { if u.Height < 0 { // upgrade disabled @@ -704,6 +702,73 @@ func UpgradeCalico(ctx context.Context, sm *StateManager, cb ExecCallback, root return newRoot, nil } +func UpgradeActorsV3(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) { + buf := bufbstore.NewTieredBstore(sm.cs.Blockstore(), bstore.NewTemporarySync()) + 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.StateTreeVersion1 { + return cid.Undef, xerrors.Errorf( + "expected state root version 1 for actors v3 upgrade, got %d", + stateRoot.Version, + ) + } + + // Perform the migration + + // TODO: store this somewhere and pre-migrate + cache := nv10.NewMemMigrationCache() + // TODO: tune this. + config := nv10.Config{MaxWorkers: 1} + newHamtRoot, err := nv10.MigrateStateTree(ctx, store, stateRoot.Actors, epoch, config, migrationLogger{}, cache) + if err != nil { + return cid.Undef, xerrors.Errorf("upgrading to actors v2: %w", err) + } + + // Persist the result. + + newRoot, err := store.Put(ctx, &types.StateRoot{ + Version: types.StateTreeVersion2, + Actors: newHamtRoot, + Info: stateRoot.Info, + }) + if err != nil { + return cid.Undef, xerrors.Errorf("failed to persist new state root: %w", err) + } + + // Check the result. + + // perform some basic sanity checks to make sure everything still works. + if newSm, err := state.LoadStateTree(store, newRoot); err != nil { + return cid.Undef, xerrors.Errorf("state tree sanity load failed: %w", err) + } else if newRoot2, err := newSm.Flush(ctx); err != nil { + return cid.Undef, xerrors.Errorf("state tree sanity flush failed: %w", err) + } else if newRoot2 != newRoot { + return cid.Undef, xerrors.Errorf("state-root mismatch: %s != %s", newRoot, newRoot2) + } else if _, err := newSm.GetActor(init_.Address); err != nil { + return cid.Undef, xerrors.Errorf("failed to load init actor after upgrade: %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 +} + func setNetworkName(ctx context.Context, store adt.Store, tree *state.StateTree, name string) error { ia, err := tree.GetActor(builtin0.InitActorAddr) if err != nil { diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index 5d9f35975..84e9e1744 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -21,6 +21,9 @@ import ( // Used for genesis. msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" + // we use the same adt for all receipts + blockadt "github.com/filecoin-project/specs-actors/actors/util/adt" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" @@ -42,6 +45,7 @@ import ( ) const LookbackNoLimit = abi.ChainEpoch(-1) +const ReceiptAmtBitwidth = 3 var log = logging.Logger("statemgr") @@ -384,11 +388,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp return cid.Cid{}, cid.Cid{}, err } - // XXX: Is the height correct? Or should it be epoch-1? - rectarr, err := adt.NewArray(sm.cs.Store(ctx), actors.VersionForNetwork(sm.GetNtwkVersion(ctx, epoch))) - if err != nil { - return cid.Undef, cid.Undef, xerrors.Errorf("failed to create receipts amt: %w", err) - } + rectarr := blockadt.MakeEmptyArray(sm.cs.Store(ctx)) for i, receipt := range receipts { if err := rectarr.Set(uint64(i), receipt); err != nil { return cid.Undef, cid.Undef, xerrors.Errorf("failed to build receipts amt: %w", err) diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index 1e29e72d8..1d59b2630 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -25,6 +25,7 @@ import ( exported0 "github.com/filecoin-project/specs-actors/actors/builtin/exported" exported2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/exported" + exported3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/exported" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -207,17 +208,17 @@ func GetSectorsForWinningPoSt(ctx context.Context, nv network.Version, pv ffiwra return nil, xerrors.Errorf("getting miner info: %w", err) } - wpt, err := info.SealProofType.RegisteredWinningPoStProof() - if err != nil { - return nil, xerrors.Errorf("getting window proof type: %w", err) - } - mid, err := address.IDFromAddress(maddr) if err != nil { return nil, xerrors.Errorf("getting miner ID: %w", err) } - ids, err := pv.GenerateWinningPoStSectorChallenge(ctx, wpt, abi.ActorID(mid), rand, numProvSect) + proofType, err := miner.WinningPoStProofTypeFromWindowPoStProofType(nv, info.WindowPoStProofType) + if err != nil { + return nil, xerrors.Errorf("determining winning post proof type: %w", err) + } + + ids, err := pv.GenerateWinningPoStSectorChallenge(ctx, proofType, abi.ActorID(mid), rand, numProvSect) if err != nil { return nil, xerrors.Errorf("generating winning post challenges: %w", err) } @@ -560,6 +561,7 @@ func init() { var actors []rt.VMActor actors = append(actors, exported0.BuiltinActors()...) actors = append(actors, exported2.BuiltinActors()...) + actors = append(actors, exported3.BuiltinActors()...) for _, actor := range actors { exports := actor.Exports() diff --git a/chain/sync_manager_test.go b/chain/sync_manager_test.go index a5ff033ac..5f23e67c0 100644 --- a/chain/sync_manager_test.go +++ b/chain/sync_manager_test.go @@ -150,8 +150,11 @@ func TestSyncManagerEdgeCase(t *testing.T) { t.Fatalf("Expected tipset %s to sync, but got %s", e1, last) } - if len(sm.state) != 0 { - t.Errorf("active syncs expected empty but got: %d", len(sm.state)) + sm.mx.Lock() + activeSyncs := len(sm.state) + sm.mx.Unlock() + if activeSyncs != 0 { + t.Errorf("active syncs expected empty but got: %d", activeSyncs) } }) } diff --git a/chain/types/state.go b/chain/types/state.go index a96883604..c14836ee7 100644 --- a/chain/types/state.go +++ b/chain/types/state.go @@ -9,8 +9,10 @@ type StateTreeVersion uint64 const ( // StateTreeVersion0 corresponds to actors < v2. StateTreeVersion0 StateTreeVersion = iota - // StateTreeVersion1 corresponds to actors >= v2. + // StateTreeVersion1 corresponds to actors v2 StateTreeVersion1 + // StateTreeVersion2 corresponds to actors >= v3. + StateTreeVersion2 ) type StateRoot struct { diff --git a/chain/vm/invoker.go b/chain/vm/invoker.go index a5610736a..1c1d04f19 100644 --- a/chain/vm/invoker.go +++ b/chain/vm/invoker.go @@ -17,6 +17,7 @@ import ( exported0 "github.com/filecoin-project/specs-actors/actors/builtin/exported" exported2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/exported" vmr "github.com/filecoin-project/specs-actors/v2/actors/runtime" + exported3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/exported" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/exitcode" @@ -62,6 +63,7 @@ func NewActorRegistry() *ActorRegistry { // add builtInCode using: register(cid, singleton) inv.Register(ActorsVersionPredicate(actors.Version0), exported0.BuiltinActors()...) inv.Register(ActorsVersionPredicate(actors.Version2), exported2.BuiltinActors()...) + inv.Register(ActorsVersionPredicate(actors.Version3), exported3.BuiltinActors()...) return inv } diff --git a/chain/vm/mkactor.go b/chain/vm/mkactor.go index 885d3c0db..072711db6 100644 --- a/chain/vm/mkactor.go +++ b/chain/vm/mkactor.go @@ -12,6 +12,7 @@ import ( builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/chain/actors/aerrors" @@ -91,6 +92,8 @@ func newAccountActor(ver actors.Version) *types.Actor { code = builtin0.AccountActorCodeID case actors.Version2: code = builtin2.AccountActorCodeID + case actors.Version3: + code = builtin3.AccountActorCodeID default: panic("unsupported actors version") } diff --git a/cmd/lotus-gateway/endtoend_test.go b/cmd/lotus-gateway/endtoend_test.go index 4d5e88c82..b6d81efb4 100644 --- a/cmd/lotus-gateway/endtoend_test.go +++ b/cmd/lotus-gateway/endtoend_test.go @@ -245,7 +245,7 @@ func startNodes( // Create a gateway server in front of the full node gapiImpl := newGatewayAPI(fullNode, lookbackCap, stateWaitLookbackLimit) - _, addr, err := builder.CreateRPCServer(gapiImpl) + _, addr, err := builder.CreateRPCServer(t, gapiImpl) require.NoError(t, err) // Create a gateway client API that connects to the gateway server diff --git a/cmd/lotus-shed/datastore.go b/cmd/lotus-shed/datastore.go index 8cdc1630c..e0c4465b5 100644 --- a/cmd/lotus-shed/datastore.go +++ b/cmd/lotus-shed/datastore.go @@ -120,7 +120,7 @@ var datastoreGetCmd = &cli.Command{ }, ArgsUsage: "[namespace key]", Action: func(cctx *cli.Context) error { - logging.SetLogLevel("badger", "ERROR") // nolint:errchec + logging.SetLogLevel("badger", "ERROR") // nolint:errcheck r, err := repo.NewFS(cctx.String("repo")) if err != nil { diff --git a/cmd/lotus-storage-miner/actor_test.go b/cmd/lotus-storage-miner/actor_test.go index 2aea6bda9..1816c1eab 100644 --- a/cmd/lotus-storage-miner/actor_test.go +++ b/cmd/lotus-storage-miner/actor_test.go @@ -50,7 +50,7 @@ func TestWorkerKeyChange(t *testing.T) { blocktime := 1 * time.Millisecond - n, sn := builder.MockSbBuilder(t, []test.FullNodeOpts{test.FullNodeWithActorsV2At(1), test.FullNodeWithActorsV2At(1)}, test.OneMiner) + n, sn := builder.MockSbBuilder(t, []test.FullNodeOpts{test.FullNodeWithActorsV3At(2), test.FullNodeWithActorsV3At(2)}, test.OneMiner) client1 := n[0] client2 := n[1] diff --git a/cmd/lotus-storage-miner/proving.go b/cmd/lotus-storage-miner/proving.go index 6f379e99c..3d60f4b76 100644 --- a/cmd/lotus-storage-miner/proving.go +++ b/cmd/lotus-storage-miner/proving.go @@ -430,11 +430,6 @@ var provingCheckProvableCmd = &cli.Command{ return err } - pf, err := info.SealProofType.RegisteredWindowPoStProof() - if err != nil { - return err - } - partitions, err := api.StateMinerPartitions(ctx, addr, dlIdx, types.EmptyTSK) if err != nil { return err @@ -463,7 +458,7 @@ var provingCheckProvableCmd = &cli.Command{ }) } - bad, err := sapi.CheckProvable(ctx, pf, tocheck, cctx.Bool("slow")) + bad, err := sapi.CheckProvable(ctx, info.WindowPoStProofType, tocheck, cctx.Bool("slow")) if err != nil { return err } diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index dbac8e30f..2c75ecaaa 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -4028,7 +4028,7 @@ Response: "WorkerChangeEpoch": 10101, "PeerId": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", "Multiaddrs": null, - "SealProofType": 8, + "WindowPoStProofType": 8, "SectorSize": 34359738368, "WindowPoStPartitionSectors": 42, "ConsensusFaultElapsed": 10101 diff --git a/extern/storage-sealing/sealing.go b/extern/storage-sealing/sealing.go index 96d63efdc..f46403742 100644 --- a/extern/storage-sealing/sealing.go +++ b/extern/storage-sealing/sealing.go @@ -475,7 +475,12 @@ func (m *Sealing) currentSealProof(ctx context.Context) (abi.RegisteredSealProof return 0, err } - return mi.SealProofType, nil + ver, err := m.api.StateNetworkVersion(ctx, nil) + if err != nil { + return 0, err + } + + return miner.PreferredSealProofTypeFromWindowPoStType(ver, mi.WindowPoStProofType) } func (m *Sealing) minerSector(spt abi.RegisteredSealProof, num abi.SectorNumber) storage.SectorRef { diff --git a/go.mod b/go.mod index 0810d7e7e..b4b43fb97 100644 --- a/go.mod +++ b/go.mod @@ -38,12 +38,13 @@ require ( github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261 - github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc + github.com/filecoin-project/go-state-types v0.0.0-20210119062722-4adba5aaea71 github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe github.com/filecoin-project/go-statestore v0.1.0 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b github.com/filecoin-project/specs-actors v0.9.13 - github.com/filecoin-project/specs-actors/v2 v2.3.3 + github.com/filecoin-project/specs-actors/v2 v2.3.4 + github.com/filecoin-project/specs-actors/v3 v3.0.1-0.20210122191213-c7ea99141c44 github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 github.com/filecoin-project/test-vectors/schema v0.0.5 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 diff --git a/go.sum b/go.sum index 7f60cef4a..6368b8bfb 100644 --- a/go.sum +++ b/go.sum @@ -246,6 +246,8 @@ github.com/filecoin-project/go-amt-ipld/v2 v2.1.0 h1:t6qDiuGYYngDqaLc2ZUvdtAg4UN github.com/filecoin-project/go-amt-ipld/v2 v2.1.0/go.mod h1:nfFPoGyX0CU9SkXX8EoCcSuHN1XcbN0c6KBh7yvP5fs= github.com/filecoin-project/go-amt-ipld/v2 v2.1.1-0.20201006184820-924ee87a1349 h1:pIuR0dnMD0i+as8wNnjjHyQrnhP5O5bmba/lmgQeRgU= github.com/filecoin-project/go-amt-ipld/v2 v2.1.1-0.20201006184820-924ee87a1349/go.mod h1:vgmwKBkx+ca5OIeEvstiQgzAZnb7R6QaqE1oEDSqa6g= +github.com/filecoin-project/go-amt-ipld/v3 v3.0.0 h1:Ou/q82QeHGOhpkedvaxxzpBYuqTxLCcj5OChkDNx4qc= +github.com/filecoin-project/go-amt-ipld/v3 v3.0.0/go.mod h1:Qa95YNAbtoVCTSVtX38aAC1ptBnJfPma1R/zZsKmx4o= github.com/filecoin-project/go-bitfield v0.2.0 h1:gCtLcjskIPtdg4NfN7gQZSQF9yrBQ7mkT0qCJxzGI2Q= github.com/filecoin-project/go-bitfield v0.2.0/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM= github.com/filecoin-project/go-bitfield v0.2.3-0.20201110211213-fe2c1862e816 h1:RMdzMqe3mu2Z/3N3b9UEfkbGZxukstmZgNC024ybWhA= @@ -273,6 +275,8 @@ github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3 github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0/go.mod h1:7aWZdaQ1b16BVoQUYR+eEvrDCGJoPLxFpDynFjYfBjI= +github.com/filecoin-project/go-hamt-ipld/v3 v3.0.0 h1:aEOgJxSMbJ7XtuX3WxXvbpkBDp4Sqn3jyx/umGyL8s4= +github.com/filecoin-project/go-hamt-ipld/v3 v3.0.0/go.mod h1:gXpNmr3oQx8l3o7qkGyDjJjYSRX7hp/FGOStdqrWyDI= github.com/filecoin-project/go-jsonrpc v0.1.2 h1:MTebUawBHLxxY9gDi1WXuGc89TWIDmsgoDqeZSk9KRw= github.com/filecoin-project/go-jsonrpc v0.1.2/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= github.com/filecoin-project/go-multistore v0.0.3 h1:vaRBY4YiA2UZFPK57RNuewypB8u0DzzQwqsL0XarpnI= @@ -286,6 +290,8 @@ github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4/go github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc h1:+hbMY4Pcx2oizrfH08VWXwrj5mU8aJT6g0UNxGHFCGU= github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= +github.com/filecoin-project/go-state-types v0.0.0-20210119062722-4adba5aaea71 h1:Cas/CUB4ybYpdxvW7LouaydE16cpwdq3vvS3qgZuU+Q= +github.com/filecoin-project/go-state-types v0.0.0-20210119062722-4adba5aaea71/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statestore v0.1.0 h1:t56reH59843TwXHkMcwyuayStBIiWBRilQjQ+5IiwdQ= @@ -299,8 +305,10 @@ github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK github.com/filecoin-project/specs-actors/v2 v2.0.1/go.mod h1:v2NZVYinNIKA9acEMBm5wWXxqv5+frFEbekBFemYghY= github.com/filecoin-project/specs-actors/v2 v2.3.2 h1:2Vcf4CGa29kRh4JJ02m+FbvD/p3YNnLGsaHfw7Uj49g= github.com/filecoin-project/specs-actors/v2 v2.3.2/go.mod h1:UuJQLoTx/HPvvWeqlIFmC/ywlOLHNe8SNQ3OunFbu2Y= -github.com/filecoin-project/specs-actors/v2 v2.3.3 h1:5Pd6pjU7VjUye+Hz4gYBCPAFdBxtEbHsgGYvWmfc83w= -github.com/filecoin-project/specs-actors/v2 v2.3.3/go.mod h1:UuJQLoTx/HPvvWeqlIFmC/ywlOLHNe8SNQ3OunFbu2Y= +github.com/filecoin-project/specs-actors/v2 v2.3.4 h1:NZK2oMCcA71wNsUzDBmLQyRMzcCnX9tDGvwZ53G67j8= +github.com/filecoin-project/specs-actors/v2 v2.3.4/go.mod h1:UuJQLoTx/HPvvWeqlIFmC/ywlOLHNe8SNQ3OunFbu2Y= +github.com/filecoin-project/specs-actors/v3 v3.0.1-0.20210122191213-c7ea99141c44 h1:QYCM/E0u5XJVJENnegPR7I7meciI3CITylc9BzyoiFE= +github.com/filecoin-project/specs-actors/v3 v3.0.1-0.20210122191213-c7ea99141c44/go.mod h1:aVf248CfjfyCmVel4UuFAA3u+9UQjqtqHpgfYv+M+9U= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 h1:Ur/l2+6qN+lQiqjozWWc5p9UDaAMDZKTlDS98oRnlIw= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= diff --git a/markets/storageadapter/provider.go b/markets/storageadapter/provider.go index 085888ee3..90a659d34 100644 --- a/markets/storageadapter/provider.go +++ b/markets/storageadapter/provider.go @@ -24,6 +24,7 @@ import ( "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/builtin/market" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/events" "github.com/filecoin-project/lotus/chain/events/state" "github.com/filecoin-project/lotus/chain/types" @@ -156,30 +157,36 @@ func (n *ProviderNodeAdapter) VerifySignature(ctx context.Context, sig crypto.Si return err == nil, err } -func (n *ProviderNodeAdapter) GetMinerWorkerAddress(ctx context.Context, miner address.Address, tok shared.TipSetToken) (address.Address, error) { +func (n *ProviderNodeAdapter) GetMinerWorkerAddress(ctx context.Context, maddr address.Address, tok shared.TipSetToken) (address.Address, error) { tsk, err := types.TipSetKeyFromBytes(tok) if err != nil { return address.Undef, err } - mi, err := n.StateMinerInfo(ctx, miner, tsk) + mi, err := n.StateMinerInfo(ctx, maddr, tsk) if err != nil { return address.Address{}, err } return mi.Worker, nil } -func (n *ProviderNodeAdapter) GetProofType(ctx context.Context, miner address.Address, tok shared.TipSetToken) (abi.RegisteredSealProof, error) { +func (n *ProviderNodeAdapter) GetProofType(ctx context.Context, maddr address.Address, tok shared.TipSetToken) (abi.RegisteredSealProof, error) { tsk, err := types.TipSetKeyFromBytes(tok) if err != nil { return 0, err } - mi, err := n.StateMinerInfo(ctx, miner, tsk) + mi, err := n.StateMinerInfo(ctx, maddr, tsk) if err != nil { return 0, err } - return mi.SealProofType, nil + + nver, err := n.StateNetworkVersion(ctx, tsk) + if err != nil { + return 0, err + } + + return miner.PreferredSealProofTypeFromWindowPoStType(nver, mi.WindowPoStProofType) } func (n *ProviderNodeAdapter) SignBytes(ctx context.Context, signer address.Address, b []byte) (*crypto.Signature, error) { diff --git a/node/impl/client/client.go b/node/impl/client/client.go index e90a31a80..00c840b63 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -7,6 +7,8 @@ import ( "io" "os" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "golang.org/x/xerrors" "github.com/filecoin-project/go-padreader" @@ -157,6 +159,16 @@ func (a *API) ClientStartDeal(ctx context.Context, params *api.StartDealParams) dealStart = ts.Height() + abi.ChainEpoch(dealStartBufferHours*blocksPerHour) // TODO: Get this from storage ask } + networkVersion, err := a.StateNetworkVersion(ctx, types.EmptyTSK) + if err != nil { + return nil, xerrors.Errorf("failed to get network version: %w", err) + } + + st, err := miner.PreferredSealProofTypeFromWindowPoStType(networkVersion, mi.WindowPoStProofType) + if err != nil { + return nil, xerrors.Errorf("failed to get seal proof type: %w", err) + } + result, err := a.SMDealClient.ProposeStorageDeal(ctx, storagemarket.ProposeStorageDealParams{ Addr: params.Wallet, Info: &providerInfo, @@ -165,7 +177,7 @@ func (a *API) ClientStartDeal(ctx context.Context, params *api.StartDealParams) EndEpoch: calcDealExpiration(params.MinBlocksDuration, md, dealStart), Price: params.EpochPrice, Collateral: params.ProviderCollateral, - Rt: mi.SealProofType, + Rt: st, FastRetrieval: params.FastRetrieval, VerifiedDeal: params.VerifiedDeal, StoreID: storeID, diff --git a/node/impl/full/state.go b/node/impl/full/state.go index b92813f7a..cecf8ef55 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -140,15 +140,10 @@ func (m *StateModule) StateMinerInfo(ctx context.Context, actor address.Address, return miner.MinerInfo{}, xerrors.Errorf("failed to load miner actor state: %w", err) } - // TODO: You know, this is terrible. - // I mean, we _really_ shouldn't do this. Maybe we should convert somewhere else? info, err := mas.Info() if err != nil { return miner.MinerInfo{}, err } - if m.StateManager.GetNtwkVersion(ctx, ts.Height()) >= network.Version7 && info.SealProofType < abi.RegisteredSealProof_StackedDrg2KiBV1_1 { - info.SealProofType += abi.RegisteredSealProof_StackedDrg2KiBV1_1 - } return info, nil } @@ -170,7 +165,7 @@ func (a *StateAPI) StateMinerDeadlines(ctx context.Context, m address.Address, t out := make([]api.Deadline, deadlines) if err := mas.ForEachDeadline(func(i uint64, dl miner.Deadline) error { - ps, err := dl.PostSubmissions() + ps, err := dl.PartitionsPoSted() if err != nil { return err } diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 30f84aeaf..2a0b3f8b2 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -58,6 +58,7 @@ import ( lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/gen/slashfilter" "github.com/filecoin-project/lotus/chain/types" @@ -66,7 +67,7 @@ import ( "github.com/filecoin-project/lotus/markets" marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/markets/retrievaladapter" - "github.com/filecoin-project/lotus/miner" + lotusminer "github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/helpers" @@ -127,8 +128,12 @@ func SealProofType(maddr dtypes.MinerAddress, fnapi lapi.FullNode) (abi.Register if err != nil { return 0, err } + networkVersion, err := fnapi.StateNetworkVersion(context.TODO(), types.EmptyTSK) + if err != nil { + return 0, err + } - return mi.SealProofType, nil + return miner.PreferredSealProofTypeFromWindowPoStType(networkVersion, mi.WindowPoStProofType) } type sidsc struct { @@ -419,13 +424,13 @@ func StagingGraphsync(mctx helpers.MetricsCtx, lc fx.Lifecycle, ibs dtypes.Stagi return gs } -func SetupBlockProducer(lc fx.Lifecycle, ds dtypes.MetadataDS, api lapi.FullNode, epp gen.WinningPoStProver, sf *slashfilter.SlashFilter, j journal.Journal) (*miner.Miner, error) { +func SetupBlockProducer(lc fx.Lifecycle, ds dtypes.MetadataDS, api lapi.FullNode, epp gen.WinningPoStProver, sf *slashfilter.SlashFilter, j journal.Journal) (*lotusminer.Miner, error) { minerAddr, err := minerAddrFromDS(ds) if err != nil { return nil, err } - m := miner.NewMiner(api, epp, minerAddr, sf, j) + m := lotusminer.NewMiner(api, epp, minerAddr, sf, j) lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { diff --git a/node/node_test.go b/node/node_test.go index ecc0914ae..a44b0f3a8 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -198,3 +198,16 @@ func TestPaymentChannels(t *testing.T) { test.TestPaymentChannels(t, builder.MockSbBuilder, 5*time.Millisecond) } + +func TestWindowPostDispute(t *testing.T) { + if os.Getenv("LOTUS_TEST_WINDOW_POST") != "1" { + t.Skip("this takes a few minutes, set LOTUS_TEST_WINDOW_POST=1 to run") + } + logging.SetLogLevel("miner", "ERROR") + logging.SetLogLevel("chainstore", "ERROR") + logging.SetLogLevel("chain", "ERROR") + logging.SetLogLevel("sub", "ERROR") + logging.SetLogLevel("storageminer", "ERROR") + + test.TestWindowPostDispute(t, builder.MockSbBuilder, 2*time.Millisecond) +} diff --git a/node/test/builder.go b/node/test/builder.go index f6599cf23..94ddf6a4a 100644 --- a/node/test/builder.go +++ b/node/test/builder.go @@ -148,7 +148,7 @@ func CreateTestStorageNode(ctx context.Context, t *testing.T, waddr address.Addr } } - return test.TestStorageNode{StorageMiner: minerapi, MineOne: mineOne} + return test.TestStorageNode{StorageMiner: minerapi, MineOne: mineOne, Stop: stop} } func Builder(t *testing.T, fullOpts []test.FullNodeOpts, storage []test.StorageMiner) ([]test.TestNode, []test.TestStorageNode) { @@ -491,34 +491,40 @@ func mockSbBuilderOpts(t *testing.T, fullOpts []test.FullNodeOpts, storage []tes } func fullRpc(t *testing.T, nd test.TestNode) test.TestNode { - ma, listenAddr, err := CreateRPCServer(nd) + ma, listenAddr, err := CreateRPCServer(t, nd) require.NoError(t, err) + var stop func() var full test.TestNode - full.FullNode, _, err = client.NewFullNodeRPC(context.Background(), listenAddr, nil) + full.FullNode, stop, err = client.NewFullNodeRPC(context.Background(), listenAddr, nil) require.NoError(t, err) + t.Cleanup(stop) full.ListenAddr = ma return full } func storerRpc(t *testing.T, nd test.TestStorageNode) test.TestStorageNode { - ma, listenAddr, err := CreateRPCServer(nd) + ma, listenAddr, err := CreateRPCServer(t, nd) require.NoError(t, err) + var stop func() var storer test.TestStorageNode - storer.StorageMiner, _, err = client.NewStorageMinerRPC(context.Background(), listenAddr, nil) + storer.StorageMiner, stop, err = client.NewStorageMinerRPC(context.Background(), listenAddr, nil) require.NoError(t, err) + t.Cleanup(stop) storer.ListenAddr = ma storer.MineOne = nd.MineOne return storer } -func CreateRPCServer(handler interface{}) (multiaddr.Multiaddr, string, error) { +func CreateRPCServer(t *testing.T, handler interface{}) (multiaddr.Multiaddr, string, error) { rpcServer := jsonrpc.NewServer() rpcServer.Register("Filecoin", handler) testServ := httptest.NewServer(rpcServer) // todo: close + t.Cleanup(testServ.Close) + t.Cleanup(testServ.CloseClientConnections) addr := testServ.Listener.Addr() listenAddr := "ws://" + addr.String() diff --git a/storage/miner.go b/storage/miner.go index 752d7ff42..425664991 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -225,18 +225,13 @@ func NewWinningPoStProver(api api.FullNode, prover storage.Prover, verifier ffiw return nil, xerrors.Errorf("getting sector size: %w", err) } - wpt, err := mi.SealProofType.RegisteredWinningPoStProof() - if err != nil { - return nil, err - } - if build.InsecurePoStValidation { log.Warn("*****************************************************************************") log.Warn(" Generating fake PoSt proof! You should only see this while running tests! ") log.Warn("*****************************************************************************") } - return &StorageWpp{prover, verifier, abi.ActorID(miner), wpt}, nil + return &StorageWpp{prover, verifier, abi.ActorID(miner), mi.WindowPoStProofType}, nil } var _ gen.WinningPoStProver = (*StorageWpp)(nil) diff --git a/storage/wdpost_sched.go b/storage/wdpost_sched.go index f81a60a1e..3d6073a63 100644 --- a/storage/wdpost_sched.go +++ b/storage/wdpost_sched.go @@ -47,18 +47,13 @@ func NewWindowedPoStScheduler(api storageMinerApi, fc config.MinerFeeConfig, as return nil, xerrors.Errorf("getting sector size: %w", err) } - rt, err := mi.SealProofType.RegisteredWindowPoStProof() - if err != nil { - return nil, err - } - return &WindowPoStScheduler{ api: api, feeCfg: fc, addrSel: as, prover: sb, faultTracker: ft, - proofType: rt, + proofType: mi.WindowPoStProofType, partitionSectors: mi.WindowPoStPartitionSectors, actor: actor,