From a6d1323eba651eef409fea8446449b3c3a74e532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 26 Jun 2020 15:08:03 +0200 Subject: [PATCH] Update specs-actors to v0.7.0; More correct genesis sector import --- build/params_shared.go | 2 +- chain/gen/gen.go | 4 +- chain/gen/genesis/miners.go | 249 ++++++++++++++++++++++----------- chain/gen/genesis/t04_power.go | 2 +- chain/stmgr/utils.go | 2 +- chain/vm/vm.go | 8 ++ go.mod | 4 +- go.sum | 2 + node/impl/full/state.go | 2 +- 9 files changed, 187 insertions(+), 88 deletions(-) diff --git a/build/params_shared.go b/build/params_shared.go index 5ab07bd3f..e839b1d08 100644 --- a/build/params_shared.go +++ b/build/params_shared.go @@ -58,7 +58,7 @@ const ForkLengthThreshold = Finality var BlocksPerEpoch = uint64(builtin.ExpectedLeadersPerEpoch) // Epochs -const Finality = miner.ChainFinalityish +const Finality = miner.ChainFinality const MessageConfidence = 5 // constants for Weight calculation diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 99ac2f109..336dbd8e5 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -177,12 +177,12 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) { Accounts: []genesis.Actor{ { Type: genesis.TAccount, - Balance: types.FromFil(40000), + Balance: types.FromFil(40_000_000), Meta: (&genesis.AccountMeta{Owner: mk1}).ActorMeta(), }, { Type: genesis.TAccount, - Balance: types.FromFil(40000), + Balance: types.FromFil(40_000_000), Meta: (&genesis.AccountMeta{Owner: mk2}).ActorMeta(), }, { diff --git a/chain/gen/genesis/miners.go b/chain/gen/genesis/miners.go index acc63c31c..f4f96db98 100644 --- a/chain/gen/genesis/miners.go +++ b/chain/gen/genesis/miners.go @@ -22,7 +22,6 @@ import ( "github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/runtime" - "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" @@ -56,6 +55,14 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid return cid.Undef, xerrors.New("no genesis miners") } + minerInfos := make([]struct { + maddr address.Address + + presealExp abi.ChainEpoch + + dealIDs []abi.DealID + }, len(miners)) + for i, m := range miners { // Create miner through power actor i := i @@ -66,7 +73,6 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid return cid.Undef, err } - var maddr address.Address { constructorParams := &power.CreateMinerParams{ Owner: m.Worker, @@ -90,13 +96,20 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid if ma.IDAddress != expma { return cid.Undef, xerrors.Errorf("miner assigned wrong address: %s != %s", ma.IDAddress, expma) } - maddr = ma.IDAddress + minerInfos[i].maddr = ma.IDAddress + + err = vm.MutateState(ctx, minerInfos[i].maddr, func(cst cbor.IpldStore, st *miner.State) error { + maxPeriods := miner.MaxSectorExpirationExtension / miner.WPoStProvingPeriod + minerInfos[i].presealExp = (maxPeriods-1)*miner.WPoStProvingPeriod + st.ProvingPeriodStart - 1 + + return nil + }) } // Add market funds { - params := mustEnc(&maddr) + params := mustEnc(&minerInfos[i].maddr) _, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, m.MarketBalance, builtin.MethodsMarket.AddBalance, params) if err != nil { return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err) @@ -112,7 +125,6 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid // Publish preseal deals - var dealIDs []abi.DealID { publish := func(params *market.PublishStorageDealsParams) error { fmt.Printf("publishing %d storage deals on miner %s with worker %s\n", len(params.Deals), params.Deals[0].Proposal.Provider, m.Worker) @@ -126,7 +138,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid return xerrors.Errorf("unmarsahling publishStorageDeals result: %w", err) } - dealIDs = append(dealIDs, ids.IDs...) + minerInfos[i].dealIDs = append(minerInfos[i].dealIDs, ids.IDs...) return nil } @@ -153,93 +165,106 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid } } } + } - // Commit sectors - for pi, preseal := range m.Sectors { - preseal := preseal - // TODO: Maybe check seal (Can just be snark inputs, doesn't go into the genesis file) + // adjust total network power for equal pledge per sector + rawPow, qaPow := big.NewInt(0), big.NewInt(0) + { + for i, m := range miners { + for pi := range m.Sectors { + rawPow = types.BigAdd(rawPow, types.NewInt(uint64(m.SectorSize))) - // check deals, get dealWeight - var dealWeight market.VerifyDealsOnSectorProveCommitReturn - { - params := &market.VerifyDealsOnSectorProveCommitParams{ - DealIDs: []abi.DealID{dealIDs[pi]}, - SectorExpiry: preseal.Deal.EndEpoch, - } - - ret, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, maddr, big.Zero(), builtin.MethodsMarket.VerifyDealsOnSectorProveCommit, mustEnc(params)) + dweight, err := dealWeight(ctx, vm, minerInfos[i].maddr, []abi.DealID{minerInfos[i].dealIDs[pi]}, 0, minerInfos[i].presealExp) if err != nil { - return cid.Undef, xerrors.Errorf("failed to verify preseal deals miner: %w", err) - } - if err := dealWeight.UnmarshalCBOR(bytes.NewReader(ret)); err != nil { - return cid.Undef, xerrors.Errorf("unmarshaling market onProveCommit result: %w", err) - } - } - - // update power claims - { - err = vm.MutateState(ctx, builtin.StoragePowerActorAddr, func(cst cbor.IpldStore, st *power.State) error { - weight := &power.SectorStorageWeightDesc{ - SectorSize: m.SectorSize, - Duration: preseal.Deal.Duration(), - DealWeight: dealWeight.DealWeight, - VerifiedDealWeight: dealWeight.VerifiedDealWeight, - } - - qapower := power.QAPowerForWeight(weight) - - err := st.AddToClaim(&state.AdtStore{cst}, maddr, types.NewInt(uint64(weight.SectorSize)), qapower) - if err != nil { - return xerrors.Errorf("add to claim: %w", err) - } - fmt.Println("Added weight to claim: ", st.TotalRawBytePower, st.TotalQualityAdjPower) - return nil - }) - if err != nil { - return cid.Undef, xerrors.Errorf("register power claim in power actor: %w", err) - } - } - - // Put sectors to miner sector sets - { - newSectorInfo := &miner.SectorOnChainInfo{ - Info: miner.SectorPreCommitInfo{ - SealProof: preseal.ProofType, - SectorNumber: preseal.SectorID, - SealedCID: preseal.CommR, - SealRandEpoch: 0, - DealIDs: []abi.DealID{dealIDs[pi]}, - Expiration: preseal.Deal.EndEpoch, - }, - ActivationEpoch: 0, - DealWeight: dealWeight.DealWeight, - VerifiedDealWeight: dealWeight.VerifiedDealWeight, + return cid.Undef, xerrors.Errorf("getting deal weight: %w", err) } - err = vm.MutateState(ctx, maddr, func(cst cbor.IpldStore, st *miner.State) error { - store := &state.AdtStore{cst} + sectorWeight := miner.QAPowerForWeight(m.SectorSize, minerInfos[i].presealExp, dweight.DealWeight, dweight.VerifiedDealWeight) - if err = st.PutSector(store, newSectorInfo); err != nil { - return xerrors.Errorf("failed to put sector: %v", err) - } - - if err := st.AddNewSectors(newSectorInfo.Info.SectorNumber); err != nil { - return xerrors.Errorf("failed to add NewSector: %w", err) - } - - return nil - }) - if err != nil { - return cid.Cid{}, xerrors.Errorf("put to sset: %w", err) - } + qaPow = types.BigAdd(qaPow, sectorWeight) } } + err = vm.MutateState(ctx, builtin.StoragePowerActorAddr, func(cst cbor.IpldStore, st *power.State) error { + st.TotalQualityAdjPower = qaPow + st.TotalRawBytePower = rawPow + return nil + }) + if err != nil { + return cid.Undef, xerrors.Errorf("mutating state: %w", err) + } } - // TODO: to avoid division by zero, we set the initial power actor power to 1, this adjusts that back down so the accounting is accurate. + for i, m := range miners { + // Commit sectors + { + for pi, preseal := range m.Sectors { + params := &miner.SectorPreCommitInfo{ + SealProof: preseal.ProofType, + SectorNumber: preseal.SectorID, + SealedCID: preseal.CommR, + SealRandEpoch: -1, + DealIDs: []abi.DealID{minerInfos[i].dealIDs[pi]}, + Expiration: minerInfos[i].presealExp, // TODO: Allow setting externally! + } + + dweight, err := dealWeight(ctx, vm, minerInfos[i].maddr, params.DealIDs, 0, minerInfos[i].presealExp) + if err != nil { + return cid.Undef, xerrors.Errorf("getting deal weight: %w", err) + } + + sectorWeight := miner.QAPowerForWeight(m.SectorSize, minerInfos[i].presealExp, dweight.DealWeight, dweight.VerifiedDealWeight) + + // we've added fake power for this sector above, remove it now + err = vm.MutateState(ctx, builtin.StoragePowerActorAddr, func(cst cbor.IpldStore, st *power.State) error { + st.TotalQualityAdjPower = types.BigSub(st.TotalQualityAdjPower, sectorWeight) + st.TotalRawBytePower = types.BigSub(st.TotalRawBytePower, types.NewInt(uint64(m.SectorSize))) + return nil + }) + if err != nil { + return cid.Undef, xerrors.Errorf("removing fake power: %w", err) + } + + epochReward, err := currentEpochBlockReward(ctx, vm, minerInfos[i].maddr) + if err != nil { + return cid.Undef, xerrors.Errorf("getting current epoch reward: %w", err) + } + + tpow, err := currentTotalPower(ctx, vm, minerInfos[i].maddr) + if err != nil { + return cid.Undef, xerrors.Errorf("getting current total power: %w", err) + } + + pledge := miner.InitialPledgeForPower(sectorWeight, tpow.QualityAdjPower, tpow.PledgeCollateral, epochReward, circSupply(ctx, vm, minerInfos[i].maddr)) + + _, err = doExecValue(ctx, vm, minerInfos[i].maddr, m.Worker, pledge, builtin.MethodsMiner.PreCommitSector, mustEnc(params)) + if err != nil { + return cid.Undef, xerrors.Errorf("failed to confirm presealed sectors: %w", err) + } + + // Commit one-by-one, otherwise pledge math tends to explode + confirmParams := &builtin.ConfirmSectorProofsParams{ + Sectors: []abi.SectorNumber{preseal.SectorID}, + } + + _, err = doExecValue(ctx, vm, minerInfos[i].maddr, builtin.StoragePowerActorAddr, big.Zero(), builtin.MethodsMiner.ConfirmSectorProofsValid, mustEnc(confirmParams)) + if err != nil { + return cid.Undef, xerrors.Errorf("failed to confirm presealed sectors: %w", err) + } + } + } + } + + // Sanity-check total network power err = vm.MutateState(ctx, builtin.StoragePowerActorAddr, func(cst cbor.IpldStore, st *power.State) error { - st.TotalQualityAdjPower = big.Sub(st.TotalQualityAdjPower, big.NewInt(1)) + if !st.TotalRawBytePower.Equals(rawPow) { + return xerrors.Errorf("st.TotalRawBytePower doesn't match previously calculated rawPow") + } + + if !st.TotalQualityAdjPower.Equals(qaPow) { + return xerrors.Errorf("st.TotalQualityAdjPower doesn't match previously calculated qaPow") + } + return nil }) if err != nil { @@ -261,3 +286,65 @@ func (fr *fakeRand) GetRandomness(ctx context.Context, personalization crypto.Do _, _ = rand.New(rand.NewSource(int64(randEpoch))).Read(out) return out, nil } + +func currentTotalPower(ctx context.Context, vm *vm.VM, maddr address.Address) (*power.CurrentTotalPowerReturn, error) { + pwret, err := doExecValue(ctx, vm, builtin.StoragePowerActorAddr, maddr, big.Zero(), builtin.MethodsPower.CurrentTotalPower, nil) + if err != nil { + return nil, err + } + var pwr power.CurrentTotalPowerReturn + if err := pwr.UnmarshalCBOR(bytes.NewReader(pwret)); err != nil { + return nil, err + } + + return &pwr, nil +} + +func dealWeight(ctx context.Context, vm *vm.VM, maddr address.Address, dealIDs []abi.DealID, sectorStart, sectorExpiry abi.ChainEpoch) (market.VerifyDealsForActivationReturn, error) { + params := &market.VerifyDealsForActivationParams{ + DealIDs: dealIDs, + SectorStart: sectorStart, + SectorExpiry: sectorExpiry, + } + + var dealWeights market.VerifyDealsForActivationReturn + ret, err := doExecValue(ctx, vm, + builtin.StorageMarketActorAddr, + maddr, + abi.NewTokenAmount(0), + builtin.MethodsMarket.VerifyDealsForActivation, + mustEnc(params), + ) + if err != nil { + return market.VerifyDealsForActivationReturn{}, err + } + if err := dealWeights.UnmarshalCBOR(bytes.NewReader(ret)); err != nil { + return market.VerifyDealsForActivationReturn{}, err + } + + return dealWeights, nil +} + +func currentEpochBlockReward(ctx context.Context, vm *vm.VM, maddr address.Address) (abi.TokenAmount, error) { + rwret, err := doExecValue(ctx, vm, builtin.RewardActorAddr, maddr, big.Zero(), builtin.MethodsReward.LastPerEpochReward, nil) + if err != nil { + return abi.TokenAmount{}, err + } + + epochReward := abi.NewTokenAmount(0) + if err := epochReward.UnmarshalCBOR(bytes.NewReader(rwret)); err != nil { + return abi.TokenAmount{}, err + } + + return epochReward, nil +} + +func circSupply(ctx context.Context, vmi *vm.VM, maddr address.Address) abi.TokenAmount { + unsafeVM := &vm.UnsafeVM{VM: vmi} + rt := unsafeVM.MakeRuntime(ctx, &types.Message{ + GasLimit: 1_000_000_000, + From: maddr, + }, maddr, 0, 0, 0) + + return rt.TotalFilCircSupply() +} diff --git a/chain/gen/genesis/t04_power.go b/chain/gen/genesis/t04_power.go index 136026977..de87871ce 100644 --- a/chain/gen/genesis/t04_power.go +++ b/chain/gen/genesis/t04_power.go @@ -24,7 +24,7 @@ func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) { sms := &power.State{ TotalRawBytePower: big.NewInt(0), - TotalQualityAdjPower: big.NewInt(1), // TODO: has to be 1 initially to avoid div by zero. Kinda annoying, should find a way to fix + TotalQualityAdjPower: big.NewInt(0), TotalPledgeCollateral: big.NewInt(0), MinerCount: 0, CronEventQueue: emptyhamt, diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index cf424b4eb..eae75f079 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -208,7 +208,7 @@ func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *S out[i] = abi.SectorInfo{ SealProof: spt, SectorNumber: sectorSet[n].ID, - SealedCID: sectorSet[n].Info.Info.SealedCID, + SealedCID: sectorSet[n].Info.SealedCID, } } diff --git a/chain/vm/vm.go b/chain/vm/vm.go index 9a4c9991d..7014dc281 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -126,6 +126,14 @@ func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin addres return rt } +type UnsafeVM struct { + VM *VM +} + +func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message, origin address.Address, originNonce uint64, usedGas int64, nac uint64) *Runtime { + return vm.VM.makeRuntime(ctx, msg, origin, originNonce, usedGas, nac) +} + type VM struct { cstate *state.StateTree base cid.Cid diff --git a/go.mod b/go.mod index 7d25c03c1..c6b39b293 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/filecoin-project/go-statestore v0.1.0 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b github.com/filecoin-project/sector-storage v0.0.0-20200626110003-76ce3b9d9496 - github.com/filecoin-project/specs-actors v0.6.2-0.20200617175406-de392ca14121 + github.com/filecoin-project/specs-actors v0.7.0 github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea github.com/filecoin-project/storage-fsm v0.0.0-20200626110227-c059934fe82e github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 @@ -128,3 +128,5 @@ require ( replace github.com/golangci/golangci-lint => github.com/golangci/golangci-lint v1.18.0 replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi + +replace github.com/filecoin-project/storage-fsm => /home/magik6k/gohack/github.com/filecoin-project/storage-fsm diff --git a/go.sum b/go.sum index 03b4a1b23..be6fd1f1f 100644 --- a/go.sum +++ b/go.sum @@ -261,6 +261,8 @@ github.com/filecoin-project/specs-actors v0.3.0/go.mod h1:nQYnFbQ7Y0bHZyq6HDEuVl github.com/filecoin-project/specs-actors v0.6.0/go.mod h1:dRdy3cURykh2R8O/DKqy8olScl70rmIS7GrB4hB1IDY= github.com/filecoin-project/specs-actors v0.6.2-0.20200617175406-de392ca14121 h1:oRA+b4iN4H86xXDXbU3TOyvmBZp7//c5VqTc0oJ6nLg= github.com/filecoin-project/specs-actors v0.6.2-0.20200617175406-de392ca14121/go.mod h1:dRdy3cURykh2R8O/DKqy8olScl70rmIS7GrB4hB1IDY= +github.com/filecoin-project/specs-actors v0.7.0 h1:tldjW8pFiJcMtyGPsXmPoFdbN/18mKW3BpEMlO4NJAc= +github.com/filecoin-project/specs-actors v0.7.0/go.mod h1:+z0htZu/wLBDbOLcQTKKUEC2rkUTFzL2KJ/bRAVWkws= github.com/filecoin-project/specs-storage v0.1.0 h1:PkDgTOT5W5Ao7752onjDl4QSv+sgOVdJbvFjOnD5w94= github.com/filecoin-project/specs-storage v0.1.0/go.mod h1:Pr5ntAaxsh+sLG/LYiL4tKzvA83Vk5vLODYhfNwOg7k= github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea h1:iixjULRQFPn7Q9KlIqfwLJnlAXO10bbkI+xy5GKGdLY= diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 048ae7858..642e66234 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -753,7 +753,7 @@ func (a *StateAPI) StateMinerInitialPledgeCollateral(ctx context.Context, maddr return types.EmptyInt, err } - params, err := actors.SerializeParams(&power.OnSectorProveCommitParams{ + params, err := actors.SerializeParams(&power.Sea{ Weight: power.SectorStorageWeightDesc{ SectorSize: ssize, Duration: precommit.Info.Expiration - ts.Height(), // NB: not exactly accurate, but should always lead us to *over* estimate, not under