Merge tag 'v1.8.0' into release/v1.9.0

This commit is contained in:
Łukasz Magiera 2021-04-27 10:30:33 +02:00
commit a24a73bb52
61 changed files with 2377 additions and 81 deletions

View File

@ -130,6 +130,9 @@ jobs:
winpost-test:
type: string
default: "0"
deadline-test:
type: string
default: "0"
test-suite-name:
type: string
default: unit
@ -163,6 +166,7 @@ jobs:
name: go test
environment:
LOTUS_TEST_WINDOW_POST: << parameters.winpost-test >>
LOTUS_TEST_DEADLINE_TOGGLING: << parameters.deadline-test >>
SKIP_CONFORMANCE: "1"
command: |
mkdir -p /tmp/test-reports/<< parameters.test-suite-name >>
@ -204,6 +208,8 @@ jobs:
<<: *test
test-window-post-dispute:
<<: *test
test-deadline-toggling:
<<: *test
test-terminate:
<<: *test
test-conformance:
@ -730,6 +736,11 @@ workflows:
go-test-flags: "-run=TestTerminate"
winpost-test: "1"
test-suite-name: terminate
- test-deadline-toggling:
codecov-upload: true
go-test-flags: "-run=TestDeadlineToggling"
deadline-test: "1"
test-suite-name: deadline-toggling
- test-short:
go-test-flags: "--timeout 10m --short"
test-suite-name: short

View File

@ -67,6 +67,14 @@ This is an optional Lotus release that introduces various improvements to the se
- fix 4857: show help for set-addrs (https://github.com/filecoin-project/lotus/pull/5943)
- fix health report (https://github.com/filecoin-project/lotus/pull/6011)
# 1.8.0 / 2021-04-05
This is a mandatory release of Lotus that upgrades the network to version 12, which introduces various performance improvements to the cron processing of the power actor. The network will upgrade at height 712320, which is 2021-04-29T06:00:00Z.
## Changes
- v4 specs-actors integration, nv12 migration (https://github.com/filecoin-project/lotus/pull/6116)
# 1.6.0 / 2021-04-05
This is a mandatory release of Lotus that upgrades the network to version 11, which implements [FIP-0014](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0014.md). The network will upgrade at height 665280, which is 2021-04-12T22:00:00Z.

View File

@ -17,7 +17,7 @@ import (
func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
for _, height := range []abi.ChainEpoch{
2, // before
-1, // before
162, // while sealing
530, // after upgrade deal
5000, // after
@ -31,7 +31,7 @@ func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) {
func testCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration, upgradeHeight abi.ChainEpoch) {
ctx := context.Background()
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV3At(upgradeHeight)}, OneMiner)
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(upgradeHeight)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]

350
api/test/deadlines.go Normal file
View File

@ -0,0 +1,350 @@
package test
import (
"bytes"
"context"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/require"
"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/big"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-state-types/network"
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/extern/sector-storage/mock"
"github.com/filecoin-project/lotus/node/impl"
)
// TestDeadlineToggling:
// * spins up a v3 network (miner A)
// * creates an inactive miner (miner B)
// * creates another miner, pledges a sector, waits for power (miner C)
//
// * goes through v4 upgrade
// * goes through PP
// * creates minerD, minerE
// * makes sure that miner B/D are inactive, A/C still are
// * pledges sectors on miner B/D
// * precommits a sector on minerE
// * disables post on miner C
// * goes through PP 0.5PP
// * asserts that minerE is active
// * goes through rest of PP (1.5)
// * asserts that miner C loses power
// * asserts that miner B/D is active and has power
// * asserts that minerE is inactive
// * disables post on miner B
// * terminates sectors on miner D
// * goes through another PP
// * asserts that miner B loses power
// * asserts that miner D loses power, is inactive
func TestDeadlineToggling(t *testing.T, b APIBuilder, blocktime time.Duration) {
var upgradeH abi.ChainEpoch = 4000
var provingPeriod abi.ChainEpoch = 2880
const sectorsC, sectorsD, sectersB = 10, 9, 8
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(upgradeH)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
minerA := sn[0]
{
addrinfo, err := client.NetAddrsListen(ctx)
if err != nil {
t.Fatal(err)
}
if err := minerA.NetConnect(ctx, addrinfo); err != nil {
t.Fatal(err)
}
}
defaultFrom, err := client.WalletDefaultAddress(ctx)
require.NoError(t, err)
maddrA, err := minerA.ActorAddress(ctx)
require.NoError(t, err)
build.Clock.Sleep(time.Second)
done := make(chan struct{})
go func() {
defer close(done)
for ctx.Err() == nil {
build.Clock.Sleep(blocktime)
if err := minerA.MineOne(ctx, MineNext); err != nil {
if ctx.Err() != nil {
// context was canceled, ignore the error.
return
}
t.Error(err)
}
}
}()
defer func() {
cancel()
<-done
}()
minerB := n[0].Stb(ctx, t, TestSpt, defaultFrom)
minerC := n[0].Stb(ctx, t, TestSpt, defaultFrom)
maddrB, err := minerB.ActorAddress(ctx)
require.NoError(t, err)
maddrC, err := minerC.ActorAddress(ctx)
require.NoError(t, err)
ssz, err := minerC.ActorSectorSize(ctx, maddrC)
require.NoError(t, err)
// pledge sectors on C, go through a PP, check for power
{
pledgeSectors(t, ctx, minerC, sectorsC, 0, nil)
di, err := client.StateMinerProvingDeadline(ctx, maddrC, types.EmptyTSK)
require.NoError(t, err)
fmt.Printf("Running one proving period (miner C)\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+provingPeriod*2 {
fmt.Printf("Now head.Height = %d\n", head.Height())
break
}
build.Clock.Sleep(blocktime)
}
expectedPower := types.NewInt(uint64(ssz) * sectorsC)
p, err := client.StateMinerPower(ctx, maddrC, types.EmptyTSK)
require.NoError(t, err)
// make sure it has gained power.
require.Equal(t, p.MinerPower.RawBytePower, expectedPower)
}
// go through upgrade + PP
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
if head.Height() > upgradeH+provingPeriod {
fmt.Printf("Now head.Height = %d\n", head.Height())
break
}
build.Clock.Sleep(blocktime)
}
checkMiner := func(ma address.Address, power abi.StoragePower, active bool, tsk types.TipSetKey) {
p, err := client.StateMinerPower(ctx, ma, tsk)
require.NoError(t, err)
// make sure it has the expected power.
require.Equal(t, p.MinerPower.RawBytePower, power)
mact, err := client.StateGetActor(ctx, ma, tsk)
require.NoError(t, err)
mst, err := miner.Load(adt.WrapStore(ctx, cbor.NewCborStore(blockstore.NewAPIBlockstore(client))), mact)
require.NoError(t, err)
act, err := mst.DeadlineCronActive()
require.NoError(t, err)
require.Equal(t, active, act)
}
// check that just after the upgrade minerB was still active
{
uts, err := client.ChainGetTipSetByHeight(ctx, upgradeH+2, types.EmptyTSK)
require.NoError(t, err)
checkMiner(maddrB, types.NewInt(0), true, uts.Key())
}
nv, err := client.StateNetworkVersion(ctx, types.EmptyTSK)
require.NoError(t, err)
require.GreaterOrEqual(t, nv, network.Version12)
minerD := n[0].Stb(ctx, t, TestSpt, defaultFrom)
minerE := n[0].Stb(ctx, t, TestSpt, defaultFrom)
maddrD, err := minerD.ActorAddress(ctx)
require.NoError(t, err)
maddrE, err := minerE.ActorAddress(ctx)
require.NoError(t, err)
// first round of miner checks
checkMiner(maddrA, types.NewInt(uint64(ssz)*GenesisPreseals), true, types.EmptyTSK)
checkMiner(maddrC, types.NewInt(uint64(ssz)*sectorsC), true, types.EmptyTSK)
checkMiner(maddrB, types.NewInt(0), false, types.EmptyTSK)
checkMiner(maddrD, types.NewInt(0), false, types.EmptyTSK)
checkMiner(maddrE, types.NewInt(0), false, types.EmptyTSK)
// pledge sectors on minerB/minerD, stop post on minerC
pledgeSectors(t, ctx, minerB, sectersB, 0, nil)
checkMiner(maddrB, types.NewInt(0), true, types.EmptyTSK)
pledgeSectors(t, ctx, minerD, sectorsD, 0, nil)
checkMiner(maddrD, types.NewInt(0), true, types.EmptyTSK)
minerC.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).Fail()
// precommit a sector on minerE
{
head, err := client.ChainHead(ctx)
require.NoError(t, err)
cr, err := cid.Parse("bagboea4b5abcatlxechwbp7kjpjguna6r6q7ejrhe6mdp3lf34pmswn27pkkiekz")
require.NoError(t, err)
params := &miner.SectorPreCommitInfo{
Expiration: 2880 * 300,
SectorNumber: 22,
SealProof: TestSpt,
SealedCID: cr,
SealRandEpoch: head.Height() - 200,
}
enc := new(bytes.Buffer)
require.NoError(t, params.MarshalCBOR(enc))
m, err := client.MpoolPushMessage(ctx, &types.Message{
To: maddrE,
From: defaultFrom,
Value: types.FromFil(1),
Method: miner.Methods.PreCommitSector,
Params: enc.Bytes(),
}, nil)
require.NoError(t, err)
r, err := client.StateWaitMsg(ctx, m.Cid(), 2)
require.NoError(t, err)
require.Equal(t, exitcode.Ok, r.Receipt.ExitCode)
}
// go through 0.5 PP
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
if head.Height() > upgradeH+provingPeriod+(provingPeriod/2) {
fmt.Printf("Now head.Height = %d\n", head.Height())
break
}
build.Clock.Sleep(blocktime)
}
checkMiner(maddrE, types.NewInt(0), true, types.EmptyTSK)
// go through rest of the PP
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
if head.Height() > upgradeH+(provingPeriod*3) {
fmt.Printf("Now head.Height = %d\n", head.Height())
break
}
build.Clock.Sleep(blocktime)
}
// second round of miner checks
checkMiner(maddrA, types.NewInt(uint64(ssz)*GenesisPreseals), true, types.EmptyTSK)
checkMiner(maddrC, types.NewInt(0), true, types.EmptyTSK)
checkMiner(maddrB, types.NewInt(uint64(ssz)*sectersB), true, types.EmptyTSK)
checkMiner(maddrD, types.NewInt(uint64(ssz)*sectorsD), true, types.EmptyTSK)
checkMiner(maddrE, types.NewInt(0), false, types.EmptyTSK)
// disable post on minerB
minerB.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).Fail()
// terminate sectors on minerD
{
var terminationDeclarationParams []miner2.TerminationDeclaration
secs, err := minerD.SectorsList(ctx)
require.NoError(t, err)
require.Len(t, secs, sectorsD)
for _, sectorNum := range secs {
sectorbit := bitfield.New()
sectorbit.Set(uint64(sectorNum))
loca, err := client.StateSectorPartition(ctx, maddrD, sectorNum, types.EmptyTSK)
require.NoError(t, err)
para := miner2.TerminationDeclaration{
Deadline: loca.Deadline,
Partition: loca.Partition,
Sectors: sectorbit,
}
terminationDeclarationParams = append(terminationDeclarationParams, para)
}
terminateSectorParams := &miner2.TerminateSectorsParams{
Terminations: terminationDeclarationParams,
}
sp, aerr := actors.SerializeParams(terminateSectorParams)
require.NoError(t, aerr)
smsg, err := client.MpoolPushMessage(ctx, &types.Message{
From: defaultFrom,
To: maddrD,
Method: miner.Methods.TerminateSectors,
Value: big.Zero(),
Params: sp,
}, nil)
require.NoError(t, err)
fmt.Println("sent termination message:", smsg.Cid())
r, err := client.StateWaitMsg(ctx, smsg.Cid(), 2)
require.NoError(t, err)
require.Equal(t, exitcode.Ok, r.Receipt.ExitCode)
checkMiner(maddrD, types.NewInt(0), true, r.TipSet)
}
// go through another PP
for {
head, err := client.ChainHead(ctx)
require.NoError(t, err)
if head.Height() > upgradeH+(provingPeriod*5) {
fmt.Printf("Now head.Height = %d\n", head.Height())
break
}
build.Clock.Sleep(blocktime)
}
// third round of miner checks
checkMiner(maddrA, types.NewInt(uint64(ssz)*GenesisPreseals), true, types.EmptyTSK)
checkMiner(maddrC, types.NewInt(0), true, types.EmptyTSK)
checkMiner(maddrB, types.NewInt(0), true, types.EmptyTSK)
checkMiner(maddrD, types.NewInt(0), false, types.EmptyTSK)
}

View File

@ -11,10 +11,13 @@ import (
logging "github.com/ipfs/go-log/v2"
"github.com/filecoin-project/go-state-types/abi"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/lotus/node/impl"
)
@ -199,3 +202,39 @@ func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExpo
fmt.Println("shutting down mining")
<-done
}
func (ts *testSuite) testNonGenesisMiner(t *testing.T) {
ctx := context.Background()
n, sn := ts.makeNodes(t, []FullNodeOpts{
FullNodeWithActorsV4At(-1),
}, []StorageMiner{
{Full: 0, Preseal: PresealGenesis},
})
full, ok := n[0].FullNode.(*impl.FullNodeAPI)
if !ok {
t.Skip("not testing with a full node")
return
}
genesisMiner := sn[0]
bm := NewBlockMiner(ctx, t, genesisMiner, 4*time.Millisecond)
bm.MineBlocks()
t.Cleanup(bm.Stop)
gaa, err := genesisMiner.ActorAddress(ctx)
require.NoError(t, err)
gmi, err := full.StateMinerInfo(ctx, gaa, types.EmptyTSK)
require.NoError(t, err)
testm := n[0].Stb(ctx, t, TestSpt, gmi.Owner)
ta, err := testm.ActorAddress(ctx)
require.NoError(t, err)
tid, err := address.IDFromAddress(ta)
require.NoError(t, err)
require.Equal(t, uint64(1001), tid)
}

View File

@ -8,20 +8,21 @@ import (
"testing"
"time"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
logging "github.com/ipfs/go-log/v2"
"github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/miner"
"github.com/filecoin-project/lotus/node"
)
@ -35,11 +36,15 @@ func init() {
build.InsecurePoStValidation = true
}
type StorageBuilder func(context.Context, *testing.T, abi.RegisteredSealProof, address.Address) TestStorageNode
type TestNode struct {
api.FullNode
// ListenAddr is the address on which an API server is listening, if an
// API server is created for this Node
ListenAddr multiaddr.Multiaddr
Stb StorageBuilder
}
type TestStorageNode struct {
@ -56,6 +61,8 @@ var PresealGenesis = -1
const GenesisPreseals = 2
const TestSpt = abi.RegisteredSealProof_StackedDrg2KiBV1_1
// Options for setting up a mock storage miner
type StorageMiner struct {
Full int
@ -94,6 +101,7 @@ func TestApis(t *testing.T, b APIBuilder) {
t.Run("testMining", ts.testMining)
t.Run("testMiningReal", ts.testMiningReal)
t.Run("testSearchMsg", ts.testSearchMsg)
t.Run("testNonGenesisMiner", ts.testNonGenesisMiner)
}
func DefaultFullOpts(nFull int) []FullNodeOpts {
@ -112,7 +120,11 @@ var OneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}}
var OneFull = DefaultFullOpts(1)
var TwoFull = DefaultFullOpts(2)
var FullNodeWithActorsV3At = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
var FullNodeWithActorsV4At = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
if upgradeHeight == -1 {
upgradeHeight = 3
}
return FullNodeOpts{
Opts: func(nodes []TestNode) node.Option {
return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
@ -121,10 +133,13 @@ var FullNodeWithActorsV3At = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
Height: 1,
Migration: stmgr.UpgradeActorsV2,
}, {
// Skip directly to tape height so precommits work.
Network: network.Version10,
Height: upgradeHeight,
Height: 2,
Migration: stmgr.UpgradeActorsV3,
}, {
Network: network.Version12,
Height: upgradeHeight,
Migration: stmgr.UpgradeActorsV4,
}})
},
}
@ -156,6 +171,9 @@ var MineNext = miner.MineReq{
func (ts *testSuite) testVersion(t *testing.T) {
api.RunningNodeType = api.NodeFull
t.Cleanup(func() {
api.RunningNodeType = api.NodeUnknown
})
ctx := context.Background()
apis, _ := ts.makeNodes(t, OneFull, OneMiner)

View File

@ -206,7 +206,7 @@ func pledgeSectors(t *testing.T, ctx context.Context, miner TestStorageNode, n,
func TestWindowPost(t *testing.T, b APIBuilder, blocktime time.Duration, nSectors int) {
for _, height := range []abi.ChainEpoch{
2, // before
-1, // before
162, // while sealing
5000, // while proving
} {
@ -223,7 +223,7 @@ func testWindowPostUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration,
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV3At(upgradeHeight)}, OneMiner)
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(upgradeHeight)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@ -442,7 +442,7 @@ func TestTerminate(t *testing.T, b APIBuilder, blocktime time.Duration) {
nSectors := uint64(2)
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV3At(2)}, []StorageMiner{{Full: 0, Preseal: int(nSectors)}})
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(-1)}, []StorageMiner{{Full: 0, Preseal: int(nSectors)}})
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]
@ -617,7 +617,7 @@ func TestWindowPostDispute(t *testing.T, b APIBuilder, blocktime time.Duration)
///
// Then we're going to manually submit bad proofs.
n, sn := b(t, []FullNodeOpts{
FullNodeWithActorsV3At(2),
FullNodeWithActorsV4At(-1),
}, []StorageMiner{
{Full: 0, Preseal: PresealGenesis},
{Full: 0},
@ -900,7 +900,7 @@ func TestWindowPostDisputeFails(t *testing.T, b APIBuilder, blocktime time.Durat
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV3At(2)}, OneMiner)
n, sn := b(t, []FullNodeOpts{FullNodeWithActorsV4At(-1)}, OneMiner)
client := n[0].FullNode.(*impl.FullNodeAPI)
miner := sn[0]

View File

@ -54,7 +54,7 @@ func VersionForType(nodeType NodeType) (Version, error) {
// semver versions of the rpc api exposed
var (
FullAPIVersion = newVer(1, 1, 0)
FullAPIVersion = newVer(1, 2, 0)
MinerAPIVersion = newVer(1, 0, 1)
WorkerAPIVersion = newVer(1, 0, 0)
)

View File

@ -37,6 +37,8 @@ var UpgradeActorsV3Height = abi.ChainEpoch(35)
var UpgradeNorwegianHeight = abi.ChainEpoch(40)
var UpgradeActorsV4Height = abi.ChainEpoch(45)
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,
}
@ -75,6 +77,7 @@ func init() {
UpgradeClausHeight = getUpgradeHeight("LOTUS_CLAUS_HEIGHT", UpgradeClausHeight)
UpgradeActorsV3Height = getUpgradeHeight("LOTUS_ACTORSV3_HEIGHT", UpgradeActorsV3Height)
UpgradeNorwegianHeight = getUpgradeHeight("LOTUS_NORWEGIAN_HEIGHT", UpgradeNorwegianHeight)
UpgradeActorsV4Height = getUpgradeHeight("LOTUS_ACTORSV4_HEIGHT", UpgradeActorsV4Height)
BuildType |= Build2k
}

View File

@ -34,6 +34,7 @@ const UpgradeClausHeight = 180
const UpgradeOrangeHeight = 210
const UpgradeActorsV3Height = 240
const UpgradeNorwegianHeight = UpgradeActorsV3Height + (builtin2.EpochsInHour * 12)
const UpgradeActorsV4Height = 8922
func init() {
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2 << 30))

View File

@ -43,6 +43,8 @@ const UpgradeOrangeHeight = 300
const UpgradeActorsV3Height = 600
const UpgradeNorwegianHeight = 114000
const UpgradeActorsV4Height = 193789
func init() {
policy.SetConsensusMinerMinPower(abi.NewStoragePower(32 << 30))
policy.SetSupportedProofTypes(

View File

@ -59,6 +59,9 @@ var UpgradeActorsV3Height = abi.ChainEpoch(550321)
// 2021-04-12T22:00:00Z
const UpgradeNorwegianHeight = 665280
// 2021-04-29T06:00:00Z
var UpgradeActorsV4Height = abi.ChainEpoch(712320)
func init() {
policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40))
@ -70,6 +73,10 @@ func init() {
UpgradeActorsV3Height = math.MaxInt64
}
if os.Getenv("LOTUS_DISABLE_V4_ACTOR_MIGRATION") == "1" {
UpgradeActorsV4Height = math.MaxInt64
}
Devnet = false
BuildType = BuildMainnet

View File

@ -41,6 +41,7 @@ const UpgradeOrangeHeight = 300
const UpgradeActorsV3Height = 600
const UpgradeNorwegianHeight = 999999
const UpgradeActorsV4Height = 99999999
func init() {
// Minimum block production power is set to 4 TiB

View File

@ -95,6 +95,7 @@ var (
UpgradeClausHeight abi.ChainEpoch = -10
UpgradeActorsV3Height abi.ChainEpoch = -11
UpgradeNorwegianHeight abi.ChainEpoch = -12
UpgradeActorsV4Height abi.ChainEpoch = -13
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
0: DrandMainnet,

View File

@ -14,6 +14,7 @@ import (
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
)
func init() {
@ -26,9 +27,12 @@ func init() {
builtin.RegisterActorState(builtin3.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
builtin.RegisterActorState(builtin4.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root)
})
}
var Methods = builtin3.MethodsAccount
var Methods = builtin4.MethodsAccount
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
@ -38,6 +42,8 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
return load2(store, act.Head)
case builtin3.AccountActorCodeID:
return load3(store, act.Head)
case builtin4.AccountActorCodeID:
return load4(store, act.Head)
}
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"
account4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/account"
)
var _ State = (*state4)(nil)
func load4(store adt.Store, root cid.Cid) (State, error) {
out := state4{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state4 struct {
account4.State
store adt.Store
}
func (s *state4) PubkeyAddress() (address.Address, error) {
return s.Address, nil
}

View File

@ -8,6 +8,7 @@ import (
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
@ -18,6 +19,7 @@ import (
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"
smoothing4 "github.com/filecoin-project/specs-actors/v4/actors/util/smoothing"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof"
@ -41,8 +43,8 @@ const (
)
const (
MethodSend = builtin3.MethodSend
MethodConstructor = builtin3.MethodConstructor
MethodSend = builtin4.MethodSend
MethodConstructor = builtin4.MethodConstructor
)
// These are all just type aliases across actor versions 0, 2, & 3. In the future, that might change
@ -68,6 +70,10 @@ func FromV3FilterEstimate(v3 smoothing3.FilterEstimate) FilterEstimate {
return (FilterEstimate)(v3)
}
func FromV4FilterEstimate(v4 smoothing4.FilterEstimate) FilterEstimate {
return (FilterEstimate)(v4)
}
type ActorStateLoader func(store adt.Store, root cid.Cid) (cbor.Marshaler, error)
var ActorStateLoaders = make(map[cid.Cid]ActorStateLoader)
@ -92,6 +98,8 @@ func ActorNameByCode(c cid.Cid) string {
return builtin2.ActorNameByCode(c)
case builtin3.IsBuiltinActor(c):
return builtin3.ActorNameByCode(c)
case builtin4.IsBuiltinActor(c):
return builtin4.ActorNameByCode(c)
default:
return "<unknown>"
}
@ -100,32 +108,36 @@ func ActorNameByCode(c cid.Cid) string {
func IsBuiltinActor(c cid.Cid) bool {
return builtin0.IsBuiltinActor(c) ||
builtin2.IsBuiltinActor(c) ||
builtin3.IsBuiltinActor(c)
builtin3.IsBuiltinActor(c) ||
builtin4.IsBuiltinActor(c)
}
func IsAccountActor(c cid.Cid) bool {
return c == builtin0.AccountActorCodeID ||
c == builtin2.AccountActorCodeID ||
c == builtin3.AccountActorCodeID
c == builtin3.AccountActorCodeID ||
c == builtin4.AccountActorCodeID
}
func IsStorageMinerActor(c cid.Cid) bool {
return c == builtin0.StorageMinerActorCodeID ||
c == builtin2.StorageMinerActorCodeID ||
c == builtin3.StorageMinerActorCodeID
c == builtin3.StorageMinerActorCodeID ||
c == builtin4.StorageMinerActorCodeID
}
func IsMultisigActor(c cid.Cid) bool {
return c == builtin0.MultisigActorCodeID ||
c == builtin2.MultisigActorCodeID ||
c == builtin3.MultisigActorCodeID
c == builtin3.MultisigActorCodeID ||
c == builtin4.MultisigActorCodeID
}
func IsPaymentChannelActor(c cid.Cid) bool {
return c == builtin0.PaymentChannelActorCodeID ||
c == builtin2.PaymentChannelActorCodeID ||
c == builtin3.PaymentChannelActorCodeID
c == builtin3.PaymentChannelActorCodeID ||
c == builtin4.PaymentChannelActorCodeID
}
func makeAddress(addr string) address.Address {

View File

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

View File

@ -16,6 +16,7 @@ import (
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
)
func init() {
@ -28,11 +29,14 @@ func init() {
builtin.RegisterActorState(builtin3.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
builtin.RegisterActorState(builtin4.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root)
})
}
var (
Address = builtin3.InitActorAddr
Methods = builtin3.MethodsInit
Address = builtin4.InitActorAddr
Methods = builtin4.MethodsInit
)
func Load(store adt.Store, act *types.Actor) (State, error) {
@ -43,6 +47,8 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
return load2(store, act.Head)
case builtin3.InitActorCodeID:
return load3(store, act.Head)
case builtin4.InitActorCodeID:
return load4(store, act.Head)
}
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"
builtin4 "github.com/filecoin-project/specs-actors/v4/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"
init4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/init"
adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt"
)
var _ State = (*state4)(nil)
func load4(store adt.Store, root cid.Cid) (State, error) {
out := state4{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state4 struct {
init4.State
store adt.Store
}
func (s *state4) ResolveAddress(address address.Address) (address.Address, bool, error) {
return s.State.ResolveAddress(s.store, address)
}
func (s *state4) MapAddressToNewID(address address.Address) (address.Address, error) {
return s.State.MapAddressToNewID(s.store, address)
}
func (s *state4) ForEachActor(cb func(id abi.ActorID, address address.Address) error) error {
addrs, err := adt4.AsMap(s.store, s.State.AddressMap, builtin4.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 *state4) NetworkName() (dtypes.NetworkName, error) {
return dtypes.NetworkName(s.State.NetworkName), nil
}
func (s *state4) SetNetworkName(name string) error {
s.State.NetworkName = name
return nil
}
func (s *state4) Remove(addrs ...address.Address) (err error) {
m, err := adt4.AsMap(s.store, s.State.AddressMap, builtin4.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 *state4) addressMap() (adt.Map, error) {
return adt4.AsMap(s.store, s.AddressMap, builtin4.DefaultHamtBitwidth)
}

View File

@ -13,6 +13,7 @@ import (
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
@ -29,11 +30,14 @@ func init() {
builtin.RegisterActorState(builtin3.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
builtin.RegisterActorState(builtin4.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root)
})
}
var (
Address = builtin3.StorageMarketActorAddr
Methods = builtin3.MethodsMarket
Address = builtin4.StorageMarketActorAddr
Methods = builtin4.MethodsMarket
)
func Load(store adt.Store, act *types.Actor) (st State, err error) {
@ -44,6 +48,8 @@ func Load(store adt.Store, act *types.Actor) (st State, err error) {
return load2(store, act.Head)
case builtin3.StorageMarketActorCodeID:
return load3(store, act.Head)
case builtin4.StorageMarketActorCodeID:
return load4(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}

View File

@ -0,0 +1,209 @@
package market
import (
"bytes"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
market4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/market"
adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt"
)
var _ State = (*state4)(nil)
func load4(store adt.Store, root cid.Cid) (State, error) {
out := state4{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state4 struct {
market4.State
store adt.Store
}
func (s *state4) TotalLocked() (abi.TokenAmount, error) {
fml := types.BigAdd(s.TotalClientLockedCollateral, s.TotalProviderLockedCollateral)
fml = types.BigAdd(fml, s.TotalClientStorageFee)
return fml, nil
}
func (s *state4) BalancesChanged(otherState State) (bool, error) {
otherState2, ok := otherState.(*state4)
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 *state4) StatesChanged(otherState State) (bool, error) {
otherState2, ok := otherState.(*state4)
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 *state4) States() (DealStates, error) {
stateArray, err := adt4.AsArray(s.store, s.State.States, market4.StatesAmtBitwidth)
if err != nil {
return nil, err
}
return &dealStates4{stateArray}, nil
}
func (s *state4) ProposalsChanged(otherState State) (bool, error) {
otherState2, ok := otherState.(*state4)
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 *state4) Proposals() (DealProposals, error) {
proposalArray, err := adt4.AsArray(s.store, s.State.Proposals, market4.ProposalsAmtBitwidth)
if err != nil {
return nil, err
}
return &dealProposals4{proposalArray}, nil
}
func (s *state4) EscrowTable() (BalanceTable, error) {
bt, err := adt4.AsBalanceTable(s.store, s.State.EscrowTable)
if err != nil {
return nil, err
}
return &balanceTable4{bt}, nil
}
func (s *state4) LockedTable() (BalanceTable, error) {
bt, err := adt4.AsBalanceTable(s.store, s.State.LockedTable)
if err != nil {
return nil, err
}
return &balanceTable4{bt}, nil
}
func (s *state4) VerifyDealsForActivation(
minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch,
) (weight, verifiedWeight abi.DealWeight, err error) {
w, vw, _, err := market4.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch)
return w, vw, err
}
func (s *state4) NextID() (abi.DealID, error) {
return s.State.NextID, nil
}
type balanceTable4 struct {
*adt4.BalanceTable
}
func (bt *balanceTable4) ForEach(cb func(address.Address, abi.TokenAmount) error) error {
asMap := (*adt4.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 dealStates4 struct {
adt.Array
}
func (s *dealStates4) Get(dealID abi.DealID) (*DealState, bool, error) {
var deal2 market4.DealState
found, err := s.Array.Get(uint64(dealID), &deal2)
if err != nil {
return nil, false, err
}
if !found {
return nil, false, nil
}
deal := fromV4DealState(deal2)
return &deal, true, nil
}
func (s *dealStates4) ForEach(cb func(dealID abi.DealID, ds DealState) error) error {
var ds1 market4.DealState
return s.Array.ForEach(&ds1, func(idx int64) error {
return cb(abi.DealID(idx), fromV4DealState(ds1))
})
}
func (s *dealStates4) decode(val *cbg.Deferred) (*DealState, error) {
var ds1 market4.DealState
if err := ds1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err
}
ds := fromV4DealState(ds1)
return &ds, nil
}
func (s *dealStates4) array() adt.Array {
return s.Array
}
func fromV4DealState(v4 market4.DealState) DealState {
return (DealState)(v4)
}
type dealProposals4 struct {
adt.Array
}
func (s *dealProposals4) Get(dealID abi.DealID) (*DealProposal, bool, error) {
var proposal2 market4.DealProposal
found, err := s.Array.Get(uint64(dealID), &proposal2)
if err != nil {
return nil, false, err
}
if !found {
return nil, false, nil
}
proposal := fromV4DealProposal(proposal2)
return &proposal, true, nil
}
func (s *dealProposals4) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error {
var dp1 market4.DealProposal
return s.Array.ForEach(&dp1, func(idx int64) error {
return cb(abi.DealID(idx), fromV4DealProposal(dp1))
})
}
func (s *dealProposals4) decode(val *cbg.Deferred) (*DealProposal, error) {
var dp1 market4.DealProposal
if err := dp1.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return nil, err
}
dp := fromV4DealProposal(dp1)
return &dp, nil
}
func (s *dealProposals4) array() adt.Array {
return s.Array
}
func fromV4DealProposal(v4 market4.DealProposal) DealProposal {
return (DealProposal)(v4)
}

View File

@ -24,6 +24,7 @@ import (
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"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
)
func init() {
@ -36,11 +37,14 @@ func init() {
builtin.RegisterActorState(builtin3.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
builtin.RegisterActorState(builtin4.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root)
})
}
var Methods = builtin3.MethodsMiner
var Methods = builtin4.MethodsMiner
// Unchanged between v0, v2, and v3 actors
// Unchanged between v0, v2, v3, and v4 actors
var WPoStProvingPeriod = miner0.WPoStProvingPeriod
var WPoStPeriodDeadlines = miner0.WPoStPeriodDeadlines
var WPoStChallengeWindow = miner0.WPoStChallengeWindow
@ -62,6 +66,8 @@ func Load(store adt.Store, act *types.Actor) (st State, err error) {
return load2(store, act.Head)
case builtin3.StorageMinerActorCodeID:
return load3(store, act.Head)
case builtin4.StorageMinerActorCodeID:
return load4(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
@ -94,6 +100,7 @@ type State interface {
MinerInfoChanged(State) (bool, error)
DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error)
DeadlineCronActive() (bool, error)
// Diff helpers. Used by Diff* functions internally.
sectors() (adt.Array, error)

View File

@ -330,6 +330,10 @@ func (s *state0) DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error) {
return s.State.DeadlineInfo(epoch), nil
}
func (s *state0) DeadlineCronActive() (bool, error) {
return true, nil // always active in this version
}
func (s *state0) sectors() (adt.Array, error) {
return adt0.AsArray(s.store, s.Sectors)
}

View File

@ -329,6 +329,10 @@ func (s *state2) DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error) {
return s.State.DeadlineInfo(epoch), nil
}
func (s *state2) DeadlineCronActive() (bool, error) {
return true, nil // always active in this version
}
func (s *state2) sectors() (adt.Array, error) {
return adt2.AsArray(s.store, s.Sectors)
}

View File

@ -325,6 +325,10 @@ func (s *state3) DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error) {
return s.State.DeadlineInfo(epoch), nil
}
func (s *state3) DeadlineCronActive() (bool, error) {
return true, nil // always active in this version
}
func (s *state3) sectors() (adt.Array, error) {
return adt3.AsArray(s.store, s.Sectors, miner3.SectorsAmtBitwidth)
}

View File

@ -0,0 +1,438 @@
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"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
miner4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner"
adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt"
)
var _ State = (*state4)(nil)
func load4(store adt.Store, root cid.Cid) (State, error) {
out := state4{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state4 struct {
miner4.State
store adt.Store
}
type deadline4 struct {
miner4.Deadline
store adt.Store
}
type partition4 struct {
miner4.Partition
store adt.Store
}
func (s *state4) 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 *state4) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) {
return s.CheckVestedFunds(s.store, epoch)
}
func (s *state4) LockedFunds() (LockedFunds, error) {
return LockedFunds{
VestingFunds: s.State.LockedFunds,
InitialPledgeRequirement: s.State.InitialPledge,
PreCommitDeposits: s.State.PreCommitDeposits,
}, nil
}
func (s *state4) FeeDebt() (abi.TokenAmount, error) {
return s.State.FeeDebt, nil
}
func (s *state4) InitialPledge() (abi.TokenAmount, error) {
return s.State.InitialPledge, nil
}
func (s *state4) PreCommitDeposits() (abi.TokenAmount, error) {
return s.State.PreCommitDeposits, nil
}
func (s *state4) GetSector(num abi.SectorNumber) (*SectorOnChainInfo, error) {
info, ok, err := s.State.GetSector(s.store, num)
if !ok || err != nil {
return nil, err
}
ret := fromV4SectorOnChainInfo(*info)
return &ret, nil
}
func (s *state4) 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 *state4) 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 *miner4.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 *state4) 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 *miner4.Deadline) error {
partitions, err := dl.PartitionsArray(s.store)
if err != nil {
return err
}
quant := s.State.QuantSpecForDeadline(dlIdx)
var part miner4.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 := miner4.LoadExpirationQueue(s.store, part.ExpirationsEpochs, quant, miner4.PartitionExpirationAmtBitwidth)
if err != nil {
return err
}
var exp miner4.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 *state4) GetPrecommittedSector(num abi.SectorNumber) (*SectorPreCommitOnChainInfo, error) {
info, ok, err := s.State.GetPrecommittedSector(s.store, num)
if !ok || err != nil {
return nil, err
}
ret := fromV4SectorPreCommitOnChainInfo(*info)
return &ret, nil
}
func (s *state4) LoadSectors(snos *bitfield.BitField) ([]*SectorOnChainInfo, error) {
sectors, err := miner4.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 miner4.SectorOnChainInfo
if err := sectors.ForEach(&info2, func(_ int64) error {
info := fromV4SectorOnChainInfo(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 := fromV4SectorOnChainInfo(*info2)
infos[i] = &info
}
return infos, nil
}
func (s *state4) 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 *state4) 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 &deadline4{*dl, s.store}, nil
}
func (s *state4) 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 *miner4.Deadline) error {
return cb(i, &deadline4{*dl, s.store})
})
}
func (s *state4) NumDeadlines() (uint64, error) {
return miner4.WPoStPeriodDeadlines, nil
}
func (s *state4) DeadlinesChanged(other State) (bool, error) {
other2, ok := other.(*state4)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.Deadlines.Equals(other2.Deadlines), nil
}
func (s *state4) MinerInfoChanged(other State) (bool, error) {
other0, ok := other.(*state4)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.Info.Equals(other0.State.Info), nil
}
func (s *state4) 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 *state4) DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error) {
return s.State.RecordedDeadlineInfo(epoch), nil
}
func (s *state4) DeadlineCronActive() (bool, error) {
return s.State.DeadlineCronActive, nil
}
func (s *state4) sectors() (adt.Array, error) {
return adt4.AsArray(s.store, s.Sectors, miner4.SectorsAmtBitwidth)
}
func (s *state4) decodeSectorOnChainInfo(val *cbg.Deferred) (SectorOnChainInfo, error) {
var si miner4.SectorOnChainInfo
err := si.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return SectorOnChainInfo{}, err
}
return fromV4SectorOnChainInfo(si), nil
}
func (s *state4) precommits() (adt.Map, error) {
return adt4.AsMap(s.store, s.PreCommittedSectors, builtin4.DefaultHamtBitwidth)
}
func (s *state4) decodeSectorPreCommitOnChainInfo(val *cbg.Deferred) (SectorPreCommitOnChainInfo, error) {
var sp miner4.SectorPreCommitOnChainInfo
err := sp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return SectorPreCommitOnChainInfo{}, err
}
return fromV4SectorPreCommitOnChainInfo(sp), nil
}
func (d *deadline4) LoadPartition(idx uint64) (Partition, error) {
p, err := d.Deadline.LoadPartition(d.store, idx)
if err != nil {
return nil, err
}
return &partition4{*p, d.store}, nil
}
func (d *deadline4) ForEachPartition(cb func(uint64, Partition) error) error {
ps, err := d.Deadline.PartitionsArray(d.store)
if err != nil {
return err
}
var part miner4.Partition
return ps.ForEach(&part, func(i int64) error {
return cb(uint64(i), &partition4{part, d.store})
})
}
func (d *deadline4) PartitionsChanged(other Deadline) (bool, error) {
other2, ok := other.(*deadline4)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !d.Deadline.Partitions.Equals(other2.Deadline.Partitions), nil
}
func (d *deadline4) PartitionsPoSted() (bitfield.BitField, error) {
return d.Deadline.PartitionsPoSted, nil
}
func (d *deadline4) DisputableProofCount() (uint64, error) {
ops, err := d.OptimisticProofsSnapshotArray(d.store)
if err != nil {
return 0, err
}
return ops.Length(), nil
}
func (p *partition4) AllSectors() (bitfield.BitField, error) {
return p.Partition.Sectors, nil
}
func (p *partition4) FaultySectors() (bitfield.BitField, error) {
return p.Partition.Faults, nil
}
func (p *partition4) RecoveringSectors() (bitfield.BitField, error) {
return p.Partition.Recoveries, nil
}
func fromV4SectorOnChainInfo(v4 miner4.SectorOnChainInfo) SectorOnChainInfo {
return SectorOnChainInfo{
SectorNumber: v4.SectorNumber,
SealProof: v4.SealProof,
SealedCID: v4.SealedCID,
DealIDs: v4.DealIDs,
Activation: v4.Activation,
Expiration: v4.Expiration,
DealWeight: v4.DealWeight,
VerifiedDealWeight: v4.VerifiedDealWeight,
InitialPledge: v4.InitialPledge,
ExpectedDayReward: v4.ExpectedDayReward,
ExpectedStoragePledge: v4.ExpectedStoragePledge,
}
}
func fromV4SectorPreCommitOnChainInfo(v4 miner4.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo {
return SectorPreCommitOnChainInfo{
Info: (SectorPreCommitInfo)(v4.Info),
PreCommitDeposit: v4.PreCommitDeposit,
PreCommitEpoch: v4.PreCommitEpoch,
DealWeight: v4.DealWeight,
VerifiedDealWeight: v4.VerifiedDealWeight,
}
}

View File

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

View File

@ -0,0 +1,71 @@
package multisig
import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
init4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/init"
multisig4 "github.com/filecoin-project/specs-actors/v4/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 message4 struct{ message0 }
func (m message4) 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 := &multisig4.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 := &init4.ExecParams{
CodeCID: builtin4.MultisigActorCodeID,
ConstructorParams: enc,
}
enc, actErr = actors.SerializeParams(execParams)
if actErr != nil {
return nil, actErr
}
return &types.Message{
To: init_.Address,
From: m.from,
Method: builtin4.MethodsInit.Exec,
Params: enc,
Value: initialAmount,
}, nil
}

View File

@ -13,6 +13,7 @@ import (
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
@ -29,6 +30,9 @@ func init() {
builtin.RegisterActorState(builtin3.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
builtin.RegisterActorState(builtin4.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root)
})
}
func Load(store adt.Store, act *types.Actor) (State, error) {
@ -39,6 +43,8 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
return load2(store, act.Head)
case builtin3.MultisigActorCodeID:
return load3(store, act.Head)
case builtin4.MultisigActorCodeID:
return load4(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}

View File

@ -0,0 +1,95 @@
package multisig
import (
"bytes"
"encoding/binary"
adt4 "github.com/filecoin-project/specs-actors/v4/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"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
msig4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/multisig"
)
var _ State = (*state4)(nil)
func load4(store adt.Store, root cid.Cid) (State, error) {
out := state4{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state4 struct {
msig4.State
store adt.Store
}
func (s *state4) LockedBalance(currEpoch abi.ChainEpoch) (abi.TokenAmount, error) {
return s.State.AmountLocked(currEpoch - s.State.StartEpoch), nil
}
func (s *state4) StartEpoch() (abi.ChainEpoch, error) {
return s.State.StartEpoch, nil
}
func (s *state4) UnlockDuration() (abi.ChainEpoch, error) {
return s.State.UnlockDuration, nil
}
func (s *state4) InitialBalance() (abi.TokenAmount, error) {
return s.State.InitialBalance, nil
}
func (s *state4) Threshold() (uint64, error) {
return s.State.NumApprovalsThreshold, nil
}
func (s *state4) Signers() ([]address.Address, error) {
return s.State.Signers, nil
}
func (s *state4) ForEachPendingTxn(cb func(id int64, txn Transaction) error) error {
arr, err := adt4.AsMap(s.store, s.State.PendingTxns, builtin4.DefaultHamtBitwidth)
if err != nil {
return err
}
var out msig4.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 *state4) PendingTxnChanged(other State) (bool, error) {
other2, ok := other.(*state4)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.PendingTxns.Equals(other2.PendingTxns), nil
}
func (s *state4) transactions() (adt.Map, error) {
return adt4.AsMap(s.store, s.PendingTxns, builtin4.DefaultHamtBitwidth)
}
func (s *state4) decodeTransaction(val *cbg.Deferred) (Transaction, error) {
var tx msig4.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/types"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
)
var Methods = builtin3.MethodsPaych
var Methods = builtin4.MethodsPaych
func Message(version actors.Version, from address.Address) MessageBuilder {
switch version {
@ -21,6 +21,8 @@ func Message(version actors.Version, from address.Address) MessageBuilder {
return message2{from}
case actors.Version3:
return message3{from}
case actors.Version4:
return message4{from}
default:
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"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
init4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/init"
paych4 "github.com/filecoin-project/specs-actors/v4/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 message4 struct{ from address.Address }
func (m message4) Create(to address.Address, initialAmount abi.TokenAmount) (*types.Message, error) {
params, aerr := actors.SerializeParams(&paych4.ConstructorParams{From: m.from, To: to})
if aerr != nil {
return nil, aerr
}
enc, aerr := actors.SerializeParams(&init4.ExecParams{
CodeCID: builtin4.PaymentChannelActorCodeID,
ConstructorParams: params,
})
if aerr != nil {
return nil, aerr
}
return &types.Message{
To: init_.Address,
From: m.from,
Value: initialAmount,
Method: builtin4.MethodsInit.Exec,
Params: enc,
}, nil
}
func (m message4) Update(paych address.Address, sv *SignedVoucher, secret []byte) (*types.Message, error) {
params, aerr := actors.SerializeParams(&paych4.UpdateChannelStateParams{
Sv: *sv,
Secret: secret,
})
if aerr != nil {
return nil, aerr
}
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin4.MethodsPaych.UpdateChannelState,
Params: params,
}, nil
}
func (m message4) Settle(paych address.Address) (*types.Message, error) {
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin4.MethodsPaych.Settle,
}, nil
}
func (m message4) Collect(paych address.Address) (*types.Message, error) {
return &types.Message{
To: paych,
From: m.from,
Value: abi.NewTokenAmount(0),
Method: builtin4.MethodsPaych.Collect,
}, nil
}

View File

@ -16,6 +16,7 @@ import (
paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
@ -32,6 +33,9 @@ func init() {
builtin.RegisterActorState(builtin3.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
builtin.RegisterActorState(builtin4.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root)
})
}
// Load returns an abstract copy of payment channel state, irregardless of actor version
@ -43,6 +47,8 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
return load2(store, act.Head)
case builtin3.PaymentChannelActorCodeID:
return load3(store, act.Head)
case builtin4.PaymentChannelActorCodeID:
return load4(store, act.Head)
}
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"
paych4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/paych"
adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt"
)
var _ State = (*state4)(nil)
func load4(store adt.Store, root cid.Cid) (State, error) {
out := state4{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state4 struct {
paych4.State
store adt.Store
lsAmt *adt4.Array
}
// Channel owner, who has funded the actor
func (s *state4) From() (address.Address, error) {
return s.State.From, nil
}
// Recipient of payouts from channel
func (s *state4) To() (address.Address, error) {
return s.State.To, nil
}
// Height at which the channel can be `Collected`
func (s *state4) SettlingAt() (abi.ChainEpoch, error) {
return s.State.SettlingAt, nil
}
// Amount successfully redeemed through the payment channel, paid out on `Collect()`
func (s *state4) ToSend() (abi.TokenAmount, error) {
return s.State.ToSend, nil
}
func (s *state4) getOrLoadLsAmt() (*adt4.Array, error) {
if s.lsAmt != nil {
return s.lsAmt, nil
}
// Get the lane state from the chain
lsamt, err := adt4.AsArray(s.store, s.State.LaneStates, paych4.LaneStatesAmtBitwidth)
if err != nil {
return nil, err
}
s.lsAmt = lsamt
return lsamt, nil
}
// Get total number of lanes
func (s *state4) LaneCount() (uint64, error) {
lsamt, err := s.getOrLoadLsAmt()
if err != nil {
return 0, err
}
return lsamt.Length(), nil
}
// Iterate lane states
func (s *state4) 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 paych4.LaneState
return lsamt.ForEach(&ls, func(i int64) error {
return cb(uint64(i), &laneState4{ls})
})
}
type laneState4 struct {
paych4.LaneState
}
func (ls *laneState4) Redeemed() (big.Int, error) {
return ls.LaneState.Redeemed, nil
}
func (ls *laneState4) Nonce() (uint64, error) {
return ls.LaneState.Nonce, nil
}

View File

@ -17,6 +17,7 @@ import (
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
)
func init() {
@ -29,11 +30,14 @@ func init() {
builtin.RegisterActorState(builtin3.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
builtin.RegisterActorState(builtin4.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root)
})
}
var (
Address = builtin3.StoragePowerActorAddr
Methods = builtin3.MethodsPower
Address = builtin4.StoragePowerActorAddr
Methods = builtin4.MethodsPower
)
func Load(store adt.Store, act *types.Actor) (st State, err error) {
@ -44,6 +48,8 @@ func Load(store adt.Store, act *types.Actor) (st State, err error) {
return load2(store, act.Head)
case builtin3.StoragePowerActorCodeID:
return load3(store, act.Head)
case builtin4.StoragePowerActorCodeID:
return load4(store, act.Head)
}
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"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
power4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/power"
adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt"
)
var _ State = (*state4)(nil)
func load4(store adt.Store, root cid.Cid) (State, error) {
out := state4{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state4 struct {
power4.State
store adt.Store
}
func (s *state4) TotalLocked() (abi.TokenAmount, error) {
return s.TotalPledgeCollateral, nil
}
func (s *state4) 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 *state4) TotalCommitted() (Claim, error) {
return Claim{
RawBytePower: s.TotalBytesCommitted,
QualityAdjPower: s.TotalQABytesCommitted,
}, nil
}
func (s *state4) MinerPower(addr address.Address) (Claim, bool, error) {
claims, err := s.claims()
if err != nil {
return Claim{}, false, err
}
var claim power4.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 *state4) MinerNominalPowerMeetsConsensusMinimum(a address.Address) (bool, error) {
return s.State.MinerNominalPowerMeetsConsensusMinimum(s.store, a)
}
func (s *state4) TotalPowerSmoothed() (builtin.FilterEstimate, error) {
return builtin.FromV4FilterEstimate(s.State.ThisEpochQAPowerSmoothed), nil
}
func (s *state4) MinerCounts() (uint64, uint64, error) {
return uint64(s.State.MinerAboveMinPowerCount), uint64(s.State.MinerCount), nil
}
func (s *state4) 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 *state4) ForEachClaim(cb func(miner address.Address, claim Claim) error) error {
claims, err := s.claims()
if err != nil {
return err
}
var claim power4.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 *state4) ClaimsChanged(other State) (bool, error) {
other2, ok := other.(*state4)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.Claims.Equals(other2.State.Claims), nil
}
func (s *state4) claims() (adt.Map, error) {
return adt4.AsMap(s.store, s.Claims, builtin4.DefaultHamtBitwidth)
}
func (s *state4) decodeClaim(val *cbg.Deferred) (Claim, error) {
var ci power4.Claim
if err := ci.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return Claim{}, err
}
return fromV4Claim(ci), nil
}
func fromV4Claim(v4 power4.Claim) Claim {
return Claim{
RawBytePower: v4.RawBytePower,
QualityAdjPower: v4.QualityAdjPower,
}
}

View File

@ -10,6 +10,7 @@ import (
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
@ -26,11 +27,14 @@ func init() {
builtin.RegisterActorState(builtin3.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
builtin.RegisterActorState(builtin4.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root)
})
}
var (
Address = builtin3.RewardActorAddr
Methods = builtin3.MethodsReward
Address = builtin4.RewardActorAddr
Methods = builtin4.MethodsReward
)
func Load(store adt.Store, act *types.Actor) (st State, err error) {
@ -41,6 +45,8 @@ func Load(store adt.Store, act *types.Actor) (st State, err error) {
return load2(store, act.Head)
case builtin3.RewardActorCodeID:
return load3(store, act.Head)
case builtin4.RewardActorCodeID:
return load4(store, act.Head)
}
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"
miner4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner"
reward4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/reward"
smoothing4 "github.com/filecoin-project/specs-actors/v4/actors/util/smoothing"
)
var _ State = (*state4)(nil)
func load4(store adt.Store, root cid.Cid) (State, error) {
out := state4{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state4 struct {
reward4.State
store adt.Store
}
func (s *state4) ThisEpochReward() (abi.TokenAmount, error) {
return s.State.ThisEpochReward, nil
}
func (s *state4) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) {
return builtin.FilterEstimate{
PositionEstimate: s.State.ThisEpochRewardSmoothed.PositionEstimate,
VelocityEstimate: s.State.ThisEpochRewardSmoothed.VelocityEstimate,
}, nil
}
func (s *state4) ThisEpochBaselinePower() (abi.StoragePower, error) {
return s.State.ThisEpochBaselinePower, nil
}
func (s *state4) TotalStoragePowerReward() (abi.TokenAmount, error) {
return s.State.TotalStoragePowerReward, nil
}
func (s *state4) EffectiveBaselinePower() (abi.StoragePower, error) {
return s.State.EffectiveBaselinePower, nil
}
func (s *state4) EffectiveNetworkTime() (abi.ChainEpoch, error) {
return s.State.EffectiveNetworkTime, nil
}
func (s *state4) CumsumBaseline() (reward4.Spacetime, error) {
return s.State.CumsumBaseline, nil
}
func (s *state4) CumsumRealized() (reward4.Spacetime, error) {
return s.State.CumsumRealized, nil
}
func (s *state4) InitialPledgeForPower(qaPower abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) {
return miner4.InitialPledgeForPower(
qaPower,
s.State.ThisEpochBaselinePower,
s.State.ThisEpochRewardSmoothed,
smoothing4.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
},
circSupply,
), nil
}
func (s *state4) PreCommitDepositForPower(networkQAPower builtin.FilterEstimate, sectorWeight abi.StoragePower) (abi.TokenAmount, error) {
return miner4.PreCommitDepositForPower(s.State.ThisEpochRewardSmoothed,
smoothing4.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
},
sectorWeight), nil
}

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"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
verifreg4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg"
adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt"
)
var _ State = (*state4)(nil)
func load4(store adt.Store, root cid.Cid) (State, error) {
out := state4{store: store}
err := store.Get(store.Context(), root, &out)
if err != nil {
return nil, err
}
return &out, nil
}
type state4 struct {
verifreg4.State
store adt.Store
}
func (s *state4) RootKey() (address.Address, error) {
return s.State.RootKey, nil
}
func (s *state4) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) {
return getDataCap(s.store, actors.Version4, s.verifiedClients, addr)
}
func (s *state4) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) {
return getDataCap(s.store, actors.Version4, s.verifiers, addr)
}
func (s *state4) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error {
return forEachCap(s.store, actors.Version4, s.verifiers, cb)
}
func (s *state4) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error {
return forEachCap(s.store, actors.Version4, s.verifiedClients, cb)
}
func (s *state4) verifiedClients() (adt.Map, error) {
return adt4.AsMap(s.store, s.VerifiedClients, builtin4.DefaultHamtBitwidth)
}
func (s *state4) verifiers() (adt.Map, error) {
return adt4.AsMap(s.store, s.Verifiers, builtin4.DefaultHamtBitwidth)
}

View File

@ -1,15 +1,17 @@
package verifreg
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
@ -26,11 +28,14 @@ func init() {
builtin.RegisterActorState(builtin3.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load3(store, root)
})
builtin.RegisterActorState(builtin4.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load4(store, root)
})
}
var (
Address = builtin3.VerifiedRegistryActorAddr
Methods = builtin3.MethodsVerifiedRegistry
Address = builtin4.VerifiedRegistryActorAddr
Methods = builtin4.MethodsVerifiedRegistry
)
func Load(store adt.Store, act *types.Actor) (State, error) {
@ -41,6 +46,8 @@ func Load(store adt.Store, act *types.Actor) (State, error) {
return load2(store, act.Head)
case builtin3.VerifiedRegistryActorCodeID:
return load3(store, act.Head)
case builtin4.VerifiedRegistryActorCodeID:
return load4(store, act.Head)
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}

View File

@ -20,15 +20,20 @@ import (
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"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
market4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/market"
miner4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner"
paych4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/paych"
verifreg4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg"
)
const (
ChainFinality = miner3.ChainFinality
SealRandomnessLookback = ChainFinality
PaychSettleDelay = paych3.SettleDelay
MaxPreCommitRandomnessLookback = builtin3.EpochsInDay + SealRandomnessLookback
ChainFinality = miner4.ChainFinality
SealRandomnessLookback = ChainFinality
PaychSettleDelay = paych4.SettleDelay
MaxPreCommitRandomnessLookback = builtin4.EpochsInDay + SealRandomnessLookback
)
// SetSupportedProofTypes sets supported proof types, across all actor versions.
@ -43,6 +48,10 @@ func SetSupportedProofTypes(types ...abi.RegisteredSealProof) {
miner3.PreCommitSealProofTypesV7 = make(map[abi.RegisteredSealProof]struct{}, len(types)*2)
miner3.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types))
miner4.PreCommitSealProofTypesV0 = make(map[abi.RegisteredSealProof]struct{}, len(types))
miner4.PreCommitSealProofTypesV7 = make(map[abi.RegisteredSealProof]struct{}, len(types)*2)
miner4.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types))
AddSupportedProofTypes(types...)
}
@ -55,19 +64,21 @@ func AddSupportedProofTypes(types ...abi.RegisteredSealProof) {
}
// Set for all miner versions.
miner0.SupportedProofTypes[t] = struct{}{}
miner2.PreCommitSealProofTypesV0[t] = struct{}{}
miner2.PreCommitSealProofTypesV0[t] = struct{}{}
miner2.PreCommitSealProofTypesV7[t] = struct{}{}
miner2.PreCommitSealProofTypesV7[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
miner2.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
miner3.PreCommitSealProofTypesV0[t] = struct{}{}
miner3.PreCommitSealProofTypesV7[t] = struct{}{}
miner3.PreCommitSealProofTypesV7[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
miner3.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
miner4.PreCommitSealProofTypesV0[t] = struct{}{}
miner4.PreCommitSealProofTypesV7[t] = struct{}{}
miner4.PreCommitSealProofTypesV7[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
miner4.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{}
}
}
@ -78,6 +89,7 @@ func SetPreCommitChallengeDelay(delay abi.ChainEpoch) {
miner0.PreCommitChallengeDelay = delay
miner2.PreCommitChallengeDelay = delay
miner3.PreCommitChallengeDelay = delay
miner4.PreCommitChallengeDelay = delay
}
// TODO: this function shouldn't really exist. Instead, the API should expose the precommit delay.
@ -97,6 +109,10 @@ func SetConsensusMinerMinPower(p abi.StoragePower) {
for _, policy := range builtin3.PoStProofPolicies {
policy.ConsensusMinerMinPower = p
}
for _, policy := range builtin4.PoStProofPolicies {
policy.ConsensusMinerMinPower = p
}
}
// SetMinVerifiedDealSize sets the minimum size of a verified deal. This should
@ -105,6 +121,7 @@ func SetMinVerifiedDealSize(size abi.StoragePower) {
verifreg0.MinVerifiedDealSize = size
verifreg2.MinVerifiedDealSize = size
verifreg3.MinVerifiedDealSize = size
verifreg4.MinVerifiedDealSize = size
}
func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) abi.ChainEpoch {
@ -115,6 +132,8 @@ func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) ab
return miner2.MaxProveCommitDuration[t]
case actors.Version3:
return miner3.MaxProveCommitDuration[t]
case actors.Version4:
return miner4.MaxProveCommitDuration[t]
default:
panic("unsupported actors version")
}
@ -132,6 +151,8 @@ func DealProviderCollateralBounds(
return market2.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil)
case actors.Version3:
return market3.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil)
case actors.Version4:
return market4.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil)
default:
panic("unsupported actors version")
}
@ -155,6 +176,10 @@ func SetWPoStChallengeWindow(period abi.ChainEpoch) {
// by default, this is 2x finality which is 30 periods.
// scale it if we're scaling the challenge period.
miner3.WPoStDisputeWindow = period * 30
miner4.WPoStChallengeWindow = period
miner4.WPoStProvingPeriod = period * abi.ChainEpoch(miner4.WPoStPeriodDeadlines)
miner4.WPoStDisputeWindow = period * 30 // see the miner3 comment
}
func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch {
@ -175,13 +200,13 @@ func GetMaxPoStPartitions(p abi.RegisteredPoStProof) (int, error) {
if err != nil {
return 0, err
}
return int(miner3.AddressedSectorsMax / sectorsPerPart), nil
return int(miner4.AddressedSectorsMax / sectorsPerPart), nil
}
func GetDefaultSectorSize() abi.SectorSize {
// supported sector sizes are the same across versions.
szs := make([]abi.SectorSize, 0, len(miner3.PreCommitSealProofTypesV8))
for spt := range miner3.PreCommitSealProofTypesV8 {
szs := make([]abi.SectorSize, 0, len(miner4.PreCommitSealProofTypesV8))
for spt := range miner4.PreCommitSealProofTypesV8 {
ss, err := spt.SectorSize()
if err != nil {
panic(err)
@ -199,10 +224,10 @@ func GetDefaultSectorSize() abi.SectorSize {
func GetSectorMaxLifetime(proof abi.RegisteredSealProof, nwVer network.Version) abi.ChainEpoch {
if nwVer <= network.Version10 {
return builtin3.SealProofPoliciesV0[proof].SectorMaxLifetime
return builtin4.SealProofPoliciesV0[proof].SectorMaxLifetime
}
return builtin3.SealProofPoliciesV11[proof].SectorMaxLifetime
return builtin4.SealProofPoliciesV11[proof].SectorMaxLifetime
}
func GetAddressedSectorsMax(nwVer network.Version) int {
@ -213,6 +238,8 @@ func GetAddressedSectorsMax(nwVer network.Version) int {
return miner2.AddressedSectorsMax
case actors.Version3:
return miner3.AddressedSectorsMax
case actors.Version4:
return miner4.AddressedSectorsMax
default:
panic("unsupported network version")
}
@ -227,6 +254,8 @@ func GetDeclarationsMax(nwVer network.Version) int {
return miner2.DeclarationsMax
case actors.Version3:
return miner3.DeclarationsMax
case actors.Version4:
return miner4.DeclarationsMax
default:
panic("unsupported network version")
}

View File

@ -12,6 +12,7 @@ const (
Version0 Version = 0
Version2 Version = 2
Version3 Version = 3
Version4 Version = 4
)
// Converts a network version into an actors adt version.
@ -23,6 +24,8 @@ func VersionForNetwork(version network.Version) Version {
return Version2
case network.Version10, network.Version11:
return Version3
case network.Version12:
return Version4
default:
panic(fmt.Sprintf("unsupported network version %d", version))
}

View File

@ -3,7 +3,6 @@ package drand
import (
"bytes"
"context"
"sync"
"time"
dchain "github.com/drand/drand/chain"
@ -13,6 +12,7 @@ import (
gclient "github.com/drand/drand/lp2p/client"
"github.com/drand/kyber"
kzap "github.com/go-kit/kit/log/zap"
lru "github.com/hashicorp/golang-lru"
"go.uber.org/zap/zapcore"
"golang.org/x/xerrors"
@ -61,8 +61,7 @@ type DrandBeacon struct {
filGenTime uint64
filRoundTime uint64
cacheLk sync.Mutex
localCache map[uint64]types.BeaconEntry
localCache *lru.Cache
}
// DrandHTTPClient interface overrides the user agent used by drand
@ -111,9 +110,14 @@ func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes
return nil, xerrors.Errorf("creating drand client")
}
lc, err := lru.New(1024)
if err != nil {
return nil, err
}
db := &DrandBeacon{
client: client,
localCache: make(map[uint64]types.BeaconEntry),
localCache: lc,
}
db.pubkey = drandChain.PublicKey
@ -156,19 +160,16 @@ func (db *DrandBeacon) Entry(ctx context.Context, round uint64) <-chan beacon.Re
return out
}
func (db *DrandBeacon) cacheValue(e types.BeaconEntry) {
db.cacheLk.Lock()
defer db.cacheLk.Unlock()
db.localCache[e.Round] = e
db.localCache.Add(e.Round, e)
}
func (db *DrandBeacon) getCachedValue(round uint64) *types.BeaconEntry {
db.cacheLk.Lock()
defer db.cacheLk.Unlock()
v, ok := db.localCache[round]
v, ok := db.localCache.Get(round)
if !ok {
return nil
}
return &v
e, _ := v.(*types.BeaconEntry)
return e
}
func (db *DrandBeacon) VerifyEntry(curr types.BeaconEntry, prev types.BeaconEntry) error {

View File

@ -11,7 +11,9 @@ import (
"github.com/filecoin-project/go-address"
tbig "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/specs-actors/v3/actors/builtin"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/messagepool/gasguess"
"github.com/filecoin-project/lotus/chain/types"
@ -698,6 +700,17 @@ func (*MessagePool) getGasPerf(gasReward *big.Int, gasLimit int64) float64 {
return r
}
func isMessageMute(m *types.Message, ts *types.TipSet) bool {
if api.RunningNodeType != api.NodeFull || ts.Height() > build.UpgradeActorsV4Height {
return false
}
if m.To == builtin.StoragePowerActorAddr {
return m.Method == builtin.MethodsPower.CreateMiner
}
return false
}
func (mp *MessagePool) createMessageChains(actor address.Address, mset map[uint64]*types.SignedMessage, baseFee types.BigInt, ts *types.TipSet) []*msgChain {
// collect all messages
msgs := make([]*types.SignedMessage, 0, len(mset))
@ -758,6 +771,11 @@ func (mp *MessagePool) createMessageChains(actor address.Address, mset map[uint6
if balance.Cmp(required) < 0 {
break
}
if isMessageMute(&m.Message, ts) {
break
}
balance = new(big.Int).Sub(balance, required)
value := m.Message.Value.Int

View File

@ -24,6 +24,7 @@ import (
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"
states4 "github.com/filecoin-project/specs-actors/v4/actors/states"
)
var log = logging.Logger("statetree")
@ -184,6 +185,12 @@ func NewStateTree(cst cbor.IpldStore, ver types.StateTreeVersion) (*StateTree, e
return nil, xerrors.Errorf("failed to create state tree: %w", err)
}
hamt = tree.Map
case types.StateTreeVersion3:
tree, err := states4.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)
}
@ -233,6 +240,12 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
if tree != nil {
hamt = tree.Map
}
case types.StateTreeVersion3:
var tree *states4.Tree
tree, err = states4.LoadTree(store, root.Actors)
if tree != nil {
hamt = tree.Map
}
default:
return nil, xerrors.Errorf("unsupported state tree version: %d", root.Version)
}

View File

@ -34,6 +34,7 @@ import (
"github.com/filecoin-project/specs-actors/v2/actors/migration/nv4"
"github.com/filecoin-project/specs-actors/v2/actors/migration/nv7"
"github.com/filecoin-project/specs-actors/v3/actors/migration/nv10"
"github.com/filecoin-project/specs-actors/v4/actors/migration/nv12"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"golang.org/x/xerrors"
@ -190,6 +191,22 @@ func DefaultUpgradeSchedule() UpgradeSchedule {
Height: build.UpgradeNorwegianHeight,
Network: network.Version11,
Migration: nil,
}, {
Height: build.UpgradeActorsV4Height,
Network: network.Version12,
Migration: UpgradeActorsV4,
PreMigrations: []PreMigration{{
PreMigration: PreUpgradeActorsV4,
StartWithin: 120,
DontStartWithin: 60,
StopWithin: 35,
}, {
PreMigration: PreUpgradeActorsV4,
StartWithin: 30,
DontStartWithin: 15,
StopWithin: 5,
}},
Expensive: true,
}}
for _, u := range updates {
@ -1063,6 +1080,92 @@ func upgradeActorsV3Common(
return newRoot, nil
}
func UpgradeActorsV4(ctx context.Context, sm *StateManager, cache MigrationCache, cb ExecCallback, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
// Use all the CPUs except 3.
workerCount := runtime.NumCPU() - 3
if workerCount <= 0 {
workerCount = 1
}
config := nv12.Config{
MaxWorkers: uint(workerCount),
JobQueueSize: 1000,
ResultQueueSize: 100,
ProgressLogPeriod: 10 * time.Second,
}
newRoot, err := upgradeActorsV4Common(ctx, sm, cache, root, epoch, ts, config)
if err != nil {
return cid.Undef, xerrors.Errorf("migrating actors v4 state: %w", err)
}
return newRoot, nil
}
func PreUpgradeActorsV4(ctx context.Context, sm *StateManager, cache MigrationCache, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) error {
// Use half the CPUs for pre-migration, but leave at least 3.
workerCount := runtime.NumCPU()
if workerCount <= 4 {
workerCount = 1
} else {
workerCount /= 2
}
config := nv12.Config{MaxWorkers: uint(workerCount)}
_, err := upgradeActorsV4Common(ctx, sm, cache, root, epoch, ts, config)
return err
}
func upgradeActorsV4Common(
ctx context.Context, sm *StateManager, cache MigrationCache,
root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet,
config nv12.Config,
) (cid.Cid, error) {
buf := blockstore.NewTieredBstore(sm.cs.StateBlockstore(), blockstore.NewMemorySync())
store := store.ActorStore(ctx, buf)
// Load the state root.
var stateRoot types.StateRoot
if err := store.Get(ctx, root, &stateRoot); err != nil {
return cid.Undef, xerrors.Errorf("failed to decode state root: %w", err)
}
if stateRoot.Version != types.StateTreeVersion2 {
return cid.Undef, xerrors.Errorf(
"expected state root version 2 for actors v4 upgrade, got %d",
stateRoot.Version,
)
}
// Perform the migration
newHamtRoot, err := nv12.MigrateStateTree(ctx, store, stateRoot.Actors, epoch, config, migrationLogger{}, cache)
if err != nil {
return cid.Undef, xerrors.Errorf("upgrading to actors v2: %w", err)
}
// Persist the result.
newRoot, err := store.Put(ctx, &types.StateRoot{
Version: types.StateTreeVersion3,
Actors: newHamtRoot,
Info: stateRoot.Info,
})
if err != nil {
return cid.Undef, xerrors.Errorf("failed to persist new state root: %w", err)
}
// Persist the new tree.
{
from := buf
to := buf.Read()
if err := vm.Copy(ctx, from, to, newRoot); err != nil {
return cid.Undef, xerrors.Errorf("copying migrated tree: %w", err)
}
}
return newRoot, nil
}
func setNetworkName(ctx context.Context, store adt.Store, tree *state.StateTree, name string) error {
ia, err := tree.GetActor(builtin0.InitActorAddr)
if err != nil {

View File

@ -26,6 +26,7 @@ import (
exported0 "github.com/filecoin-project/specs-actors/actors/builtin/exported"
exported2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/exported"
exported3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/exported"
exported4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/exported"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors/builtin"
@ -548,6 +549,7 @@ func init() {
actors = append(actors, exported0.BuiltinActors()...)
actors = append(actors, exported2.BuiltinActors()...)
actors = append(actors, exported3.BuiltinActors()...)
actors = append(actors, exported4.BuiltinActors()...)
for _, actor := range actors {
exports := actor.Exports()

View File

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

View File

@ -18,6 +18,7 @@ import (
exported2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/exported"
vmr "github.com/filecoin-project/specs-actors/v2/actors/runtime"
exported3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/exported"
exported4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/exported"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/exitcode"
@ -64,6 +65,7 @@ func NewActorRegistry() *ActorRegistry {
inv.Register(ActorsVersionPredicate(actors.Version0), exported0.BuiltinActors()...)
inv.Register(ActorsVersionPredicate(actors.Version2), exported2.BuiltinActors()...)
inv.Register(ActorsVersionPredicate(actors.Version3), exported3.BuiltinActors()...)
inv.Register(ActorsVersionPredicate(actors.Version4), exported4.BuiltinActors()...)
return inv
}

View File

@ -17,6 +17,7 @@ import (
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin"
builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
@ -102,6 +103,8 @@ func newAccountActor(ver actors.Version) *types.Actor {
code = builtin2.AccountActorCodeID
case actors.Version3:
code = builtin3.AccountActorCodeID
case actors.Version4:
code = builtin4.AccountActorCodeID
default:
panic("unsupported actors version")
}

View File

@ -51,7 +51,7 @@ func TestWorkerKeyChange(t *testing.T) {
blocktime := 1 * time.Millisecond
n, sn := builder.MockSbBuilder(t, []test.FullNodeOpts{test.FullNodeWithActorsV3At(2), test.FullNodeWithActorsV3At(2)}, test.OneMiner)
n, sn := builder.MockSbBuilder(t, []test.FullNodeOpts{test.FullNodeWithActorsV4At(-1), test.FullNodeWithActorsV4At(-1)}, test.OneMiner)
client1 := n[0]
client2 := n[1]

View File

@ -193,7 +193,7 @@ Response:
```json
{
"Version": "string value",
"APIVersion": 65792,
"APIVersion": 66048,
"BlockDelay": 42
}
```

View File

@ -145,7 +145,7 @@ Perms: admin
Inputs: `null`
Response: `65792`
Response: `66048`
## Add

View File

@ -276,7 +276,7 @@ Response:
```json
{
"Version": "string value",
"APIVersion": 65792,
"APIVersion": 66048,
"BlockDelay": 42
}
```

View File

@ -27,6 +27,7 @@ var log = logging.Logger("sbmock")
type SectorMgr struct {
sectors map[abi.SectorID]*sectorState
failPoSt bool
pieces map[cid.Cid][]byte
nextSectorID abi.SectorNumber
@ -263,6 +264,14 @@ func (mgr *SectorMgr) MarkFailed(sid storage.SectorRef, failed bool) error {
return nil
}
func (mgr *SectorMgr) Fail() {
mgr.lk.Lock()
defer mgr.lk.Unlock()
mgr.failPoSt = true
return
}
func (mgr *SectorMgr) MarkCorrupted(sid storage.SectorRef, corrupted bool) error {
mgr.lk.Lock()
defer mgr.lk.Unlock()
@ -292,10 +301,20 @@ func AddOpFinish(ctx context.Context) (context.Context, func()) {
}
func (mgr *SectorMgr) GenerateWinningPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof2.SectorInfo, randomness abi.PoStRandomness) ([]proof2.PoStProof, error) {
mgr.lk.Lock()
defer mgr.lk.Unlock()
return generateFakePoSt(sectorInfo, abi.RegisteredSealProof.RegisteredWinningPoStProof, randomness), nil
}
func (mgr *SectorMgr) GenerateWindowPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof2.SectorInfo, randomness abi.PoStRandomness) ([]proof2.PoStProof, []abi.SectorID, error) {
mgr.lk.Lock()
defer mgr.lk.Unlock()
if mgr.failPoSt {
return nil, nil, xerrors.Errorf("failed to post (mock)")
}
si := make([]proof2.SectorInfo, 0, len(sectorInfo))
var skipped []abi.SectorID

1
go.mod
View File

@ -46,6 +46,7 @@ require (
github.com/filecoin-project/specs-actors v0.9.13
github.com/filecoin-project/specs-actors/v2 v2.3.5-0.20210114162132-5b58b773f4fb
github.com/filecoin-project/specs-actors/v3 v3.1.0
github.com/filecoin-project/specs-actors/v4 v4.0.0
github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506
github.com/filecoin-project/test-vectors/schema v0.0.5
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1

2
go.sum
View File

@ -312,6 +312,8 @@ github.com/filecoin-project/specs-actors/v2 v2.3.5-0.20210114162132-5b58b773f4fb
github.com/filecoin-project/specs-actors/v2 v2.3.5-0.20210114162132-5b58b773f4fb/go.mod h1:LljnY2Mn2homxZsmokJZCpRuhOPxfXhvcek5gWkmqAc=
github.com/filecoin-project/specs-actors/v3 v3.1.0 h1:s4qiPw8pgypqBGAy853u/zdZJ7K9cTZdM1rTiSonHrg=
github.com/filecoin-project/specs-actors/v3 v3.1.0/go.mod h1:mpynccOLlIRy0QnR008BwYBwT9fen+sPR13MA1VmMww=
github.com/filecoin-project/specs-actors/v4 v4.0.0 h1:vMALksY5G3J5rj3q9rbcyB+f4Tk1xrLqSgdB3jOok4s=
github.com/filecoin-project/specs-actors/v4 v4.0.0/go.mod h1:TkHXf/l7Wyw4ZejyXIPS2rK8bBO0rdwhTZyQQgaglng=
github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 h1:Ur/l2+6qN+lQiqjozWWc5p9UDaAMDZKTlDS98oRnlIw=
github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g=
github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg=

View File

@ -306,5 +306,109 @@
"AddVerifiedClient",
"UseBytes",
"RestoreBytes"
],
"fil/4/account": [
"Send",
"Constructor",
"PubkeyAddress"
],
"fil/4/cron": [
"Send",
"Constructor",
"EpochTick"
],
"fil/4/init": [
"Send",
"Constructor",
"Exec"
],
"fil/4/multisig": [
"Send",
"Constructor",
"Propose",
"Approve",
"Cancel",
"AddSigner",
"RemoveSigner",
"SwapSigner",
"ChangeNumApprovalsThreshold",
"LockBalance"
],
"fil/4/paymentchannel": [
"Send",
"Constructor",
"UpdateChannelState",
"Settle",
"Collect"
],
"fil/4/reward": [
"Send",
"Constructor",
"AwardBlockReward",
"ThisEpochReward",
"UpdateNetworkKPI"
],
"fil/4/storagemarket": [
"Send",
"Constructor",
"AddBalance",
"WithdrawBalance",
"PublishStorageDeals",
"VerifyDealsForActivation",
"ActivateDeals",
"OnMinerSectorsTerminate",
"ComputeDataCommitment",
"CronTick"
],
"fil/4/storageminer": [
"Send",
"Constructor",
"ControlAddresses",
"ChangeWorkerAddress",
"ChangePeerID",
"SubmitWindowedPoSt",
"PreCommitSector",
"ProveCommitSector",
"ExtendSectorExpiration",
"TerminateSectors",
"DeclareFaults",
"DeclareFaultsRecovered",
"OnDeferredCronEvent",
"CheckSectorProven",
"ApplyRewards",
"ReportConsensusFault",
"WithdrawBalance",
"ConfirmSectorProofsValid",
"ChangeMultiaddrs",
"CompactPartitions",
"CompactSectorNumbers",
"ConfirmUpdateWorkerKey",
"RepayDebt",
"ChangeOwnerAddress",
"DisputeWindowedPoSt"
],
"fil/4/storagepower": [
"Send",
"Constructor",
"CreateMiner",
"UpdateClaimedPower",
"EnrollCronEvent",
"OnEpochTickEnd",
"UpdatePledgeTotal",
"SubmitPoRepForBulkVerify",
"CurrentTotalPower"
],
"fil/4/system": [
"Send",
"Constructor"
],
"fil/4/verifiedregistry": [
"Send",
"Constructor",
"AddVerifier",
"RemoveVerifier",
"AddVerifiedClient",
"UseBytes",
"RestoreBytes"
]
}

View File

@ -232,3 +232,16 @@ func TestWindowPostDisputeFails(t *testing.T) {
test.TestWindowPostDisputeFails(t, builder.MockSbBuilder, 2*time.Millisecond)
}
func TestDeadlineToggling(t *testing.T) {
if os.Getenv("LOTUS_TEST_DEADLINE_TOGGLING") != "1" {
t.Skip("this takes a few minutes, set LOTUS_TEST_DEADLINE_TOGGLING=1 to run")
}
logging.SetLogLevel("miner", "ERROR")
logging.SetLogLevel("chainstore", "ERROR")
logging.SetLogLevel("chain", "ERROR")
logging.SetLogLevel("sub", "ERROR")
logging.SetLogLevel("storageminer", "FATAL")
test.TestDeadlineToggling(t, builder.MockSbBuilder, 2*time.Millisecond)
}

View File

@ -18,6 +18,7 @@ import (
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-storedcounter"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/client"
@ -26,6 +27,7 @@ import (
"github.com/filecoin-project/lotus/chain"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/gen"
genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/lotus/chain/messagepool"
@ -44,6 +46,7 @@ import (
"github.com/filecoin-project/lotus/node/repo"
"github.com/filecoin-project/lotus/storage/mockstorage"
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
power2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/power"
"github.com/ipfs/go-datastore"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
@ -151,6 +154,49 @@ func CreateTestStorageNode(ctx context.Context, t *testing.T, waddr address.Addr
return test.TestStorageNode{StorageMiner: minerapi, MineOne: mineOne, Stop: stop}
}
func storageBuilder(parentNode test.TestNode, mn mocknet.Mocknet, opts node.Option) test.StorageBuilder {
return func(ctx context.Context, t *testing.T, spt abi.RegisteredSealProof, owner address.Address) test.TestStorageNode {
pk, _, err := crypto.GenerateEd25519Key(rand.Reader)
require.NoError(t, err)
minerPid, err := peer.IDFromPrivateKey(pk)
require.NoError(t, err)
params, serr := actors.SerializeParams(&power2.CreateMinerParams{
Owner: owner,
Worker: owner,
SealProofType: spt,
Peer: abi.PeerID(minerPid),
})
require.NoError(t, serr)
createStorageMinerMsg := &types.Message{
To: power.Address,
From: owner,
Value: big.Zero(),
Method: power.Methods.CreateMiner,
Params: params,
GasLimit: 0,
GasPremium: big.NewInt(5252),
}
signed, err := parentNode.MpoolPushMessage(ctx, createStorageMinerMsg, nil)
require.NoError(t, err)
mw, err := parentNode.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence)
require.NoError(t, err)
require.Equal(t, exitcode.Ok, mw.Receipt.ExitCode)
var retval power2.CreateMinerReturn
err = retval.UnmarshalCBOR(bytes.NewReader(mw.Receipt.Return))
require.NoError(t, err)
return CreateTestStorageNode(ctx, t, owner, retval.IDAddress, pk, parentNode, mn, opts)
}
}
func Builder(t *testing.T, fullOpts []test.FullNodeOpts, storage []test.StorageMiner) ([]test.TestNode, []test.TestStorageNode) {
return mockBuilderOpts(t, fullOpts, storage, false)
}
@ -266,6 +312,8 @@ func mockBuilderOpts(t *testing.T, fullOpts []test.FullNodeOpts, storage []test.
if rpc {
fulls[i] = fullRpc(t, fulls[i])
}
fulls[i].Stb = storageBuilder(fulls[i], mn, node.Options())
}
for i, def := range storage {
@ -432,6 +480,14 @@ func mockSbBuilderOpts(t *testing.T, fullOpts []test.FullNodeOpts, storage []tes
if rpc {
fulls[i] = fullRpc(t, fulls[i])
}
fulls[i].Stb = storageBuilder(fulls[i], mn, node.Options(
node.Override(new(sectorstorage.SectorManager), func() (sectorstorage.SectorManager, error) {
return mock.NewMockSectorMgr(nil), nil
}),
node.Override(new(ffiwrapper.Verifier), mock.MockVerifier),
node.Unset(new(*sectorstorage.Manager)),
))
}
for i, def := range storage {