Merge pull request #5418 from filecoin-project/next

v3 actors staging branch
This commit is contained in:
Łukasz Magiera 2021-01-26 01:59:12 +01:00 committed by GitHub
commit 77fa3d6ca7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
68 changed files with 2863 additions and 250 deletions

View File

@ -201,6 +201,8 @@ jobs:
<<: *test <<: *test
test-window-post: test-window-post:
<<: *test <<: *test
test-window-post-dispute:
<<: *test
test-terminate: test-terminate:
<<: *test <<: *test
test-conformance: test-conformance:
@ -265,6 +267,16 @@ jobs:
path: /tmp/test-reports path: /tmp/test-reports
- store_artifacts: - store_artifacts:
path: /tmp/test-artifacts/conformance-coverage.html path: /tmp/test-artifacts/conformance-coverage.html
build-ntwk-calibration:
description: |
Compile lotus binaries for the calibration network
parameters:
<<: *test-params
executor: << parameters.executor >>
steps:
- install-deps
- prepare
- run: make calibnet
build-lotus-soup: build-lotus-soup:
description: | description: |
Compile `lotus-soup` Testground test plan Compile `lotus-soup` Testground test plan
@ -591,6 +603,11 @@ workflows:
go-test-flags: "-run=TestWindowedPost" go-test-flags: "-run=TestWindowedPost"
winpost-test: "1" winpost-test: "1"
test-suite-name: window-post 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: - test-terminate:
codecov-upload: true codecov-upload: true
go-test-flags: "-run=TestTerminate" go-test-flags: "-run=TestTerminate"
@ -611,6 +628,7 @@ workflows:
test-suite-name: conformance-bleeding-edge test-suite-name: conformance-bleeding-edge
packages: "./conformance" packages: "./conformance"
vectors-branch: master vectors-branch: master
- build-ntwk-calibration
- build-lotus-soup - build-lotus-soup
- trigger-testplans: - trigger-testplans:
filters: filters:

View File

@ -949,7 +949,8 @@ const (
) )
type Deadline struct { type Deadline struct {
PostSubmissions bitfield.BitField PostSubmissions bitfield.BitField
DisputableProofCount uint64
} }
type Partition struct { type Partition struct {

View File

@ -17,9 +17,9 @@ import (
func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) { func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
for _, height := range []abi.ChainEpoch{ for _, height := range []abi.ChainEpoch{
1, // before 2, // before
162, // while sealing 162, // while sealing
520, // after upgrade deal 530, // after upgrade deal
5000, // after 5000, // after
} { } {
height := height // make linters happy by copying 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) { func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeHeight abi.ChainEpoch) {
ctx := context.Background() 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) client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0] miner := sn[0]

View File

@ -49,6 +49,7 @@ type TestStorageNode struct {
ListenAddr multiaddr.Multiaddr ListenAddr multiaddr.Multiaddr
MineOne func(context.Context, miner.MineReq) error MineOne func(context.Context, miner.MineReq) error
Stop func(context.Context) error
} }
var PresealGenesis = -1 var PresealGenesis = -1
@ -110,14 +111,19 @@ var OneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}}
var OneFull = DefaultFullOpts(1) var OneFull = DefaultFullOpts(1)
var TwoFull = DefaultFullOpts(2) var TwoFull = DefaultFullOpts(2)
var FullNodeWithActorsV2At = func(upgradeHeight abi.ChainEpoch) FullNodeOpts { var FullNodeWithActorsV3At = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
return FullNodeOpts{ return FullNodeOpts{
Opts: func(nodes []TestNode) node.Option { Opts: func(nodes []TestNode) node.Option {
return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{ return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
// Skip directly to tape height so precommits work. // prepare for upgrade.
Network: network.Version5, Network: network.Version9,
Height: upgradeHeight, Height: 1,
Migration: stmgr.UpgradeActorsV2, Migration: stmgr.UpgradeActorsV2,
}, {
// Skip directly to tape height so precommits work.
Network: network.Version10,
Height: upgradeHeight,
Migration: stmgr.UpgradeActorsV3,
}}) }})
}, },
} }

View File

@ -16,13 +16,18 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi" "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/go-state-types/network"
"github.com/filecoin-project/lotus/extern/sector-storage/mock" "github.com/filecoin-project/lotus/extern/sector-storage/mock"
sealing "github.com/filecoin-project/lotus/extern/storage-sealing" 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/specs-storage/storage"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
minerActor "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
bminer "github.com/filecoin-project/lotus/miner" bminer "github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/lotus/node/impl" "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) { func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
for _, height := range []abi.ChainEpoch{ for _, height := range []abi.ChainEpoch{
1, // before 2, // before
162, // while sealing 162, // while sealing
5000, // while proving 5000, // while proving
} { } {
@ -218,7 +223,7 @@ func testWindowPostUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration,
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV2At(upgradeHeight)}, OneMiner) n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV3At(upgradeHeight)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI) client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0] miner := sn[0]
@ -437,7 +442,7 @@ func TestTerminate(t *testing.T, b APIBuilder, blocktime time.Duration) {
nSectors := uint64(2) 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) client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0] miner := sn[0]
@ -602,3 +607,420 @@ loop:
require.Equal(t, p.MinerPower, p.TotalPower) require.Equal(t, p.MinerPower, p.TotalPower)
require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)*(nSectors-1))) 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 := &minerActor.DisputeWindowedPoStParams{
Deadline: evilSectorLoc.Deadline,
PoStIndex: 0,
}
enc, aerr := actors.SerializeParams(params)
require.NoError(t, aerr)
msg := &types.Message{
To: evilMinerAddr,
Method: minerActor.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())
}
// 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 := &minerActor.DeclareFaultsRecoveredParams{
Recoveries: []minerActor.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: minerActor.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 := &minerActor.SubmitWindowedPoStParams{
ChainCommitEpoch: commEpoch,
ChainCommitRand: commRand,
Deadline: dlIdx,
Partitions: []minerActor.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: minerActor.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
}
func TestWindowPostDisputeFails(t *testing.T, b APIBuilder, blocktime time.Duration) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV3At(2)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
{
addrinfo, err := client.NetAddrsListen(ctx)
if err != nil {
t.Fatal(err)
}
if err := miner.NetConnect(ctx, addrinfo); err != nil {
t.Fatal(err)
}
}
defaultFrom, err := client.WalletDefaultAddress(ctx)
require.NoError(t, err)
maddr, err := miner.ActorAddress(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 := miner.MineOne(ctx, MineNext); err != nil {
if ctx.Err() != nil {
// context was canceled, ignore the error.
return
}
t.Error(err)
}
}
}()
defer func() {
cancel()
<-done
}()
pledgeSectors(t, ctx, miner, 10, 0, nil)
di, err := client.StateMinerProvingDeadline(ctx, maddr, 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)
}
ssz, err := miner.ActorSectorSize(ctx, maddr)
require.NoError(t, err)
expectedPower := types.NewInt(uint64(ssz) * (GenesisPreseals + 10))
p, err := client.StateMinerPower(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
// make sure it has gained power.
require.Equal(t, p.MinerPower.RawBytePower, expectedPower)
// Wait until a proof has been submitted.
var targetDeadline uint64
waitForProof:
for {
deadlines, err := client.StateMinerDeadlines(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
for dlIdx, dl := range deadlines {
nonEmpty, err := dl.PostSubmissions.IsEmpty()
require.NoError(t, err)
if nonEmpty {
targetDeadline = uint64(dlIdx)
break waitForProof
}
}
build.Clock.Sleep(blocktime)
}
for {
di, err := client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK)
require.NoError(t, err)
// wait until the deadline finishes.
if di.Index == ((targetDeadline + 1) % di.WPoStPeriodDeadlines) {
break
}
build.Clock.Sleep(blocktime)
}
// Try to object to the proof. This should fail.
{
params := &minerActor.DisputeWindowedPoStParams{
Deadline: targetDeadline,
PoStIndex: 0,
}
enc, aerr := actors.SerializeParams(params)
require.NoError(t, aerr)
msg := &types.Message{
To: maddr,
Method: minerActor.Methods.DisputeWindowedPoSt,
Params: enc,
Value: types.NewInt(0),
From: defaultFrom,
}
_, err := client.MpoolPushMessage(ctx, msg, nil)
require.Error(t, err)
require.Contains(t, err.Error(), "failed to dispute valid post (RetCode=16)")
}
}

View File

@ -27,6 +27,8 @@ const UpgradePersianHeight = 25
const UpgradeOrangeHeight = 27 const UpgradeOrangeHeight = 27
const UpgradeClausHeight = 30 const UpgradeClausHeight = 30
const UpgradeActorsV3Height = 35
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet, 0: DrandMainnet,
} }

View File

@ -44,6 +44,9 @@ const UpgradeClausHeight = 161386
// 2021-01-17T19:00:00Z // 2021-01-17T19:00:00Z
const UpgradeOrangeHeight = 250666 const UpgradeOrangeHeight = 250666
// TODO
const UpgradeActorsV3Height = 99999999
func init() { func init() {
policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 30)) policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 30))
policy.SetSupportedProofTypes( policy.SetSupportedProofTypes(

View File

@ -50,6 +50,9 @@ const UpgradeOrangeHeight = 336458
// 2020-12-22T02:00:00Z // 2020-12-22T02:00:00Z
const UpgradeClausHeight = 343200 const UpgradeClausHeight = 343200
// TODO
const UpgradeActorsV3Height = 999999999
func init() { func init() {
policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40)) policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40))

View File

@ -90,8 +90,9 @@ var (
UpgradeKumquatHeight abi.ChainEpoch = -6 UpgradeKumquatHeight abi.ChainEpoch = -6
UpgradeCalicoHeight abi.ChainEpoch = -7 UpgradeCalicoHeight abi.ChainEpoch = -7
UpgradePersianHeight abi.ChainEpoch = -8 UpgradePersianHeight abi.ChainEpoch = -8
UpgradeClausHeight abi.ChainEpoch = -9 UpgradeOrangeHeight abi.ChainEpoch = -9
UpgradeOrangeHeight abi.ChainEpoch = -10 UpgradeClausHeight abi.ChainEpoch = -10
UpgradeActorsV3Height abi.ChainEpoch = -11
DrandSchedule = map[abi.ChainEpoch]DrandEnum{ DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet, 0: DrandMainnet,

View File

@ -2,16 +2,9 @@ package adt
import ( import (
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor" "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 { type Map interface {
@ -24,26 +17,6 @@ type Map interface {
ForEach(v cbor.Unmarshaler, fn func(key string) error) error 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 { type Array interface {
Root() (cid.Cid, error) Root() (cid.Cid, error)
@ -54,23 +27,3 @@ type Array interface {
ForEach(v cbor.Unmarshaler, fn func(idx int64) error) error 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)
}

View File

@ -13,6 +13,7 @@ import (
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
) )
func init() { func init() {
@ -22,9 +23,12 @@ func init() {
builtin.RegisterActorState(builtin2.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin2.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) 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) { func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code { switch act.Code {
@ -32,6 +36,8 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
return load0(store, act.Head) return load0(store, act.Head)
case builtin2.AccountActorCodeID: case builtin2.AccountActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.AccountActorCodeID:
return load3(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

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

View File

@ -2,12 +2,12 @@ package builtin
import ( import (
"github.com/filecoin-project/go-address" "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" "github.com/ipfs/go-cid"
"golang.org/x/xerrors" "golang.org/x/xerrors"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" 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/abi"
"github.com/filecoin-project/go-state-types/cbor" "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/actors/adt"
"github.com/filecoin-project/lotus/chain/types" "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" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof" proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof"
smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing"
) )
var SystemActorAddr = builtin0.SystemActorAddr var SystemActorAddr = builtin0.SystemActorAddr
@ -38,11 +41,12 @@ const (
) )
const ( const (
MethodSend = builtin2.MethodSend MethodSend = builtin3.MethodSend
MethodConstructor = builtin2.MethodConstructor 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 SectorInfo = proof0.SectorInfo
type PoStProof = proof0.PoStProof type PoStProof = proof0.PoStProof
type FilterEstimate = smoothing0.FilterEstimate type FilterEstimate = smoothing0.FilterEstimate
@ -51,13 +55,17 @@ func FromV0FilterEstimate(v0 smoothing0.FilterEstimate) FilterEstimate {
return (FilterEstimate)(v0) 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 { func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower {
return miner0.QAPowerForWeight(size, duration, dealWeight, verifiedWeight) return miner0.QAPowerForWeight(size, duration, dealWeight, verifiedWeight)
} }
func FromV2FilterEstimate(v1 smoothing2.FilterEstimate) FilterEstimate { func FromV2FilterEstimate(v2 smoothing2.FilterEstimate) FilterEstimate {
return (FilterEstimate)(v1) return (FilterEstimate)(v2)
}
func FromV3FilterEstimate(v3 smoothing3.FilterEstimate) FilterEstimate {
return (FilterEstimate)(v3)
} }
type ActorStateLoader func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) 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) return builtin0.ActorNameByCode(c)
case builtin2.IsBuiltinActor(c): case builtin2.IsBuiltinActor(c):
return builtin2.ActorNameByCode(c) return builtin2.ActorNameByCode(c)
case builtin3.IsBuiltinActor(c):
return builtin3.ActorNameByCode(c)
default: default:
return "<unknown>" return "<unknown>"
} }
} }
func IsBuiltinActor(c cid.Cid) bool { 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 { 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 { 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 { 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 { 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 { func makeAddress(addr string) address.Address {

View File

@ -1,10 +1,10 @@
package cron package cron
import ( import (
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
) )
var ( var (
Address = builtin2.CronActorAddr Address = builtin3.CronActorAddr
Methods = builtin2.MethodsCron Methods = builtin3.MethodsCron
) )

View File

@ -15,6 +15,7 @@ import (
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
) )
func init() { func init() {
@ -24,11 +25,14 @@ func init() {
builtin.RegisterActorState(builtin2.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin2.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) return load2(store, root)
}) })
builtin.RegisterActorState(builtin3.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
} }
var ( var (
Address = builtin2.InitActorAddr Address = builtin3.InitActorAddr
Methods = builtin2.MethodsInit Methods = builtin3.MethodsInit
) )
func Load(store adt.Store, act *types.Actor) (State, error) { 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) return load0(store, act.Head)
case builtin2.InitActorCodeID: case builtin2.InitActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.InitActorCodeID:
return load3(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

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

View File

@ -12,6 +12,7 @@ import (
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
builtin2 "github.com/filecoin-project/specs-actors/v2/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/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin" "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) { builtin.RegisterActorState(builtin2.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) return load2(store, root)
}) })
builtin.RegisterActorState(builtin3.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
} }
var ( var (
Address = builtin2.StorageMarketActorAddr Address = builtin3.StorageMarketActorAddr
Methods = builtin2.MethodsMarket Methods = builtin3.MethodsMarket
) )
func Load(store adt.Store, act *types.Actor) (st State, err error) { 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) return load0(store, act.Head)
case builtin2.StorageMarketActorCodeID: case builtin2.StorageMarketActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.StorageMarketActorCodeID:
return load3(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

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

View File

@ -2,6 +2,7 @@ package miner
import ( import (
"github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/network"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
@ -21,6 +22,8 @@ import (
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" 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() { func init() {
@ -30,11 +33,14 @@ func init() {
builtin.RegisterActorState(builtin2.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin2.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) 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 WPoStProvingPeriod = miner0.WPoStProvingPeriod
var WPoStPeriodDeadlines = miner0.WPoStPeriodDeadlines var WPoStPeriodDeadlines = miner0.WPoStPeriodDeadlines
var WPoStChallengeWindow = miner0.WPoStChallengeWindow 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) return load0(store, act.Head)
case builtin2.StorageMinerActorCodeID: case builtin2.StorageMinerActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.StorageMinerActorCodeID:
return load3(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }
@ -96,9 +104,10 @@ type State interface {
type Deadline interface { type Deadline interface {
LoadPartition(idx uint64) (Partition, error) LoadPartition(idx uint64) (Partition, error)
ForEachPartition(cb func(idx uint64, part Partition) error) error ForEachPartition(cb func(idx uint64, part Partition) error) error
PostSubmissions() (bitfield.BitField, error) PartitionsPoSted() (bitfield.BitField, error)
PartitionsChanged(Deadline) (bool, error) PartitionsChanged(Deadline) (bool, error)
DisputableProofCount() (uint64, error)
} }
type Partition interface { type Partition interface {
@ -142,6 +151,60 @@ type DeclareFaultsParams = miner0.DeclareFaultsParams
type DeclareFaultsRecoveredParams = miner0.DeclareFaultsRecoveredParams type DeclareFaultsRecoveredParams = miner0.DeclareFaultsRecoveredParams
type SubmitWindowedPoStParams = miner0.SubmitWindowedPoStParams type SubmitWindowedPoStParams = miner0.SubmitWindowedPoStParams
type ProveCommitSectorParams = miner0.ProveCommitSectorParams 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 { type MinerInfo struct {
Owner address.Address // Must be an ID-address. Owner address.Address // Must be an ID-address.
@ -151,7 +214,7 @@ type MinerInfo struct {
WorkerChangeEpoch abi.ChainEpoch WorkerChangeEpoch abi.ChainEpoch
PeerId *peer.ID PeerId *peer.ID
Multiaddrs []abi.Multiaddrs Multiaddrs []abi.Multiaddrs
SealProofType abi.RegisteredSealProof WindowPoStProofType abi.RegisteredPoStProof
SectorSize abi.SectorSize SectorSize abi.SectorSize
WindowPoStPartitionSectors uint64 WindowPoStPartitionSectors uint64
ConsensusFaultElapsed abi.ChainEpoch ConsensusFaultElapsed abi.ChainEpoch

View File

@ -297,6 +297,11 @@ func (s *state0) Info() (MinerInfo, error) {
pid = &peerID pid = &peerID
} }
wpp, err := info.SealProofType.RegisteredWindowPoStProof()
if err != nil {
return MinerInfo{}, err
}
mi := MinerInfo{ mi := MinerInfo{
Owner: info.Owner, Owner: info.Owner,
Worker: info.Worker, Worker: info.Worker,
@ -307,7 +312,7 @@ func (s *state0) Info() (MinerInfo, error) {
PeerId: pid, PeerId: pid,
Multiaddrs: info.Multiaddrs, Multiaddrs: info.Multiaddrs,
SealProofType: info.SealProofType, WindowPoStProofType: wpp,
SectorSize: info.SectorSize, SectorSize: info.SectorSize,
WindowPoStPartitionSectors: info.WindowPoStPartitionSectors, WindowPoStPartitionSectors: info.WindowPoStPartitionSectors,
ConsensusFaultElapsed: -1, ConsensusFaultElapsed: -1,
@ -382,10 +387,15 @@ func (d *deadline0) PartitionsChanged(other Deadline) (bool, error) {
return !d.Deadline.Partitions.Equals(other0.Deadline.Partitions), nil 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 return d.Deadline.PostSubmissions, nil
} }
func (d *deadline0) DisputableProofCount() (uint64, error) {
// field doesn't exist until v3
return 0, nil
}
func (p *partition0) AllSectors() (bitfield.BitField, error) { func (p *partition0) AllSectors() (bitfield.BitField, error) {
return p.Partition.Sectors, nil return p.Partition.Sectors, nil
} }

View File

@ -296,6 +296,11 @@ func (s *state2) Info() (MinerInfo, error) {
pid = &peerID pid = &peerID
} }
wpp, err := info.SealProofType.RegisteredWindowPoStProof()
if err != nil {
return MinerInfo{}, err
}
mi := MinerInfo{ mi := MinerInfo{
Owner: info.Owner, Owner: info.Owner,
Worker: info.Worker, Worker: info.Worker,
@ -306,7 +311,7 @@ func (s *state2) Info() (MinerInfo, error) {
PeerId: pid, PeerId: pid,
Multiaddrs: info.Multiaddrs, Multiaddrs: info.Multiaddrs,
SealProofType: info.SealProofType, WindowPoStProofType: wpp,
SectorSize: info.SectorSize, SectorSize: info.SectorSize,
WindowPoStPartitionSectors: info.WindowPoStPartitionSectors, WindowPoStPartitionSectors: info.WindowPoStPartitionSectors,
ConsensusFaultElapsed: info.ConsensusFaultElapsed, ConsensusFaultElapsed: info.ConsensusFaultElapsed,
@ -381,10 +386,15 @@ func (d *deadline2) PartitionsChanged(other Deadline) (bool, error) {
return !d.Deadline.Partitions.Equals(other2.Deadline.Partitions), nil 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 return d.Deadline.PostSubmissions, nil
} }
func (d *deadline2) DisputableProofCount() (uint64, error) {
// field doesn't exist until v3
return 0, nil
}
func (p *partition2) AllSectors() (bitfield.BitField, error) { func (p *partition2) AllSectors() (bitfield.BitField, error) {
return p.Partition.Sectors, nil return p.Partition.Sectors, nil
} }

View File

@ -0,0 +1,434 @@
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 (d *deadline3) DisputableProofCount() (uint64, error) {
ops, err := d.OptimisticProofsSnapshotArray(d.store)
if err != nil {
return 0, err
}
return ops.Length(), 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,
}
}

View File

@ -9,14 +9,14 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
multisig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" multisig3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
) )
var Methods = builtin2.MethodsMultisig var Methods = builtin3.MethodsMultisig
func Message(version actors.Version, from address.Address) MessageBuilder { func Message(version actors.Version, from address.Address) MessageBuilder {
switch version { switch version {
@ -24,6 +24,8 @@ func Message(version actors.Version, from address.Address) MessageBuilder {
return message0{from} return message0{from}
case actors.Version2: case actors.Version2:
return message2{message0{from}} return message2{message0{from}}
case actors.Version3:
return message3{message0{from}}
default: default:
panic(fmt.Sprintf("unsupported actors version: %d", version)) panic(fmt.Sprintf("unsupported actors version: %d", version))
} }
@ -47,11 +49,11 @@ type MessageBuilder interface {
} }
// this type is the same between v0 and v2 // this type is the same between v0 and v2
type ProposalHashData = multisig2.ProposalHashData type ProposalHashData = multisig3.ProposalHashData
type ProposeReturn = multisig2.ProposeReturn type ProposeReturn = multisig3.ProposeReturn
func txnParams(id uint64, data *ProposalHashData) ([]byte, error) { 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 != nil {
if data.Requester.Protocol() != address.ID { if data.Requester.Protocol() != address.ID {
return nil, xerrors.Errorf("proposer address must be an ID address, was %s", data.Requester) return nil, xerrors.Errorf("proposer address must be an ID address, was %s", data.Requester)

View File

@ -0,0 +1,71 @@
package multisig
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
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
}

View File

@ -12,6 +12,7 @@ import (
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
builtin2 "github.com/filecoin-project/specs-actors/v2/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/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin" "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) { builtin.RegisterActorState(builtin2.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) 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) { 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) return load0(store, act.Head)
case builtin2.MultisigActorCodeID: case builtin2.MultisigActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.MultisigActorCodeID:
return load3(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

@ -13,8 +13,8 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" 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" 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) var _ State = (*state0)(nil)

View File

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

View File

@ -8,10 +8,10 @@ import (
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types" "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 { func Message(version actors.Version, from address.Address) MessageBuilder {
switch version { switch version {
@ -19,6 +19,8 @@ func Message(version actors.Version, from address.Address) MessageBuilder {
return message0{from} return message0{from}
case actors.Version2: case actors.Version2:
return message2{from} return message2{from}
case actors.Version3:
return message3{from}
default: default:
panic(fmt.Sprintf("unsupported actors version: %d", version)) panic(fmt.Sprintf("unsupported actors version: %d", version))
} }

View File

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

View File

@ -15,6 +15,7 @@ import (
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych" paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
builtin2 "github.com/filecoin-project/specs-actors/v2/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/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin" "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) { builtin.RegisterActorState(builtin2.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) 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 // 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) return load0(store, act.Head)
case builtin2.PaymentChannelActorCodeID: case builtin2.PaymentChannelActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.PaymentChannelActorCodeID:
return load3(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

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

View File

@ -16,6 +16,7 @@ import (
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
) )
func init() { func init() {
@ -25,11 +26,14 @@ func init() {
builtin.RegisterActorState(builtin2.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin2.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) return load2(store, root)
}) })
builtin.RegisterActorState(builtin3.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
} }
var ( var (
Address = builtin2.StoragePowerActorAddr Address = builtin3.StoragePowerActorAddr
Methods = builtin2.MethodsPower Methods = builtin3.MethodsPower
) )
func Load(store adt.Store, act *types.Actor) (st State, err error) { 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) return load0(store, act.Head)
case builtin2.StoragePowerActorCodeID: case builtin2.StoragePowerActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.StoragePowerActorCodeID:
return load3(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

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

View File

@ -9,6 +9,7 @@ import (
"github.com/filecoin-project/go-state-types/cbor" "github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/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/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin" "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) { builtin.RegisterActorState(builtin2.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) return load2(store, root)
}) })
builtin.RegisterActorState(builtin3.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
} }
var ( var (
Address = builtin2.RewardActorAddr Address = builtin3.RewardActorAddr
Methods = builtin2.MethodsReward Methods = builtin3.MethodsReward
) )
func Load(store adt.Store, act *types.Actor) (st State, err error) { 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) return load0(store, act.Head)
case builtin2.RewardActorCodeID: case builtin2.RewardActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.RewardActorCodeID:
return load3(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

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

View File

@ -6,16 +6,21 @@ import (
"github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors" "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 { if addr.Protocol() != address.ID {
return false, big.Zero(), xerrors.Errorf("can only look up ID addresses") return false, big.Zero(), xerrors.Errorf("can only look up ID addresses")
} }
vh, err := root()
vh, err := adt.AsMap(store, root, ver)
if err != nil { if err != nil {
return false, big.Zero(), xerrors.Errorf("loading verifreg: %w", err) 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 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 { // Assumes that the bitwidth for v3 HAMTs is the DefaultHamtBitwidth
vh, err := adt.AsMap(store, root, ver) 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 { if err != nil {
return xerrors.Errorf("loading verified clients: %w", err) return xerrors.Errorf("loading verified clients: %w", err)
} }

View File

@ -9,6 +9,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg" verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
) )
var _ State = (*state0)(nil) 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) { 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) { 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 { 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 { 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)
} }

View File

@ -9,6 +9,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg" 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) 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) { 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) { 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 { 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 { 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)
} }

View File

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

View File

@ -3,6 +3,7 @@ package verifreg
import ( import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -22,11 +23,14 @@ func init() {
builtin.RegisterActorState(builtin2.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { builtin.RegisterActorState(builtin2.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load2(store, root) return load2(store, root)
}) })
builtin.RegisterActorState(builtin3.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
} }
var ( var (
Address = builtin2.VerifiedRegistryActorAddr Address = builtin3.VerifiedRegistryActorAddr
Methods = builtin2.MethodsVerifiedRegistry Methods = builtin3.MethodsVerifiedRegistry
) )
func Load(store adt.Store, act *types.Actor) (State, error) { 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) return load0(store, act.Head)
case builtin2.VerifiedRegistryActorCodeID: case builtin2.VerifiedRegistryActorCodeID:
return load2(store, act.Head) return load2(store, act.Head)
case builtin3.VerifiedRegistryActorCodeID:
return load3(store, act.Head)
} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code) return nil, xerrors.Errorf("unknown actor code %s", act.Code)
} }

View File

@ -6,21 +6,28 @@ import (
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power" power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg" verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market"
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" 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" 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 ( const (
ChainFinality = miner0.ChainFinality ChainFinality = miner3.ChainFinality
SealRandomnessLookback = ChainFinality SealRandomnessLookback = ChainFinality
PaychSettleDelay = paych2.SettleDelay PaychSettleDelay = paych3.SettleDelay
) )
// SetSupportedProofTypes sets supported proof types, across all actor versions. // 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.PreCommitSealProofTypesV7 = make(map[abi.RegisteredSealProof]struct{}, len(types)*2)
miner2.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types)) 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...) AddSupportedProofTypes(types...)
} }
@ -49,6 +60,13 @@ func AddSupportedProofTypes(types ...abi.RegisteredSealProof) {
miner2.PreCommitSealProofTypesV7[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{} miner2.PreCommitSealProofTypesV7[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
miner2.PreCommitSealProofTypesV8[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. // Set for all miner versions.
miner0.PreCommitChallengeDelay = delay miner0.PreCommitChallengeDelay = delay
miner2.PreCommitChallengeDelay = delay miner2.PreCommitChallengeDelay = delay
miner3.PreCommitChallengeDelay = delay
} }
// TODO: this function shouldn't really exist. Instead, the API should expose the precommit 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 { for _, policy := range builtin2.SealProofPolicies {
policy.ConsensusMinerMinPower = p policy.ConsensusMinerMinPower = p
} }
for _, policy := range builtin3.PoStProofPolicies {
policy.ConsensusMinerMinPower = p
}
} }
// SetMinVerifiedDealSize sets the minimum size of a verified deal. This should // 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) { func SetMinVerifiedDealSize(size abi.StoragePower) {
verifreg0.MinVerifiedDealSize = size verifreg0.MinVerifiedDealSize = size
verifreg2.MinVerifiedDealSize = size verifreg2.MinVerifiedDealSize = size
verifreg3.MinVerifiedDealSize = size
} }
func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) abi.ChainEpoch { 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] return miner0.MaxSealDuration[t]
case actors.Version2: case actors.Version2:
return miner2.MaxProveCommitDuration[t] return miner2.MaxProveCommitDuration[t]
case actors.Version3:
return miner3.MaxProveCommitDuration[t]
default: default:
panic("unsupported actors version") panic("unsupported actors version")
} }
@ -103,6 +129,8 @@ func DealProviderCollateralBounds(
return market0.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil, nwVer) return market0.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil, nwVer)
case actors.Version2: case actors.Version2:
return market2.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil) return market2.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil)
case actors.Version3:
return market3.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil)
default: default:
panic("unsupported network version") panic("unsupported network version")
} }
@ -116,6 +144,12 @@ func SetWPoStChallengeWindow(period abi.ChainEpoch) {
miner2.WPoStChallengeWindow = period miner2.WPoStChallengeWindow = period
miner2.WPoStProvingPeriod = period * abi.ChainEpoch(miner2.WPoStPeriodDeadlines) 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 { 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. // TODO: we'll probably need to abstract over this better in the future.
func GetMaxPoStPartitions(p abi.RegisteredPoStProof) (int, error) { func GetMaxPoStPartitions(p abi.RegisteredPoStProof) (int, error) {
sectorsPerPart, err := builtin2.PoStProofWindowPoStPartitionSectors(p) sectorsPerPart, err := builtin3.PoStProofWindowPoStPartitionSectors(p)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return int(miner2.AddressedSectorsMax / sectorsPerPart), nil return int(miner3.AddressedSectorsMax / sectorsPerPart), nil
} }
func GetDefaultSectorSize() abi.SectorSize { func GetDefaultSectorSize() abi.SectorSize {
// supported sector sizes are the same across versions. // supported sector sizes are the same across versions.
szs := make([]abi.SectorSize, 0, len(miner2.PreCommitSealProofTypesV8)) szs := make([]abi.SectorSize, 0, len(miner3.PreCommitSealProofTypesV8))
for spt := range miner2.PreCommitSealProofTypesV8 { for spt := range miner3.PreCommitSealProofTypesV8 {
ss, err := spt.SectorSize() ss, err := spt.SectorSize()
if err != nil { if err != nil {
panic(err) panic(err)

View File

@ -11,6 +11,7 @@ type Version int
const ( const (
Version0 Version = 0 Version0 Version = 0
Version2 Version = 2 Version2 Version = 2
Version3 Version = 3
) )
// Converts a network version into an actors adt version. // Converts a network version into an actors adt version.
@ -20,6 +21,8 @@ func VersionForNetwork(version network.Version) Version {
return Version0 return Version0
case network.Version4, network.Version5, network.Version6, network.Version7, network.Version8, network.Version9: case network.Version4, network.Version5, network.Version6, network.Version7, network.Version8, network.Version9:
return Version2 return Version2
case network.Version10:
return Version3
default: default:
panic(fmt.Sprintf("unsupported network version %d", version)) panic(fmt.Sprintf("unsupported network version %d", version))
} }

View File

@ -20,6 +20,10 @@ import (
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types" "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") var log = logging.Logger("statetree")
@ -144,23 +148,12 @@ func VersionForNetwork(ver network.Version) types.StateTreeVersion {
return types.StateTreeVersion1 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) { func NewStateTree(cst cbor.IpldStore, ver types.StateTreeVersion) (*StateTree, error) {
var info cid.Cid var info cid.Cid
switch ver { switch ver {
case types.StateTreeVersion0: case types.StateTreeVersion0:
// info is undefined // info is undefined
case types.StateTreeVersion1: case types.StateTreeVersion1, types.StateTreeVersion2:
var err error var err error
info, err = cst.Put(context.TODO(), new(types.StateInfo0)) info, err = cst.Put(context.TODO(), new(types.StateInfo0))
if err != nil { if err != nil {
@ -169,13 +162,34 @@ func NewStateTree(cst cbor.IpldStore, ver types.StateTreeVersion) (*StateTree, e
default: default:
return nil, xerrors.Errorf("unsupported state tree version: %d", ver) return nil, xerrors.Errorf("unsupported state tree version: %d", ver)
} }
root, err := adt.NewMap(adt.WrapStore(context.TODO(), cst), adtForSTVersion(ver))
if err != nil { store := adt.WrapStore(context.TODO(), cst)
return nil, err 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{ s := &StateTree{
root: root, root: hamt,
info: info, info: info,
version: ver, version: ver,
Store: cst, Store: cst,
@ -194,30 +208,49 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
root.Version = types.StateTreeVersion0 root.Version = types.StateTreeVersion0
} }
switch root.Version { store := adt.WrapStore(context.TODO(), cst)
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
}
s := &StateTree{ var (
root: nd, hamt adt.Map
info: root.Info, err error
version: root.Version, )
Store: cst, switch root.Version {
snaps: newStateSnaps(), 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: default:
return nil, xerrors.Errorf("unsupported state tree version: %d", root.Version) 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 { func (st *StateTree) SetActor(addr address.Address, act *types.Actor) error {

View File

@ -4,7 +4,8 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/binary" "encoding/binary"
"math"
"github.com/filecoin-project/go-state-types/rt"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
@ -29,6 +30,7 @@ import (
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" 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/nv4"
"github.com/filecoin-project/specs-actors/v2/actors/migration/nv7" "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" "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@ -52,6 +54,21 @@ type Upgrade struct {
type UpgradeSchedule []Upgrade 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 { func DefaultUpgradeSchedule() UpgradeSchedule {
var us UpgradeSchedule var us UpgradeSchedule
@ -100,32 +117,13 @@ func DefaultUpgradeSchedule() UpgradeSchedule {
Height: build.UpgradeOrangeHeight, Height: build.UpgradeOrangeHeight,
Network: network.Version9, Network: network.Version9,
Migration: nil, 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 { for _, u := range updates {
if u.Height < 0 { if u.Height < 0 {
// upgrade disabled // upgrade disabled
@ -704,6 +702,73 @@ func UpgradeCalico(ctx context.Context, sm *StateManager, cb ExecCallback, root
return newRoot, nil 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 { func setNetworkName(ctx context.Context, store adt.Store, tree *state.StateTree, name string) error {
ia, err := tree.GetActor(builtin0.InitActorAddr) ia, err := tree.GetActor(builtin0.InitActorAddr)
if err != nil { if err != nil {

View File

@ -21,6 +21,9 @@ import (
// Used for genesis. // Used for genesis.
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" 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/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
@ -42,6 +45,7 @@ import (
) )
const LookbackNoLimit = abi.ChainEpoch(-1) const LookbackNoLimit = abi.ChainEpoch(-1)
const ReceiptAmtBitwidth = 3
var log = logging.Logger("statemgr") 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 return cid.Cid{}, cid.Cid{}, err
} }
// XXX: Is the height correct? Or should it be epoch-1? rectarr := blockadt.MakeEmptyArray(sm.cs.Store(ctx))
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)
}
for i, receipt := range receipts { for i, receipt := range receipts {
if err := rectarr.Set(uint64(i), receipt); err != nil { if err := rectarr.Set(uint64(i), receipt); err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to build receipts amt: %w", err) return cid.Undef, cid.Undef, xerrors.Errorf("failed to build receipts amt: %w", err)

View File

@ -25,6 +25,7 @@ import (
exported0 "github.com/filecoin-project/specs-actors/actors/builtin/exported" exported0 "github.com/filecoin-project/specs-actors/actors/builtin/exported"
exported2 "github.com/filecoin-project/specs-actors/v2/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/api"
"github.com/filecoin-project/lotus/chain/actors/builtin" "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) 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) mid, err := address.IDFromAddress(maddr)
if err != nil { if err != nil {
return nil, xerrors.Errorf("getting miner ID: %w", err) 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 { if err != nil {
return nil, xerrors.Errorf("generating winning post challenges: %w", err) return nil, xerrors.Errorf("generating winning post challenges: %w", err)
} }
@ -560,6 +561,7 @@ func init() {
var actors []rt.VMActor var actors []rt.VMActor
actors = append(actors, exported0.BuiltinActors()...) actors = append(actors, exported0.BuiltinActors()...)
actors = append(actors, exported2.BuiltinActors()...) actors = append(actors, exported2.BuiltinActors()...)
actors = append(actors, exported3.BuiltinActors()...)
for _, actor := range actors { for _, actor := range actors {
exports := actor.Exports() exports := actor.Exports()

View File

@ -150,8 +150,11 @@ func TestSyncManagerEdgeCase(t *testing.T) {
t.Fatalf("Expected tipset %s to sync, but got %s", e1, last) t.Fatalf("Expected tipset %s to sync, but got %s", e1, last)
} }
if len(sm.state) != 0 { sm.mx.Lock()
t.Errorf("active syncs expected empty but got: %d", len(sm.state)) activeSyncs := len(sm.state)
sm.mx.Unlock()
if activeSyncs != 0 {
t.Errorf("active syncs expected empty but got: %d", activeSyncs)
} }
}) })
} }

View File

@ -9,8 +9,10 @@ type StateTreeVersion uint64
const ( const (
// StateTreeVersion0 corresponds to actors < v2. // StateTreeVersion0 corresponds to actors < v2.
StateTreeVersion0 StateTreeVersion = iota StateTreeVersion0 StateTreeVersion = iota
// StateTreeVersion1 corresponds to actors >= v2. // StateTreeVersion1 corresponds to actors v2
StateTreeVersion1 StateTreeVersion1
// StateTreeVersion2 corresponds to actors >= v3.
StateTreeVersion2
) )
type StateRoot struct { type StateRoot struct {

View File

@ -17,6 +17,7 @@ import (
exported0 "github.com/filecoin-project/specs-actors/actors/builtin/exported" exported0 "github.com/filecoin-project/specs-actors/actors/builtin/exported"
exported2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/exported" exported2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/exported"
vmr "github.com/filecoin-project/specs-actors/v2/actors/runtime" 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/abi"
"github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/exitcode"
@ -62,6 +63,7 @@ func NewActorRegistry() *ActorRegistry {
// add builtInCode using: register(cid, singleton) // add builtInCode using: register(cid, singleton)
inv.Register(ActorsVersionPredicate(actors.Version0), exported0.BuiltinActors()...) inv.Register(ActorsVersionPredicate(actors.Version0), exported0.BuiltinActors()...)
inv.Register(ActorsVersionPredicate(actors.Version2), exported2.BuiltinActors()...) inv.Register(ActorsVersionPredicate(actors.Version2), exported2.BuiltinActors()...)
inv.Register(ActorsVersionPredicate(actors.Version3), exported3.BuiltinActors()...)
return inv return inv
} }

View File

@ -12,6 +12,7 @@ import (
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/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/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/actors/aerrors"
@ -91,6 +92,8 @@ func newAccountActor(ver actors.Version) *types.Actor {
code = builtin0.AccountActorCodeID code = builtin0.AccountActorCodeID
case actors.Version2: case actors.Version2:
code = builtin2.AccountActorCodeID code = builtin2.AccountActorCodeID
case actors.Version3:
code = builtin3.AccountActorCodeID
default: default:
panic("unsupported actors version") panic("unsupported actors version")
} }

View File

@ -58,6 +58,7 @@ var chainCmd = &cli.Command{
chainInspectUsage, chainInspectUsage,
chainDecodeCmd, chainDecodeCmd,
chainEncodeCmd, chainEncodeCmd,
chainDisputeSetCmd,
}, },
} }

429
cli/disputer.go Normal file
View File

@ -0,0 +1,429 @@
package cli
import (
"context"
"fmt"
"strconv"
"time"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner"
"github.com/filecoin-project/go-state-types/big"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/store"
"github.com/urfave/cli/v2"
)
const Confidence = 10
type minerDeadline struct {
miner address.Address
index uint64
}
var chainDisputeSetCmd = &cli.Command{
Name: "disputer",
Usage: "interact with the window post disputer",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "max-fee",
Usage: "Spend up to X FIL per DisputeWindowedPoSt message",
},
&cli.StringFlag{
Name: "from",
Usage: "optionally specify the account to send messages from",
},
},
Subcommands: []*cli.Command{
disputerStartCmd,
disputerMsgCmd,
},
}
var disputerMsgCmd = &cli.Command{
Name: "dispute",
Usage: "Send a specific DisputeWindowedPoSt message",
ArgsUsage: "[minerAddress index postIndex]",
Flags: []cli.Flag{},
Action: func(cctx *cli.Context) error {
if cctx.NArg() != 3 {
fmt.Println("Usage: dispute [minerAddress index postIndex]")
return nil
}
ctx := ReqContext(cctx)
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
toa, err := address.NewFromString(cctx.Args().First())
if err != nil {
return fmt.Errorf("given 'miner' address %q was invalid: %w", cctx.Args().First(), err)
}
deadline, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
if err != nil {
return err
}
postIndex, err := strconv.ParseUint(cctx.Args().Get(2), 10, 64)
if err != nil {
return err
}
fromAddr, err := getSender(ctx, api, cctx.String("from"))
if err != nil {
return err
}
dpp, aerr := actors.SerializeParams(&miner3.DisputeWindowedPoStParams{
Deadline: deadline,
PoStIndex: postIndex,
})
if aerr != nil {
return xerrors.Errorf("failed to serailize params: %w", aerr)
}
dmsg := &types.Message{
To: toa,
From: fromAddr,
Value: big.Zero(),
Method: builtin3.MethodsMiner.DisputeWindowedPoSt,
Params: dpp,
}
rslt, err := api.StateCall(ctx, dmsg, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("failed to simulate dispute: %w", err)
}
if rslt.MsgRct.ExitCode == 0 {
mss, err := getMaxFee(cctx.String("max-fee"))
if err != nil {
return err
}
sm, err := api.MpoolPushMessage(ctx, dmsg, mss)
if err != nil {
return err
}
fmt.Println("dispute message ", sm.Cid())
} else {
fmt.Println("dispute is unsuccessful")
}
return nil
},
}
var disputerStartCmd = &cli.Command{
Name: "start",
Usage: "Start the window post disputer",
ArgsUsage: "[minerAddress]",
Flags: []cli.Flag{
&cli.Uint64Flag{
Name: "start-epoch",
Usage: "only start disputing PoSts after this epoch ",
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
fromAddr, err := getSender(ctx, api, cctx.String("from"))
if err != nil {
return err
}
mss, err := getMaxFee(cctx.String("max-fee"))
if err != nil {
return err
}
startEpoch := abi.ChainEpoch(0)
if cctx.IsSet("height") {
startEpoch = abi.ChainEpoch(cctx.Uint64("height"))
}
fmt.Println("checking sync status")
if err := SyncWait(ctx, api, false); err != nil {
return xerrors.Errorf("sync wait: %w", err)
}
fmt.Println("setting up window post disputer")
// subscribe to head changes and validate the current value
headChanges, err := api.ChainNotify(ctx)
if err != nil {
return err
}
head, ok := <-headChanges
if !ok {
return xerrors.Errorf("Notify stream was invalid")
}
if len(head) != 1 {
return xerrors.Errorf("Notify first entry should have been one item")
}
if head[0].Type != store.HCCurrent {
return xerrors.Errorf("expected current head on Notify stream (got %s)", head[0].Type)
}
lastEpoch := head[0].Val.Height()
lastStatusCheckEpoch := lastEpoch
// build initial deadlineMap
minerList, err := api.StateListMiners(ctx, types.EmptyTSK)
if err != nil {
return err
}
knownMiners := make(map[address.Address]struct{})
deadlineMap := make(map[abi.ChainEpoch][]minerDeadline)
for _, miner := range minerList {
dClose, dl, err := makeMinerDeadline(ctx, api, miner)
if err != nil {
return xerrors.Errorf("making deadline: %w", err)
}
deadlineMap[dClose+Confidence] = append(deadlineMap[dClose+Confidence], *dl)
knownMiners[miner] = struct{}{}
}
// when this fires, check for newly created miners, and purge any "missed" epochs from deadlineMap
statusCheckTicker := time.NewTicker(time.Hour)
defer statusCheckTicker.Stop()
fmt.Println("starting up window post disputer")
applyTsk := func(tsk types.TipSetKey) error {
log.Infof("last checked height: %d", lastEpoch)
dls, ok := deadlineMap[lastEpoch]
delete(deadlineMap, lastEpoch)
if !ok || startEpoch >= lastEpoch {
// no deadlines closed at this epoch - Confidence, or we haven't reached the start cutoff yet
return nil
}
dpmsgs := make([]*types.Message, 0)
// TODO: Parallelizeable
for _, dl := range dls {
fullDeadlines, err := api.StateMinerDeadlines(ctx, dl.miner, tsk)
if err != nil {
return xerrors.Errorf("failed to load deadlines: %w", err)
}
if int(dl.index) >= len(fullDeadlines) {
return xerrors.Errorf("deadline index %d not found in deadlines", dl.index)
}
ms, err := makeDisputeWindowedPosts(ctx, api, dl, fullDeadlines[dl.index].DisputableProofCount, fromAddr)
if err != nil {
return xerrors.Errorf("failed to check for disputes: %w", err)
}
dpmsgs = append(dpmsgs, ms...)
dClose, dl, err := makeMinerDeadline(ctx, api, dl.miner)
if err != nil {
return xerrors.Errorf("making deadline: %w", err)
}
deadlineMap[dClose+Confidence] = append(deadlineMap[dClose+Confidence], *dl)
}
// TODO: Parallelizeable / can be integrated into the previous deadline-iterating for loop
for _, dpmsg := range dpmsgs {
log.Infof("disputing a PoSt from miner %s", dpmsg.To)
m, err := api.MpoolPushMessage(ctx, dpmsg, mss)
if err != nil {
log.Infof("failed to dispute post message: %s", err.Error())
} else {
log.Infof("disputed a PoSt in message: %s", m.Cid())
}
}
return nil
}
disputeLoop := func() error {
select {
case notif, ok := <-headChanges:
if !ok {
return xerrors.Errorf("head change channel errored")
}
for _, val := range notif {
switch val.Type {
case store.HCApply:
for ; lastEpoch <= val.Val.Height(); lastEpoch++ {
err := applyTsk(val.Val.Key())
if err != nil {
return err
}
}
case store.HCRevert:
// do nothing
default:
return xerrors.Errorf("unexpected head change type %s", val.Type)
}
}
case <-statusCheckTicker.C:
log.Infof("Running status check: ")
minerList, err = api.StateListMiners(ctx, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("getting miner list: %w", err)
}
for _, m := range minerList {
_, ok := knownMiners[m]
if !ok {
dClose, dl, err := makeMinerDeadline(ctx, api, m)
if err != nil {
return xerrors.Errorf("making deadline: %w", err)
}
deadlineMap[dClose+Confidence] = append(deadlineMap[dClose+Confidence], *dl)
knownMiners[m] = struct{}{}
}
}
for ; lastStatusCheckEpoch < lastEpoch; lastStatusCheckEpoch++ {
// if an epoch got "skipped" from the deadlineMap somehow, just fry it now instead of letting it sit around forever
_, ok := deadlineMap[lastStatusCheckEpoch]
if ok {
log.Infof("epoch %d was skipped during execution, deleting it from deadlineMap")
delete(deadlineMap, lastStatusCheckEpoch)
}
}
log.Infof("Status check complete")
case <-ctx.Done():
return xerrors.Errorf("context cancelled")
}
return nil
}
for {
err := disputeLoop()
if err != nil {
fmt.Println("disputer shutting down: ", err)
break
}
}
return nil
},
}
// for a given miner, index, and maxPostIndex, tries to dispute posts from 0...postsSnapshotted-1
// returns a list of DisputeWindowedPoSt msgs that are expected to succeed if sent
func makeDisputeWindowedPosts(ctx context.Context, api lapi.FullNode, dl minerDeadline, postsSnapshotted uint64, sender address.Address) ([]*types.Message, error) {
disputes := make([]*types.Message, 0)
for i := uint64(0); i < postsSnapshotted; i++ {
dpp, aerr := actors.SerializeParams(&miner3.DisputeWindowedPoStParams{
Deadline: dl.index,
PoStIndex: i,
})
if aerr != nil {
return nil, xerrors.Errorf("failed to serailize params: %w", aerr)
}
dispute := &types.Message{
To: dl.miner,
From: sender,
Value: big.Zero(),
Method: builtin3.MethodsMiner.DisputeWindowedPoSt,
Params: dpp,
}
rslt, err := api.StateCall(ctx, dispute, types.EmptyTSK)
if err == nil && rslt.MsgRct.ExitCode == 0 {
disputes = append(disputes, dispute)
}
}
return disputes, nil
}
func makeMinerDeadline(ctx context.Context, api lapi.FullNode, mAddr address.Address) (abi.ChainEpoch, *minerDeadline, error) {
dl, err := api.StateMinerProvingDeadline(ctx, mAddr, types.EmptyTSK)
if err != nil {
return -1, nil, xerrors.Errorf("getting proving index list: %w", err)
}
return dl.Close, &minerDeadline{
miner: mAddr,
index: dl.Index,
}, nil
}
func getSender(ctx context.Context, api lapi.FullNode, fromStr string) (address.Address, error) {
if fromStr == "" {
return api.WalletDefaultAddress(ctx)
}
addr, err := address.NewFromString(fromStr)
if err != nil {
return address.Undef, err
}
has, err := api.WalletHas(ctx, addr)
if err != nil {
return address.Undef, err
}
if !has {
return address.Undef, xerrors.Errorf("wallet doesn't contain: %s ", addr)
}
return addr, nil
}
func getMaxFee(maxStr string) (*lapi.MessageSendSpec, error) {
if maxStr != "" {
maxFee, err := types.ParseFIL(maxStr)
if err != nil {
return nil, xerrors.Errorf("parsing max-fee: %w", err)
}
return &lapi.MessageSendSpec{
MaxFee: types.BigInt(maxFee),
}, nil
}
return nil, nil
}

View File

@ -245,7 +245,7 @@ func startNodes(
// Create a gateway server in front of the full node // Create a gateway server in front of the full node
gapiImpl := newGatewayAPI(fullNode, lookbackCap, stateWaitLookbackLimit) gapiImpl := newGatewayAPI(fullNode, lookbackCap, stateWaitLookbackLimit)
_, addr, err := builder.CreateRPCServer(gapiImpl) _, addr, err := builder.CreateRPCServer(t, gapiImpl)
require.NoError(t, err) require.NoError(t, err)
// Create a gateway client API that connects to the gateway server // Create a gateway client API that connects to the gateway server

View File

@ -120,7 +120,7 @@ var datastoreGetCmd = &cli.Command{
}, },
ArgsUsage: "[namespace key]", ArgsUsage: "[namespace key]",
Action: func(cctx *cli.Context) error { 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")) r, err := repo.NewFS(cctx.String("repo"))
if err != nil { if err != nil {

View File

@ -50,7 +50,7 @@ func TestWorkerKeyChange(t *testing.T) {
blocktime := 1 * time.Millisecond 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] client1 := n[0]
client2 := n[1] client2 := n[1]

View File

@ -430,11 +430,6 @@ var provingCheckProvableCmd = &cli.Command{
return err return err
} }
pf, err := info.SealProofType.RegisteredWindowPoStProof()
if err != nil {
return err
}
partitions, err := api.StateMinerPartitions(ctx, addr, dlIdx, types.EmptyTSK) partitions, err := api.StateMinerPartitions(ctx, addr, dlIdx, types.EmptyTSK)
if err != nil { if err != nil {
return err 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 { if err != nil {
return err return err
} }

View File

@ -4028,7 +4028,7 @@ Response:
"WorkerChangeEpoch": 10101, "WorkerChangeEpoch": 10101,
"PeerId": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", "PeerId": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
"Multiaddrs": null, "Multiaddrs": null,
"SealProofType": 8, "WindowPoStProofType": 8,
"SectorSize": 34359738368, "SectorSize": 34359738368,
"WindowPoStPartitionSectors": 42, "WindowPoStPartitionSectors": 42,
"ConsensusFaultElapsed": 10101 "ConsensusFaultElapsed": 10101

View File

@ -475,7 +475,12 @@ func (m *Sealing) currentSealProof(ctx context.Context) (abi.RegisteredSealProof
return 0, err 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 { func (m *Sealing) minerSector(spt abi.RegisteredSealProof, num abi.SectorNumber) storage.SectorRef {

5
go.mod
View File

@ -38,12 +38,13 @@ require (
github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-multistore v0.0.3
github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261 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-statemachine v0.0.0-20200925024713-05bd7c71fbfe
github.com/filecoin-project/go-statestore v0.1.0 github.com/filecoin-project/go-statestore v0.1.0
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b 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 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/specs-storage v0.1.1-0.20201105051918-5188d9774506
github.com/filecoin-project/test-vectors/schema v0.0.5 github.com/filecoin-project/test-vectors/schema v0.0.5
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1

12
go.sum
View File

@ -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.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 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/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 h1:gCtLcjskIPtdg4NfN7gQZSQF9yrBQ7mkT0qCJxzGI2Q=
github.com/filecoin-project/go-bitfield v0.2.0/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM= 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= 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 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 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/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 h1:MTebUawBHLxxY9gDi1WXuGc89TWIDmsgoDqeZSk9KRw=
github.com/filecoin-project/go-jsonrpc v0.1.2/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= 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= 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-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 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-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 h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw=
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= 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= 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.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 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.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.4 h1:NZK2oMCcA71wNsUzDBmLQyRMzcCnX9tDGvwZ53G67j8=
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/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 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/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= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg=

View File

@ -24,6 +24,7 @@ import (
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/builtin/market" "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"
"github.com/filecoin-project/lotus/chain/events/state" "github.com/filecoin-project/lotus/chain/events/state"
"github.com/filecoin-project/lotus/chain/types" "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 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) tsk, err := types.TipSetKeyFromBytes(tok)
if err != nil { if err != nil {
return address.Undef, err return address.Undef, err
} }
mi, err := n.StateMinerInfo(ctx, miner, tsk) mi, err := n.StateMinerInfo(ctx, maddr, tsk)
if err != nil { if err != nil {
return address.Address{}, err return address.Address{}, err
} }
return mi.Worker, nil 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) tsk, err := types.TipSetKeyFromBytes(tok)
if err != nil { if err != nil {
return 0, err return 0, err
} }
mi, err := n.StateMinerInfo(ctx, miner, tsk) mi, err := n.StateMinerInfo(ctx, maddr, tsk)
if err != nil { if err != nil {
return 0, err 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) { func (n *ProviderNodeAdapter) SignBytes(ctx context.Context, signer address.Address, b []byte) (*crypto.Signature, error) {

View File

@ -7,6 +7,8 @@ import (
"io" "io"
"os" "os"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-padreader" "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 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{ result, err := a.SMDealClient.ProposeStorageDeal(ctx, storagemarket.ProposeStorageDealParams{
Addr: params.Wallet, Addr: params.Wallet,
Info: &providerInfo, Info: &providerInfo,
@ -165,7 +177,7 @@ func (a *API) ClientStartDeal(ctx context.Context, params *api.StartDealParams)
EndEpoch: calcDealExpiration(params.MinBlocksDuration, md, dealStart), EndEpoch: calcDealExpiration(params.MinBlocksDuration, md, dealStart),
Price: params.EpochPrice, Price: params.EpochPrice,
Collateral: params.ProviderCollateral, Collateral: params.ProviderCollateral,
Rt: mi.SealProofType, Rt: st,
FastRetrieval: params.FastRetrieval, FastRetrieval: params.FastRetrieval,
VerifiedDeal: params.VerifiedDeal, VerifiedDeal: params.VerifiedDeal,
StoreID: storeID, StoreID: storeID,

View File

@ -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) 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() info, err := mas.Info()
if err != nil { if err != nil {
return miner.MinerInfo{}, err 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 return info, nil
} }
@ -170,13 +165,19 @@ func (a *StateAPI) StateMinerDeadlines(ctx context.Context, m address.Address, t
out := make([]api.Deadline, deadlines) out := make([]api.Deadline, deadlines)
if err := mas.ForEachDeadline(func(i uint64, dl miner.Deadline) error { if err := mas.ForEachDeadline(func(i uint64, dl miner.Deadline) error {
ps, err := dl.PostSubmissions() ps, err := dl.PartitionsPoSted()
if err != nil {
return err
}
l, err := dl.DisputableProofCount()
if err != nil { if err != nil {
return err return err
} }
out[i] = api.Deadline{ out[i] = api.Deadline{
PostSubmissions: ps, PostSubmissions: ps,
DisputableProofCount: l,
} }
return nil return nil
}); err != nil { }); err != nil {

View File

@ -58,6 +58,7 @@ import (
lapi "github.com/filecoin-project/lotus/api" lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin" "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"
"github.com/filecoin-project/lotus/chain/gen/slashfilter" "github.com/filecoin-project/lotus/chain/gen/slashfilter"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -66,7 +67,7 @@ import (
"github.com/filecoin-project/lotus/markets" "github.com/filecoin-project/lotus/markets"
marketevents "github.com/filecoin-project/lotus/markets/loggers" marketevents "github.com/filecoin-project/lotus/markets/loggers"
"github.com/filecoin-project/lotus/markets/retrievaladapter" "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/config"
"github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/node/modules/helpers" "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 { if err != nil {
return 0, err 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 { type sidsc struct {
@ -419,13 +424,13 @@ func StagingGraphsync(mctx helpers.MetricsCtx, lc fx.Lifecycle, ibs dtypes.Stagi
return gs 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) minerAddr, err := minerAddrFromDS(ds)
if err != nil { if err != nil {
return nil, err return nil, err
} }
m := miner.NewMiner(api, epp, minerAddr, sf, j) m := lotusminer.NewMiner(api, epp, minerAddr, sf, j)
lc.Append(fx.Hook{ lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error { OnStart: func(ctx context.Context) error {

View File

@ -198,3 +198,29 @@ func TestPaymentChannels(t *testing.T) {
test.TestPaymentChannels(t, builder.MockSbBuilder, 5*time.Millisecond) 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)
}
func TestWindowPostDisputeFails(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.TestWindowPostDisputeFails(t, builder.MockSbBuilder, 2*time.Millisecond)
}

View File

@ -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) { 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 { 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) require.NoError(t, err)
var stop func()
var full test.TestNode 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) require.NoError(t, err)
t.Cleanup(stop)
full.ListenAddr = ma full.ListenAddr = ma
return full return full
} }
func storerRpc(t *testing.T, nd test.TestStorageNode) test.TestStorageNode { 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) require.NoError(t, err)
var stop func()
var storer test.TestStorageNode 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) require.NoError(t, err)
t.Cleanup(stop)
storer.ListenAddr = ma storer.ListenAddr = ma
storer.MineOne = nd.MineOne storer.MineOne = nd.MineOne
return storer 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 := jsonrpc.NewServer()
rpcServer.Register("Filecoin", handler) rpcServer.Register("Filecoin", handler)
testServ := httptest.NewServer(rpcServer) // todo: close testServ := httptest.NewServer(rpcServer) // todo: close
t.Cleanup(testServ.Close)
t.Cleanup(testServ.CloseClientConnections)
addr := testServ.Listener.Addr() addr := testServ.Listener.Addr()
listenAddr := "ws://" + addr.String() listenAddr := "ws://" + addr.String()

View File

@ -225,18 +225,13 @@ func NewWinningPoStProver(api api.FullNode, prover storage.Prover, verifier ffiw
return nil, xerrors.Errorf("getting sector size: %w", err) return nil, xerrors.Errorf("getting sector size: %w", err)
} }
wpt, err := mi.SealProofType.RegisteredWinningPoStProof()
if err != nil {
return nil, err
}
if build.InsecurePoStValidation { if build.InsecurePoStValidation {
log.Warn("*****************************************************************************") log.Warn("*****************************************************************************")
log.Warn(" Generating fake PoSt proof! You should only see this while running tests! ") log.Warn(" Generating fake PoSt proof! You should only see this while running tests! ")
log.Warn("*****************************************************************************") 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) var _ gen.WinningPoStProver = (*StorageWpp)(nil)

View File

@ -47,18 +47,13 @@ func NewWindowedPoStScheduler(api storageMinerApi, fc config.MinerFeeConfig, as
return nil, xerrors.Errorf("getting sector size: %w", err) return nil, xerrors.Errorf("getting sector size: %w", err)
} }
rt, err := mi.SealProofType.RegisteredWindowPoStProof()
if err != nil {
return nil, err
}
return &WindowPoStScheduler{ return &WindowPoStScheduler{
api: api, api: api,
feeCfg: fc, feeCfg: fc,
addrSel: as, addrSel: as,
prover: sb, prover: sb,
faultTracker: ft, faultTracker: ft,
proofType: rt, proofType: mi.WindowPoStProofType,
partitionSectors: mi.WindowPoStPartitionSectors, partitionSectors: mi.WindowPoStPartitionSectors,
actor: actor, actor: actor,