From 1449644c343340a60d80688931cd709d85220686 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Thu, 4 Nov 2021 15:59:29 +0000 Subject: [PATCH 01/12] Integrate v7 actors --- build/openrpc/full.json.gz | Bin 25453 -> 25453 bytes build/params_2k.go | 2 + build/params_butterfly.go | 1 + build/params_calibnet.go | 2 + build/params_interop.go | 1 + build/params_mainnet.go | 10 +- build/params_shared_vals.go | 2 +- build/params_testground.go | 1 + chain/actors/builtin/account/account.go | 15 + chain/actors/builtin/account/v7.go | 40 ++ chain/actors/builtin/builtin.go | 60 +- chain/actors/builtin/cron/cron.go | 12 +- chain/actors/builtin/cron/v7.go | 35 ++ chain/actors/builtin/init/init.go | 19 +- chain/actors/builtin/init/v7.go | 114 ++++ chain/actors/builtin/market/market.go | 22 +- chain/actors/builtin/market/v7.go | 252 ++++++++ chain/actors/builtin/miner/miner.go | 17 +- chain/actors/builtin/miner/v7.go | 570 ++++++++++++++++++ chain/actors/builtin/multisig/message7.go | 71 +++ chain/actors/builtin/multisig/multisig.go | 32 +- chain/actors/builtin/multisig/v7.go | 119 ++++ chain/actors/builtin/paych/message7.go | 74 +++ chain/actors/builtin/paych/paych.go | 20 +- chain/actors/builtin/paych/v7.go | 114 ++++ chain/actors/builtin/power/power.go | 19 +- chain/actors/builtin/power/v7.go | 187 ++++++ chain/actors/builtin/reward/reward.go | 19 +- chain/actors/builtin/reward/v7.go | 98 +++ chain/actors/builtin/system/system.go | 10 +- chain/actors/builtin/system/v7.go | 35 ++ chain/actors/builtin/verifreg/v7.go | 75 +++ chain/actors/builtin/verifreg/verifreg.go | 19 +- chain/actors/policy/policy.go | 84 ++- chain/actors/version.go | 7 +- chain/consensus/filcns/compute_state.go | 2 + chain/consensus/filcns/upgrades.go | 108 +++- chain/gen/gen.go | 6 + chain/gen/genesis/miners.go | 7 +- chain/state/statetree.go | 2 +- chain/vm/gas.go | 31 +- chain/vm/gas_v0.go | 15 +- chain/vm/invoker.go | 2 +- chain/vm/mkactor.go | 3 + chain/vm/runtime.go | 8 +- chain/vm/syscalls.go | 40 +- cmd/lotus-bench/caching_verifier.go | 9 +- cmd/lotus-sim/simulation/mock/mock.go | 8 + documentation/en/api-v0-methods.md | 2 +- documentation/en/api-v1-unstable-methods.md | 2 +- extern/sector-storage/ffiwrapper/types.go | 3 + .../sector-storage/ffiwrapper/verifier_cgo.go | 7 + extern/sector-storage/mock/mock.go | 7 + gen/inlinegen-data.json | 8 +- go.mod | 1 + go.sum | 5 + itests/kit/ensemble_opts_nv.go | 6 +- lotuspond/front/src/chain/methods.json | 107 ++++ storage/wdpost_run_test.go | 18 +- testplans/lotus-soup/go.mod | 20 +- testplans/lotus-soup/go.sum | 131 ++++ 61 files changed, 2595 insertions(+), 121 deletions(-) create mode 100644 chain/actors/builtin/account/v7.go create mode 100644 chain/actors/builtin/cron/v7.go create mode 100644 chain/actors/builtin/init/v7.go create mode 100644 chain/actors/builtin/market/v7.go create mode 100644 chain/actors/builtin/miner/v7.go create mode 100644 chain/actors/builtin/multisig/message7.go create mode 100644 chain/actors/builtin/multisig/v7.go create mode 100644 chain/actors/builtin/paych/message7.go create mode 100644 chain/actors/builtin/paych/v7.go create mode 100644 chain/actors/builtin/power/v7.go create mode 100644 chain/actors/builtin/reward/v7.go create mode 100644 chain/actors/builtin/system/v7.go create mode 100644 chain/actors/builtin/verifreg/v7.go diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 1578d746536613ea03a22c6165e5561d65e3df7a..8f71ee8a973b9f29d91d16893c3cbe8bf3db8356 100644 GIT binary patch delta 5087 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 B;#2?t delta 5127 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 diff --git a/build/params_2k.go b/build/params_2k.go index b9db0a467..84023c38c 100644 --- a/build/params_2k.go +++ b/build/params_2k.go @@ -47,6 +47,8 @@ var UpgradeHyperdriveHeight = abi.ChainEpoch(-16) var UpgradeChocolateHeight = abi.ChainEpoch(-17) +var UpgradeSnapDealsHeight = abi.ChainEpoch(-18) + var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, } diff --git a/build/params_butterfly.go b/build/params_butterfly.go index 9a0018e73..e26fd78fa 100644 --- a/build/params_butterfly.go +++ b/build/params_butterfly.go @@ -41,6 +41,7 @@ const UpgradeNorwegianHeight = -14 const UpgradeTurboHeight = -15 const UpgradeHyperdriveHeight = -16 const UpgradeChocolateHeight = 6360 +const UpgradeSnapDealsHeight = 99999999 func init() { policy.SetConsensusMinerMinPower(abi.NewStoragePower(2 << 30)) diff --git a/build/params_calibnet.go b/build/params_calibnet.go index 8cd99d642..16d77c7e6 100644 --- a/build/params_calibnet.go +++ b/build/params_calibnet.go @@ -54,6 +54,8 @@ const UpgradeHyperdriveHeight = 420 const UpgradeChocolateHeight = 312746 +const UpgradeSnapDealsHeight = 99999999 + func init() { policy.SetConsensusMinerMinPower(abi.NewStoragePower(32 << 30)) policy.SetSupportedProofTypes( diff --git a/build/params_interop.go b/build/params_interop.go index de5ee9a12..66033937c 100644 --- a/build/params_interop.go +++ b/build/params_interop.go @@ -47,6 +47,7 @@ var UpgradeTurboHeight = abi.ChainEpoch(-15) var UpgradeHyperdriveHeight = abi.ChainEpoch(-16) var UpgradeChocolateHeight = abi.ChainEpoch(-17) +var UpgradeSnapDealsHeight = abi.ChainEpoch(-18) var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, diff --git a/build/params_mainnet.go b/build/params_mainnet.go index 0c8c53ba8..a4781f1ff 100644 --- a/build/params_mainnet.go +++ b/build/params_mainnet.go @@ -62,18 +62,20 @@ const UpgradeNorwegianHeight = 665280 const UpgradeTurboHeight = 712320 // 2021-06-30T22:00:00Z -var UpgradeHyperdriveHeight = abi.ChainEpoch(892800) +const UpgradeHyperdriveHeight = 892800 // 2021-10-26T13:30:00Z -var UpgradeChocolateHeight = abi.ChainEpoch(1231620) +const UpgradeChocolateHeight = 1231620 + +var UpgradeSnapDealsHeight = abi.ChainEpoch(999999999999) func init() { if os.Getenv("LOTUS_USE_TEST_ADDRESSES") != "1" { SetAddressNetwork(address.Mainnet) } - if os.Getenv("LOTUS_DISABLE_CHOCOLATE") == "1" { - UpgradeChocolateHeight = math.MaxInt64 + if os.Getenv("LOTUS_DISABLE_SNAPDEALS") == "1" { + UpgradeSnapDealsHeight = math.MaxInt64 } Devnet = false diff --git a/build/params_shared_vals.go b/build/params_shared_vals.go index 0a242f6f2..704c84639 100644 --- a/build/params_shared_vals.go +++ b/build/params_shared_vals.go @@ -34,7 +34,7 @@ const NewestNetworkVersion = network.Version{{.latestNetworkVersion}} /* inline-gen start */ -const NewestNetworkVersion = network.Version14 +const NewestNetworkVersion = network.Version15 /* inline-gen end */ diff --git a/build/params_testground.go b/build/params_testground.go index 48b76f82c..539e06b45 100644 --- a/build/params_testground.go +++ b/build/params_testground.go @@ -99,6 +99,7 @@ var ( UpgradeTurboHeight abi.ChainEpoch = -14 UpgradeHyperdriveHeight abi.ChainEpoch = -15 UpgradeChocolateHeight abi.ChainEpoch = -16 + UpgradeSnapDealsHeight abi.ChainEpoch = -17 DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, diff --git a/chain/actors/builtin/account/account.go b/chain/actors/builtin/account/account.go index 249ce133f..57ea510bb 100644 --- a/chain/actors/builtin/account/account.go +++ b/chain/actors/builtin/account/account.go @@ -23,6 +23,8 @@ import ( builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" ) func init() { @@ -50,6 +52,10 @@ func init() { builtin.RegisterActorState(builtin6.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load6(store, root) }) + + builtin.RegisterActorState(builtin7.AccountActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load7(store, root) + }) } var Methods = builtin4.MethodsAccount @@ -75,6 +81,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin6.AccountActorCodeID: return load6(store, act.Head) + case builtin7.AccountActorCodeID: + return load7(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } @@ -100,6 +109,9 @@ func MakeState(store adt.Store, av actors.Version, addr address.Address) (State, case actors.Version6: return make6(store, addr) + case actors.Version7: + return make7(store, addr) + } return nil, xerrors.Errorf("unknown actor version %d", av) } @@ -125,6 +137,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { case actors.Version6: return builtin6.AccountActorCodeID, nil + case actors.Version7: + return builtin7.AccountActorCodeID, nil + } return cid.Undef, xerrors.Errorf("unknown actor version %d", av) diff --git a/chain/actors/builtin/account/v7.go b/chain/actors/builtin/account/v7.go new file mode 100644 index 000000000..883776cf8 --- /dev/null +++ b/chain/actors/builtin/account/v7.go @@ -0,0 +1,40 @@ +package account + +import ( + "github.com/filecoin-project/go-address" + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/lotus/chain/actors/adt" + + account7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/account" +) + +var _ State = (*state7)(nil) + +func load7(store adt.Store, root cid.Cid) (State, error) { + out := state7{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +func make7(store adt.Store, addr address.Address) (State, error) { + out := state7{store: store} + out.State = account7.State{Address: addr} + return &out, nil +} + +type state7 struct { + account7.State + store adt.Store +} + +func (s *state7) PubkeyAddress() (address.Address, error) { + return s.Address, nil +} + +func (s *state7) GetState() interface{} { + return &s.State +} diff --git a/chain/actors/builtin/builtin.go b/chain/actors/builtin/builtin.go index ebfe2df2e..d93732999 100644 --- a/chain/actors/builtin/builtin.go +++ b/chain/actors/builtin/builtin.go @@ -23,46 +23,49 @@ import ( builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" smoothing6 "github.com/filecoin-project/specs-actors/v6/actors/util/smoothing" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + smoothing7 "github.com/filecoin-project/specs-actors/v7/actors/util/smoothing" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/cbor" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" - miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner" - proof6 "github.com/filecoin-project/specs-actors/v6/actors/runtime/proof" + miner7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/miner" + proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" ) -var SystemActorAddr = builtin6.SystemActorAddr -var BurntFundsActorAddr = builtin6.BurntFundsActorAddr -var CronActorAddr = builtin6.CronActorAddr +var SystemActorAddr = builtin7.SystemActorAddr +var BurntFundsActorAddr = builtin7.BurntFundsActorAddr +var CronActorAddr = builtin7.CronActorAddr var SaftAddress = makeAddress("t0122") var ReserveAddress = makeAddress("t090") var RootVerifierAddress = makeAddress("t080") var ( - ExpectedLeadersPerEpoch = builtin6.ExpectedLeadersPerEpoch + ExpectedLeadersPerEpoch = builtin7.ExpectedLeadersPerEpoch ) const ( - EpochDurationSeconds = builtin6.EpochDurationSeconds - EpochsInDay = builtin6.EpochsInDay - SecondsInDay = builtin6.SecondsInDay + EpochDurationSeconds = builtin7.EpochDurationSeconds + EpochsInDay = builtin7.EpochsInDay + SecondsInDay = builtin7.SecondsInDay ) const ( - MethodSend = builtin6.MethodSend - MethodConstructor = builtin6.MethodConstructor + MethodSend = builtin7.MethodSend + MethodConstructor = builtin7.MethodConstructor ) // These are all just type aliases across actor versions. In the future, that might change // and we might need to do something fancier. -type SectorInfo = proof6.SectorInfo -type PoStProof = proof6.PoStProof +type SectorInfo = proof7.SectorInfo +type PoStProof = proof7.PoStProof type FilterEstimate = smoothing0.FilterEstimate func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower { - return miner6.QAPowerForWeight(size, duration, dealWeight, verifiedWeight) + return miner7.QAPowerForWeight(size, duration, dealWeight, verifiedWeight) } func FromV0FilterEstimate(v0 smoothing0.FilterEstimate) FilterEstimate { @@ -101,6 +104,12 @@ func FromV6FilterEstimate(v6 smoothing6.FilterEstimate) FilterEstimate { } +func FromV7FilterEstimate(v7 smoothing7.FilterEstimate) FilterEstimate { + + return (FilterEstimate)(v7) + +} + type ActorStateLoader func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) var ActorStateLoaders = make(map[cid.Cid]ActorStateLoader) @@ -138,6 +147,9 @@ func ActorNameByCode(c cid.Cid) string { case builtin6.IsBuiltinActor(c): return builtin6.ActorNameByCode(c) + case builtin7.IsBuiltinActor(c): + return builtin7.ActorNameByCode(c) + default: return "" } @@ -169,6 +181,10 @@ func IsBuiltinActor(c cid.Cid) bool { return true } + if builtin7.IsBuiltinActor(c) { + return true + } + return false } @@ -198,6 +214,10 @@ func IsAccountActor(c cid.Cid) bool { return true } + if c == builtin7.AccountActorCodeID { + return true + } + return false } @@ -227,6 +247,10 @@ func IsStorageMinerActor(c cid.Cid) bool { return true } + if c == builtin7.StorageMinerActorCodeID { + return true + } + return false } @@ -256,6 +280,10 @@ func IsMultisigActor(c cid.Cid) bool { return true } + if c == builtin7.MultisigActorCodeID { + return true + } + return false } @@ -285,6 +313,10 @@ func IsPaymentChannelActor(c cid.Cid) bool { return true } + if c == builtin7.PaymentChannelActorCodeID { + return true + } + return false } diff --git a/chain/actors/builtin/cron/cron.go b/chain/actors/builtin/cron/cron.go index 9178a44ab..f27a14ac7 100644 --- a/chain/actors/builtin/cron/cron.go +++ b/chain/actors/builtin/cron/cron.go @@ -17,6 +17,8 @@ import ( builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" ) func MakeState(store adt.Store, av actors.Version) (State, error) { @@ -40,6 +42,9 @@ func MakeState(store adt.Store, av actors.Version) (State, error) { case actors.Version6: return make6(store) + case actors.Version7: + return make7(store) + } return nil, xerrors.Errorf("unknown actor version %d", av) } @@ -65,14 +70,17 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { case actors.Version6: return builtin6.CronActorCodeID, nil + case actors.Version7: + return builtin7.CronActorCodeID, nil + } return cid.Undef, xerrors.Errorf("unknown actor version %d", av) } var ( - Address = builtin6.CronActorAddr - Methods = builtin6.MethodsCron + Address = builtin7.CronActorAddr + Methods = builtin7.MethodsCron ) type State interface { diff --git a/chain/actors/builtin/cron/v7.go b/chain/actors/builtin/cron/v7.go new file mode 100644 index 000000000..e5538c89f --- /dev/null +++ b/chain/actors/builtin/cron/v7.go @@ -0,0 +1,35 @@ +package cron + +import ( + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/lotus/chain/actors/adt" + + cron7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/cron" +) + +var _ State = (*state7)(nil) + +func load7(store adt.Store, root cid.Cid) (State, error) { + out := state7{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +func make7(store adt.Store) (State, error) { + out := state7{store: store} + out.State = *cron7.ConstructState(cron7.BuiltInEntries()) + return &out, nil +} + +type state7 struct { + cron7.State + store adt.Store +} + +func (s *state7) GetState() interface{} { + return &s.State +} diff --git a/chain/actors/builtin/init/init.go b/chain/actors/builtin/init/init.go index ee06eeab7..737241ffe 100644 --- a/chain/actors/builtin/init/init.go +++ b/chain/actors/builtin/init/init.go @@ -25,6 +25,8 @@ import ( builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" ) func init() { @@ -52,11 +54,15 @@ func init() { builtin.RegisterActorState(builtin6.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load6(store, root) }) + + builtin.RegisterActorState(builtin7.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load7(store, root) + }) } var ( - Address = builtin6.InitActorAddr - Methods = builtin6.MethodsInit + Address = builtin7.InitActorAddr + Methods = builtin7.MethodsInit ) func Load(store adt.Store, act *types.Actor) (State, error) { @@ -80,6 +86,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin6.InitActorCodeID: return load6(store, act.Head) + case builtin7.InitActorCodeID: + return load7(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } @@ -105,6 +114,9 @@ func MakeState(store adt.Store, av actors.Version, networkName string) (State, e case actors.Version6: return make6(store, networkName) + case actors.Version7: + return make7(store, networkName) + } return nil, xerrors.Errorf("unknown actor version %d", av) } @@ -130,6 +142,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { case actors.Version6: return builtin6.InitActorCodeID, nil + case actors.Version7: + return builtin7.InitActorCodeID, nil + } return cid.Undef, xerrors.Errorf("unknown actor version %d", av) diff --git a/chain/actors/builtin/init/v7.go b/chain/actors/builtin/init/v7.go new file mode 100644 index 000000000..341aa52cd --- /dev/null +++ b/chain/actors/builtin/init/v7.go @@ -0,0 +1,114 @@ +package init + +import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/node/modules/dtypes" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + + init7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/init" + adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" +) + +var _ State = (*state7)(nil) + +func load7(store adt.Store, root cid.Cid) (State, error) { + out := state7{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +func make7(store adt.Store, networkName string) (State, error) { + out := state7{store: store} + + s, err := init7.ConstructState(store, networkName) + if err != nil { + return nil, err + } + + out.State = *s + + return &out, nil +} + +type state7 struct { + init7.State + store adt.Store +} + +func (s *state7) ResolveAddress(address address.Address) (address.Address, bool, error) { + return s.State.ResolveAddress(s.store, address) +} + +func (s *state7) MapAddressToNewID(address address.Address) (address.Address, error) { + return s.State.MapAddressToNewID(s.store, address) +} + +func (s *state7) ForEachActor(cb func(id abi.ActorID, address address.Address) error) error { + addrs, err := adt7.AsMap(s.store, s.State.AddressMap, builtin7.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 *state7) NetworkName() (dtypes.NetworkName, error) { + return dtypes.NetworkName(s.State.NetworkName), nil +} + +func (s *state7) SetNetworkName(name string) error { + s.State.NetworkName = name + return nil +} + +func (s *state7) SetNextID(id abi.ActorID) error { + s.State.NextID = id + return nil +} + +func (s *state7) Remove(addrs ...address.Address) (err error) { + m, err := adt7.AsMap(s.store, s.State.AddressMap, builtin7.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 *state7) SetAddressMap(mcid cid.Cid) error { + s.State.AddressMap = mcid + return nil +} + +func (s *state7) AddressMap() (adt.Map, error) { + return adt7.AsMap(s.store, s.State.AddressMap, builtin7.DefaultHamtBitwidth) +} + +func (s *state7) GetState() interface{} { + return &s.State +} diff --git a/chain/actors/builtin/market/market.go b/chain/actors/builtin/market/market.go index 7e35f3919..6781b55e3 100644 --- a/chain/actors/builtin/market/market.go +++ b/chain/actors/builtin/market/market.go @@ -25,6 +25,8 @@ import ( builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -56,11 +58,15 @@ func init() { builtin.RegisterActorState(builtin6.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load6(store, root) }) + + builtin.RegisterActorState(builtin7.StorageMarketActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load7(store, root) + }) } var ( - Address = builtin6.StorageMarketActorAddr - Methods = builtin6.MethodsMarket + Address = builtin7.StorageMarketActorAddr + Methods = builtin7.MethodsMarket ) func Load(store adt.Store, act *types.Actor) (State, error) { @@ -84,6 +90,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin6.StorageMarketActorCodeID: return load6(store, act.Head) + case builtin7.StorageMarketActorCodeID: + return load7(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } @@ -109,6 +118,9 @@ func MakeState(store adt.Store, av actors.Version) (State, error) { case actors.Version6: return make6(store) + case actors.Version7: + return make7(store) + } return nil, xerrors.Errorf("unknown actor version %d", av) } @@ -134,6 +146,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { case actors.Version6: return builtin6.StorageMarketActorCodeID, nil + case actors.Version7: + return builtin7.StorageMarketActorCodeID, nil + } return cid.Undef, xerrors.Errorf("unknown actor version %d", av) @@ -211,6 +226,9 @@ func DecodePublishStorageDealsReturn(b []byte, nv network.Version) (PublishStora case actors.Version6: return decodePublishStorageDealsReturn6(b) + case actors.Version7: + return decodePublishStorageDealsReturn7(b) + } return nil, xerrors.Errorf("unknown actor version %d", av) } diff --git a/chain/actors/builtin/market/v7.go b/chain/actors/builtin/market/v7.go new file mode 100644 index 000000000..553913146 --- /dev/null +++ b/chain/actors/builtin/market/v7.go @@ -0,0 +1,252 @@ +package market + +import ( + "bytes" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/types" + + market7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/market" + adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" +) + +var _ State = (*state7)(nil) + +func load7(store adt.Store, root cid.Cid) (State, error) { + out := state7{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +func make7(store adt.Store) (State, error) { + out := state7{store: store} + + s, err := market7.ConstructState(store) + if err != nil { + return nil, err + } + + out.State = *s + + return &out, nil +} + +type state7 struct { + market7.State + store adt.Store +} + +func (s *state7) TotalLocked() (abi.TokenAmount, error) { + fml := types.BigAdd(s.TotalClientLockedCollateral, s.TotalProviderLockedCollateral) + fml = types.BigAdd(fml, s.TotalClientStorageFee) + return fml, nil +} + +func (s *state7) BalancesChanged(otherState State) (bool, error) { + otherState7, ok := otherState.(*state7) + 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(otherState7.State.EscrowTable) || !s.State.LockedTable.Equals(otherState7.State.LockedTable), nil +} + +func (s *state7) StatesChanged(otherState State) (bool, error) { + otherState7, ok := otherState.(*state7) + 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(otherState7.State.States), nil +} + +func (s *state7) States() (DealStates, error) { + stateArray, err := adt7.AsArray(s.store, s.State.States, market7.StatesAmtBitwidth) + if err != nil { + return nil, err + } + return &dealStates7{stateArray}, nil +} + +func (s *state7) ProposalsChanged(otherState State) (bool, error) { + otherState7, ok := otherState.(*state7) + 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(otherState7.State.Proposals), nil +} + +func (s *state7) Proposals() (DealProposals, error) { + proposalArray, err := adt7.AsArray(s.store, s.State.Proposals, market7.ProposalsAmtBitwidth) + if err != nil { + return nil, err + } + return &dealProposals7{proposalArray}, nil +} + +func (s *state7) EscrowTable() (BalanceTable, error) { + bt, err := adt7.AsBalanceTable(s.store, s.State.EscrowTable) + if err != nil { + return nil, err + } + return &balanceTable7{bt}, nil +} + +func (s *state7) LockedTable() (BalanceTable, error) { + bt, err := adt7.AsBalanceTable(s.store, s.State.LockedTable) + if err != nil { + return nil, err + } + return &balanceTable7{bt}, nil +} + +func (s *state7) VerifyDealsForActivation( + minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch, +) (weight, verifiedWeight abi.DealWeight, err error) { + w, vw, _, err := market7.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch) + return w, vw, err +} + +func (s *state7) NextID() (abi.DealID, error) { + return s.State.NextID, nil +} + +type balanceTable7 struct { + *adt7.BalanceTable +} + +func (bt *balanceTable7) ForEach(cb func(address.Address, abi.TokenAmount) error) error { + asMap := (*adt7.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 dealStates7 struct { + adt.Array +} + +func (s *dealStates7) Get(dealID abi.DealID) (*DealState, bool, error) { + var deal7 market7.DealState + found, err := s.Array.Get(uint64(dealID), &deal7) + if err != nil { + return nil, false, err + } + if !found { + return nil, false, nil + } + deal := fromV7DealState(deal7) + return &deal, true, nil +} + +func (s *dealStates7) ForEach(cb func(dealID abi.DealID, ds DealState) error) error { + var ds7 market7.DealState + return s.Array.ForEach(&ds7, func(idx int64) error { + return cb(abi.DealID(idx), fromV7DealState(ds7)) + }) +} + +func (s *dealStates7) decode(val *cbg.Deferred) (*DealState, error) { + var ds7 market7.DealState + if err := ds7.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return nil, err + } + ds := fromV7DealState(ds7) + return &ds, nil +} + +func (s *dealStates7) array() adt.Array { + return s.Array +} + +func fromV7DealState(v7 market7.DealState) DealState { + return (DealState)(v7) +} + +type dealProposals7 struct { + adt.Array +} + +func (s *dealProposals7) Get(dealID abi.DealID) (*DealProposal, bool, error) { + var proposal7 market7.DealProposal + found, err := s.Array.Get(uint64(dealID), &proposal7) + if err != nil { + return nil, false, err + } + if !found { + return nil, false, nil + } + proposal := fromV7DealProposal(proposal7) + return &proposal, true, nil +} + +func (s *dealProposals7) ForEach(cb func(dealID abi.DealID, dp DealProposal) error) error { + var dp7 market7.DealProposal + return s.Array.ForEach(&dp7, func(idx int64) error { + return cb(abi.DealID(idx), fromV7DealProposal(dp7)) + }) +} + +func (s *dealProposals7) decode(val *cbg.Deferred) (*DealProposal, error) { + var dp7 market7.DealProposal + if err := dp7.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return nil, err + } + dp := fromV7DealProposal(dp7) + return &dp, nil +} + +func (s *dealProposals7) array() adt.Array { + return s.Array +} + +func fromV7DealProposal(v7 market7.DealProposal) DealProposal { + return (DealProposal)(v7) +} + +func (s *state7) GetState() interface{} { + return &s.State +} + +var _ PublishStorageDealsReturn = (*publishStorageDealsReturn7)(nil) + +func decodePublishStorageDealsReturn7(b []byte) (PublishStorageDealsReturn, error) { + var retval market7.PublishStorageDealsReturn + if err := retval.UnmarshalCBOR(bytes.NewReader(b)); err != nil { + return nil, xerrors.Errorf("failed to unmarshal PublishStorageDealsReturn: %w", err) + } + + return &publishStorageDealsReturn7{retval}, nil +} + +type publishStorageDealsReturn7 struct { + market7.PublishStorageDealsReturn +} + +func (r *publishStorageDealsReturn7) IsDealValid(index uint64) (bool, error) { + + return r.ValidDeals.IsSet(index) + +} + +func (r *publishStorageDealsReturn7) DealIDs() ([]abi.DealID, error) { + return r.IDs, nil +} diff --git a/chain/actors/builtin/miner/miner.go b/chain/actors/builtin/miner/miner.go index 1c7f47e11..f6d633880 100644 --- a/chain/actors/builtin/miner/miner.go +++ b/chain/actors/builtin/miner/miner.go @@ -35,6 +35,8 @@ import ( builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" ) func init() { @@ -63,9 +65,13 @@ func init() { return load6(store, root) }) + builtin.RegisterActorState(builtin7.StorageMinerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load7(store, root) + }) + } -var Methods = builtin6.MethodsMiner +var Methods = builtin7.MethodsMiner // Unchanged between v0, v2, v3, v4, and v5 actors var WPoStProvingPeriod = miner0.WPoStProvingPeriod @@ -102,6 +108,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin6.StorageMinerActorCodeID: return load6(store, act.Head) + case builtin7.StorageMinerActorCodeID: + return load7(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } @@ -127,6 +136,9 @@ func MakeState(store adt.Store, av actors.Version) (State, error) { case actors.Version6: return make6(store) + case actors.Version7: + return make7(store) + } return nil, xerrors.Errorf("unknown actor version %d", av) } @@ -152,6 +164,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { case actors.Version6: return builtin6.StorageMinerActorCodeID, nil + case actors.Version7: + return builtin7.StorageMinerActorCodeID, nil + } return cid.Undef, xerrors.Errorf("unknown actor version %d", av) diff --git a/chain/actors/builtin/miner/v7.go b/chain/actors/builtin/miner/v7.go new file mode 100644 index 000000000..c7096a781 --- /dev/null +++ b/chain/actors/builtin/miner/v7.go @@ -0,0 +1,570 @@ +package miner + +import ( + "bytes" + "errors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-bitfield" + rle "github.com/filecoin-project/go-bitfield/rle" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/dline" + "github.com/ipfs/go-cid" + "github.com/libp2p/go-libp2p-core/peer" + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/chain/actors/adt" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + + miner7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/miner" + adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" +) + +var _ State = (*state7)(nil) + +func load7(store adt.Store, root cid.Cid) (State, error) { + out := state7{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +func make7(store adt.Store) (State, error) { + out := state7{store: store} + out.State = miner7.State{} + return &out, nil +} + +type state7 struct { + miner7.State + store adt.Store +} + +type deadline7 struct { + miner7.Deadline + store adt.Store +} + +type partition7 struct { + miner7.Partition + store adt.Store +} + +func (s *state7) 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 *state7) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) { + return s.CheckVestedFunds(s.store, epoch) +} + +func (s *state7) LockedFunds() (LockedFunds, error) { + return LockedFunds{ + VestingFunds: s.State.LockedFunds, + InitialPledgeRequirement: s.State.InitialPledge, + PreCommitDeposits: s.State.PreCommitDeposits, + }, nil +} + +func (s *state7) FeeDebt() (abi.TokenAmount, error) { + return s.State.FeeDebt, nil +} + +func (s *state7) InitialPledge() (abi.TokenAmount, error) { + return s.State.InitialPledge, nil +} + +func (s *state7) PreCommitDeposits() (abi.TokenAmount, error) { + return s.State.PreCommitDeposits, nil +} + +func (s *state7) GetSector(num abi.SectorNumber) (*SectorOnChainInfo, error) { + info, ok, err := s.State.GetSector(s.store, num) + if !ok || err != nil { + return nil, err + } + + ret := fromV7SectorOnChainInfo(*info) + return &ret, nil +} + +func (s *state7) 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 *state7) 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 *miner7.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 *state7) 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 *miner7.Deadline) error { + partitions, err := dl.PartitionsArray(s.store) + if err != nil { + return err + } + quant := s.State.QuantSpecForDeadline(dlIdx) + var part miner7.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 := miner7.LoadExpirationQueue(s.store, part.ExpirationsEpochs, quant, miner7.PartitionExpirationAmtBitwidth) + if err != nil { + return err + } + var exp miner7.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 *state7) GetPrecommittedSector(num abi.SectorNumber) (*SectorPreCommitOnChainInfo, error) { + info, ok, err := s.State.GetPrecommittedSector(s.store, num) + if !ok || err != nil { + return nil, err + } + + ret := fromV7SectorPreCommitOnChainInfo(*info) + + return &ret, nil +} + +func (s *state7) ForEachPrecommittedSector(cb func(SectorPreCommitOnChainInfo) error) error { + precommitted, err := adt7.AsMap(s.store, s.State.PreCommittedSectors, builtin7.DefaultHamtBitwidth) + if err != nil { + return err + } + + var info miner7.SectorPreCommitOnChainInfo + if err := precommitted.ForEach(&info, func(_ string) error { + return cb(fromV7SectorPreCommitOnChainInfo(info)) + }); err != nil { + return err + } + + return nil +} + +func (s *state7) LoadSectors(snos *bitfield.BitField) ([]*SectorOnChainInfo, error) { + sectors, err := miner7.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 info7 miner7.SectorOnChainInfo + if err := sectors.ForEach(&info7, func(_ int64) error { + info := fromV7SectorOnChainInfo(info7) + infos = append(infos, &info) + return nil + }); err != nil { + return nil, err + } + return infos, nil + } + + // Otherwise, load selected. + infos7, err := sectors.Load(*snos) + if err != nil { + return nil, err + } + infos := make([]*SectorOnChainInfo, len(infos7)) + for i, info7 := range infos7 { + info := fromV7SectorOnChainInfo(*info7) + infos[i] = &info + } + return infos, nil +} + +func (s *state7) loadAllocatedSectorNumbers() (bitfield.BitField, error) { + var allocatedSectors bitfield.BitField + err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors) + return allocatedSectors, err +} + +func (s *state7) IsAllocated(num abi.SectorNumber) (bool, error) { + allocatedSectors, err := s.loadAllocatedSectorNumbers() + if err != nil { + return false, err + } + + return allocatedSectors.IsSet(uint64(num)) +} + +func (s *state7) GetProvingPeriodStart() (abi.ChainEpoch, error) { + return s.State.ProvingPeriodStart, nil +} + +func (s *state7) UnallocatedSectorNumbers(count int) ([]abi.SectorNumber, error) { + allocatedSectors, err := s.loadAllocatedSectorNumbers() + if err != nil { + return nil, err + } + + allocatedRuns, err := allocatedSectors.RunIterator() + if err != nil { + return nil, err + } + + unallocatedRuns, err := rle.Subtract( + &rle.RunSliceIterator{Runs: []rle.Run{{Val: true, Len: abi.MaxSectorNumber}}}, + allocatedRuns, + ) + if err != nil { + return nil, err + } + + iter, err := rle.BitsFromRuns(unallocatedRuns) + if err != nil { + return nil, err + } + + sectors := make([]abi.SectorNumber, 0, count) + for iter.HasNext() && len(sectors) < count { + nextNo, err := iter.Next() + if err != nil { + return nil, err + } + sectors = append(sectors, abi.SectorNumber(nextNo)) + } + + return sectors, nil +} + +func (s *state7) GetAllocatedSectors() (*bitfield.BitField, error) { + var allocatedSectors bitfield.BitField + if err := s.store.Get(s.store.Context(), s.State.AllocatedSectors, &allocatedSectors); err != nil { + return nil, err + } + + return &allocatedSectors, nil +} + +func (s *state7) 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 &deadline7{*dl, s.store}, nil +} + +func (s *state7) 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 *miner7.Deadline) error { + return cb(i, &deadline7{*dl, s.store}) + }) +} + +func (s *state7) NumDeadlines() (uint64, error) { + return miner7.WPoStPeriodDeadlines, nil +} + +func (s *state7) DeadlinesChanged(other State) (bool, error) { + other7, ok := other.(*state7) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + + return !s.State.Deadlines.Equals(other7.Deadlines), nil +} + +func (s *state7) MinerInfoChanged(other State) (bool, error) { + other0, ok := other.(*state7) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + return !s.State.Info.Equals(other0.State.Info), nil +} + +func (s *state7) 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 *state7) DeadlineInfo(epoch abi.ChainEpoch) (*dline.Info, error) { + return s.State.RecordedDeadlineInfo(epoch), nil +} + +func (s *state7) DeadlineCronActive() (bool, error) { + return s.State.DeadlineCronActive, nil +} + +func (s *state7) sectors() (adt.Array, error) { + return adt7.AsArray(s.store, s.Sectors, miner7.SectorsAmtBitwidth) +} + +func (s *state7) decodeSectorOnChainInfo(val *cbg.Deferred) (SectorOnChainInfo, error) { + var si miner7.SectorOnChainInfo + err := si.UnmarshalCBOR(bytes.NewReader(val.Raw)) + if err != nil { + return SectorOnChainInfo{}, err + } + + return fromV7SectorOnChainInfo(si), nil +} + +func (s *state7) precommits() (adt.Map, error) { + return adt7.AsMap(s.store, s.PreCommittedSectors, builtin7.DefaultHamtBitwidth) +} + +func (s *state7) decodeSectorPreCommitOnChainInfo(val *cbg.Deferred) (SectorPreCommitOnChainInfo, error) { + var sp miner7.SectorPreCommitOnChainInfo + err := sp.UnmarshalCBOR(bytes.NewReader(val.Raw)) + if err != nil { + return SectorPreCommitOnChainInfo{}, err + } + + return fromV7SectorPreCommitOnChainInfo(sp), nil +} + +func (s *state7) EraseAllUnproven() error { + + dls, err := s.State.LoadDeadlines(s.store) + if err != nil { + return err + } + + err = dls.ForEach(s.store, func(dindx uint64, dl *miner7.Deadline) error { + ps, err := dl.PartitionsArray(s.store) + if err != nil { + return err + } + + var part miner7.Partition + err = ps.ForEach(&part, func(pindx int64) error { + _ = part.ActivateUnproven() + err = ps.Set(uint64(pindx), &part) + return nil + }) + + if err != nil { + return err + } + + dl.Partitions, err = ps.Root() + if err != nil { + return err + } + + return dls.UpdateDeadline(s.store, dindx, dl) + }) + if err != nil { + return err + } + + return s.State.SaveDeadlines(s.store, dls) + +} + +func (d *deadline7) LoadPartition(idx uint64) (Partition, error) { + p, err := d.Deadline.LoadPartition(d.store, idx) + if err != nil { + return nil, err + } + return &partition7{*p, d.store}, nil +} + +func (d *deadline7) ForEachPartition(cb func(uint64, Partition) error) error { + ps, err := d.Deadline.PartitionsArray(d.store) + if err != nil { + return err + } + var part miner7.Partition + return ps.ForEach(&part, func(i int64) error { + return cb(uint64(i), &partition7{part, d.store}) + }) +} + +func (d *deadline7) PartitionsChanged(other Deadline) (bool, error) { + other7, ok := other.(*deadline7) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + + return !d.Deadline.Partitions.Equals(other7.Deadline.Partitions), nil +} + +func (d *deadline7) PartitionsPoSted() (bitfield.BitField, error) { + return d.Deadline.PartitionsPoSted, nil +} + +func (d *deadline7) DisputableProofCount() (uint64, error) { + + ops, err := d.OptimisticProofsSnapshotArray(d.store) + if err != nil { + return 0, err + } + + return ops.Length(), nil + +} + +func (p *partition7) AllSectors() (bitfield.BitField, error) { + return p.Partition.Sectors, nil +} + +func (p *partition7) FaultySectors() (bitfield.BitField, error) { + return p.Partition.Faults, nil +} + +func (p *partition7) RecoveringSectors() (bitfield.BitField, error) { + return p.Partition.Recoveries, nil +} + +func (p *partition7) UnprovenSectors() (bitfield.BitField, error) { + return p.Partition.Unproven, nil +} + +func fromV7SectorOnChainInfo(v7 miner7.SectorOnChainInfo) SectorOnChainInfo { + + return SectorOnChainInfo{ + SectorNumber: v7.SectorNumber, + SealProof: v7.SealProof, + SealedCID: v7.SealedCID, + DealIDs: v7.DealIDs, + Activation: v7.Activation, + Expiration: v7.Expiration, + DealWeight: v7.DealWeight, + VerifiedDealWeight: v7.VerifiedDealWeight, + InitialPledge: v7.InitialPledge, + ExpectedDayReward: v7.ExpectedDayReward, + ExpectedStoragePledge: v7.ExpectedStoragePledge, + } + +} + +func fromV7SectorPreCommitOnChainInfo(v7 miner7.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { + + return SectorPreCommitOnChainInfo{ + Info: (SectorPreCommitInfo)(v7.Info), + PreCommitDeposit: v7.PreCommitDeposit, + PreCommitEpoch: v7.PreCommitEpoch, + DealWeight: v7.DealWeight, + VerifiedDealWeight: v7.VerifiedDealWeight, + } + +} + +func (s *state7) GetState() interface{} { + return &s.State +} diff --git a/chain/actors/builtin/multisig/message7.go b/chain/actors/builtin/multisig/message7.go new file mode 100644 index 000000000..e7fb83e9b --- /dev/null +++ b/chain/actors/builtin/multisig/message7.go @@ -0,0 +1,71 @@ +package multisig + +import ( + "golang.org/x/xerrors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + init7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/init" + multisig7 "github.com/filecoin-project/specs-actors/v7/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 message7 struct{ message0 } + +func (m message7) 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 := &multisig7.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 := &init7.ExecParams{ + CodeCID: builtin7.MultisigActorCodeID, + ConstructorParams: enc, + } + + enc, actErr = actors.SerializeParams(execParams) + if actErr != nil { + return nil, actErr + } + + return &types.Message{ + To: init_.Address, + From: m.from, + Method: builtin7.MethodsInit.Exec, + Params: enc, + Value: initialAmount, + }, nil +} diff --git a/chain/actors/builtin/multisig/multisig.go b/chain/actors/builtin/multisig/multisig.go index ee725f7e5..f1b50475a 100644 --- a/chain/actors/builtin/multisig/multisig.go +++ b/chain/actors/builtin/multisig/multisig.go @@ -13,7 +13,7 @@ import ( "github.com/ipfs/go-cid" msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" - msig6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/multisig" + msig7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/multisig" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" @@ -27,6 +27,8 @@ import ( builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -58,6 +60,10 @@ func init() { builtin.RegisterActorState(builtin6.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load6(store, root) }) + + builtin.RegisterActorState(builtin7.MultisigActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load7(store, root) + }) } func Load(store adt.Store, act *types.Actor) (State, error) { @@ -81,6 +87,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin6.MultisigActorCodeID: return load6(store, act.Head) + case builtin7.MultisigActorCodeID: + return load7(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } @@ -106,6 +115,9 @@ func MakeState(store adt.Store, av actors.Version, signers []address.Address, th case actors.Version6: return make6(store, signers, threshold, startEpoch, unlockDuration, initialBalance) + case actors.Version7: + return make7(store, signers, threshold, startEpoch, unlockDuration, initialBalance) + } return nil, xerrors.Errorf("unknown actor version %d", av) } @@ -131,6 +143,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { case actors.Version6: return builtin6.MultisigActorCodeID, nil + case actors.Version7: + return builtin7.MultisigActorCodeID, nil + } return cid.Undef, xerrors.Errorf("unknown actor version %d", av) @@ -156,7 +171,7 @@ type State interface { type Transaction = msig0.Transaction -var Methods = builtin6.MethodsMultisig +var Methods = builtin7.MethodsMultisig func Message(version actors.Version, from address.Address) MessageBuilder { switch version { @@ -178,6 +193,9 @@ func Message(version actors.Version, from address.Address) MessageBuilder { case actors.Version6: return message6{message0{from}} + + case actors.Version7: + return message7{message0{from}} default: panic(fmt.Sprintf("unsupported actors version: %d", version)) } @@ -201,13 +219,13 @@ type MessageBuilder interface { } // this type is the same between v0 and v2 -type ProposalHashData = msig6.ProposalHashData -type ProposeReturn = msig6.ProposeReturn -type ProposeParams = msig6.ProposeParams -type ApproveReturn = msig6.ApproveReturn +type ProposalHashData = msig7.ProposalHashData +type ProposeReturn = msig7.ProposeReturn +type ProposeParams = msig7.ProposeParams +type ApproveReturn = msig7.ApproveReturn func txnParams(id uint64, data *ProposalHashData) ([]byte, error) { - params := msig6.TxnIDParams{ID: msig6.TxnID(id)} + params := msig7.TxnIDParams{ID: msig7.TxnID(id)} if data != nil { if data.Requester.Protocol() != address.ID { return nil, xerrors.Errorf("proposer address must be an ID address, was %s", data.Requester) diff --git a/chain/actors/builtin/multisig/v7.go b/chain/actors/builtin/multisig/v7.go new file mode 100644 index 000000000..bbe41f3db --- /dev/null +++ b/chain/actors/builtin/multisig/v7.go @@ -0,0 +1,119 @@ +package multisig + +import ( + "bytes" + "encoding/binary" + + adt7 "github.com/filecoin-project/specs-actors/v7/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" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + + msig7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/multisig" +) + +var _ State = (*state7)(nil) + +func load7(store adt.Store, root cid.Cid) (State, error) { + out := state7{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +func make7(store adt.Store, signers []address.Address, threshold uint64, startEpoch abi.ChainEpoch, unlockDuration abi.ChainEpoch, initialBalance abi.TokenAmount) (State, error) { + out := state7{store: store} + out.State = msig7.State{} + out.State.Signers = signers + out.State.NumApprovalsThreshold = threshold + out.State.StartEpoch = startEpoch + out.State.UnlockDuration = unlockDuration + out.State.InitialBalance = initialBalance + + em, err := adt7.StoreEmptyMap(store, builtin7.DefaultHamtBitwidth) + if err != nil { + return nil, err + } + + out.State.PendingTxns = em + + return &out, nil +} + +type state7 struct { + msig7.State + store adt.Store +} + +func (s *state7) LockedBalance(currEpoch abi.ChainEpoch) (abi.TokenAmount, error) { + return s.State.AmountLocked(currEpoch - s.State.StartEpoch), nil +} + +func (s *state7) StartEpoch() (abi.ChainEpoch, error) { + return s.State.StartEpoch, nil +} + +func (s *state7) UnlockDuration() (abi.ChainEpoch, error) { + return s.State.UnlockDuration, nil +} + +func (s *state7) InitialBalance() (abi.TokenAmount, error) { + return s.State.InitialBalance, nil +} + +func (s *state7) Threshold() (uint64, error) { + return s.State.NumApprovalsThreshold, nil +} + +func (s *state7) Signers() ([]address.Address, error) { + return s.State.Signers, nil +} + +func (s *state7) ForEachPendingTxn(cb func(id int64, txn Transaction) error) error { + arr, err := adt7.AsMap(s.store, s.State.PendingTxns, builtin7.DefaultHamtBitwidth) + if err != nil { + return err + } + var out msig7.Transaction + return arr.ForEach(&out, func(key string) error { + txid, n := binary.Varint([]byte(key)) + if n <= 0 { + return xerrors.Errorf("invalid pending transaction key: %v", key) + } + return cb(txid, (Transaction)(out)) //nolint:unconvert + }) +} + +func (s *state7) PendingTxnChanged(other State) (bool, error) { + other7, ok := other.(*state7) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + return !s.State.PendingTxns.Equals(other7.PendingTxns), nil +} + +func (s *state7) transactions() (adt.Map, error) { + return adt7.AsMap(s.store, s.PendingTxns, builtin7.DefaultHamtBitwidth) +} + +func (s *state7) decodeTransaction(val *cbg.Deferred) (Transaction, error) { + var tx msig7.Transaction + if err := tx.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return Transaction{}, err + } + return tx, nil +} + +func (s *state7) GetState() interface{} { + return &s.State +} diff --git a/chain/actors/builtin/paych/message7.go b/chain/actors/builtin/paych/message7.go new file mode 100644 index 000000000..41dfa1bdd --- /dev/null +++ b/chain/actors/builtin/paych/message7.go @@ -0,0 +1,74 @@ +package paych + +import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + init7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/init" + paych7 "github.com/filecoin-project/specs-actors/v7/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 message7 struct{ from address.Address } + +func (m message7) Create(to address.Address, initialAmount abi.TokenAmount) (*types.Message, error) { + params, aerr := actors.SerializeParams(&paych7.ConstructorParams{From: m.from, To: to}) + if aerr != nil { + return nil, aerr + } + enc, aerr := actors.SerializeParams(&init7.ExecParams{ + CodeCID: builtin7.PaymentChannelActorCodeID, + ConstructorParams: params, + }) + if aerr != nil { + return nil, aerr + } + + return &types.Message{ + To: init_.Address, + From: m.from, + Value: initialAmount, + Method: builtin7.MethodsInit.Exec, + Params: enc, + }, nil +} + +func (m message7) Update(paych address.Address, sv *SignedVoucher, secret []byte) (*types.Message, error) { + params, aerr := actors.SerializeParams(&paych7.UpdateChannelStateParams{ + Sv: *sv, + Secret: secret, + }) + if aerr != nil { + return nil, aerr + } + + return &types.Message{ + To: paych, + From: m.from, + Value: abi.NewTokenAmount(0), + Method: builtin7.MethodsPaych.UpdateChannelState, + Params: params, + }, nil +} + +func (m message7) Settle(paych address.Address) (*types.Message, error) { + return &types.Message{ + To: paych, + From: m.from, + Value: abi.NewTokenAmount(0), + Method: builtin7.MethodsPaych.Settle, + }, nil +} + +func (m message7) Collect(paych address.Address) (*types.Message, error) { + return &types.Message{ + To: paych, + From: m.from, + Value: abi.NewTokenAmount(0), + Method: builtin7.MethodsPaych.Collect, + }, nil +} diff --git a/chain/actors/builtin/paych/paych.go b/chain/actors/builtin/paych/paych.go index eea3659f8..f807b33ed 100644 --- a/chain/actors/builtin/paych/paych.go +++ b/chain/actors/builtin/paych/paych.go @@ -27,6 +27,8 @@ import ( builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -58,6 +60,10 @@ func init() { builtin.RegisterActorState(builtin6.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load6(store, root) }) + + builtin.RegisterActorState(builtin7.PaymentChannelActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load7(store, root) + }) } // Load returns an abstract copy of payment channel state, irregardless of actor version @@ -82,6 +88,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin6.PaymentChannelActorCodeID: return load6(store, act.Head) + case builtin7.PaymentChannelActorCodeID: + return load7(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } @@ -107,6 +116,9 @@ func MakeState(store adt.Store, av actors.Version) (State, error) { case actors.Version6: return make6(store) + case actors.Version7: + return make7(store) + } return nil, xerrors.Errorf("unknown actor version %d", av) } @@ -132,6 +144,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { case actors.Version6: return builtin6.PaymentChannelActorCodeID, nil + case actors.Version7: + return builtin7.PaymentChannelActorCodeID, nil + } return cid.Undef, xerrors.Errorf("unknown actor version %d", av) @@ -185,7 +200,7 @@ func DecodeSignedVoucher(s string) (*SignedVoucher, error) { return &sv, nil } -var Methods = builtin6.MethodsPaych +var Methods = builtin7.MethodsPaych func Message(version actors.Version, from address.Address) MessageBuilder { switch version { @@ -208,6 +223,9 @@ func Message(version actors.Version, from address.Address) MessageBuilder { case actors.Version6: return message6{from} + case actors.Version7: + return message7{from} + default: panic(fmt.Sprintf("unsupported actors version: %d", version)) } diff --git a/chain/actors/builtin/paych/v7.go b/chain/actors/builtin/paych/v7.go new file mode 100644 index 000000000..ce09ea2e4 --- /dev/null +++ b/chain/actors/builtin/paych/v7.go @@ -0,0 +1,114 @@ +package paych + +import ( + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" + + "github.com/filecoin-project/lotus/chain/actors/adt" + + paych7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/paych" + adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" +) + +var _ State = (*state7)(nil) + +func load7(store adt.Store, root cid.Cid) (State, error) { + out := state7{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +func make7(store adt.Store) (State, error) { + out := state7{store: store} + out.State = paych7.State{} + return &out, nil +} + +type state7 struct { + paych7.State + store adt.Store + lsAmt *adt7.Array +} + +// Channel owner, who has funded the actor +func (s *state7) From() (address.Address, error) { + return s.State.From, nil +} + +// Recipient of payouts from channel +func (s *state7) To() (address.Address, error) { + return s.State.To, nil +} + +// Height at which the channel can be `Collected` +func (s *state7) SettlingAt() (abi.ChainEpoch, error) { + return s.State.SettlingAt, nil +} + +// Amount successfully redeemed through the payment channel, paid out on `Collect()` +func (s *state7) ToSend() (abi.TokenAmount, error) { + return s.State.ToSend, nil +} + +func (s *state7) getOrLoadLsAmt() (*adt7.Array, error) { + if s.lsAmt != nil { + return s.lsAmt, nil + } + + // Get the lane state from the chain + lsamt, err := adt7.AsArray(s.store, s.State.LaneStates, paych7.LaneStatesAmtBitwidth) + if err != nil { + return nil, err + } + + s.lsAmt = lsamt + return lsamt, nil +} + +// Get total number of lanes +func (s *state7) LaneCount() (uint64, error) { + lsamt, err := s.getOrLoadLsAmt() + if err != nil { + return 0, err + } + return lsamt.Length(), nil +} + +func (s *state7) GetState() interface{} { + return &s.State +} + +// Iterate lane states +func (s *state7) 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 paych7.LaneState + return lsamt.ForEach(&ls, func(i int64) error { + return cb(uint64(i), &laneState7{ls}) + }) +} + +type laneState7 struct { + paych7.LaneState +} + +func (ls *laneState7) Redeemed() (big.Int, error) { + return ls.LaneState.Redeemed, nil +} + +func (ls *laneState7) Nonce() (uint64, error) { + return ls.LaneState.Nonce, nil +} diff --git a/chain/actors/builtin/power/power.go b/chain/actors/builtin/power/power.go index 84bd6948a..9b73cdd60 100644 --- a/chain/actors/builtin/power/power.go +++ b/chain/actors/builtin/power/power.go @@ -26,6 +26,8 @@ import ( builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" ) func init() { @@ -53,11 +55,15 @@ func init() { builtin.RegisterActorState(builtin6.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load6(store, root) }) + + builtin.RegisterActorState(builtin7.StoragePowerActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load7(store, root) + }) } var ( - Address = builtin6.StoragePowerActorAddr - Methods = builtin6.MethodsPower + Address = builtin7.StoragePowerActorAddr + Methods = builtin7.MethodsPower ) func Load(store adt.Store, act *types.Actor) (State, error) { @@ -81,6 +87,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin6.StoragePowerActorCodeID: return load6(store, act.Head) + case builtin7.StoragePowerActorCodeID: + return load7(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } @@ -106,6 +115,9 @@ func MakeState(store adt.Store, av actors.Version) (State, error) { case actors.Version6: return make6(store) + case actors.Version7: + return make7(store) + } return nil, xerrors.Errorf("unknown actor version %d", av) } @@ -131,6 +143,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { case actors.Version6: return builtin6.StoragePowerActorCodeID, nil + case actors.Version7: + return builtin7.StoragePowerActorCodeID, nil + } return cid.Undef, xerrors.Errorf("unknown actor version %d", av) diff --git a/chain/actors/builtin/power/v7.go b/chain/actors/builtin/power/v7.go new file mode 100644 index 000000000..af1761cb2 --- /dev/null +++ b/chain/actors/builtin/power/v7.go @@ -0,0 +1,187 @@ +package power + +import ( + "bytes" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + + power7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/power" + adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" +) + +var _ State = (*state7)(nil) + +func load7(store adt.Store, root cid.Cid) (State, error) { + out := state7{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +func make7(store adt.Store) (State, error) { + out := state7{store: store} + + s, err := power7.ConstructState(store) + if err != nil { + return nil, err + } + + out.State = *s + + return &out, nil +} + +type state7 struct { + power7.State + store adt.Store +} + +func (s *state7) TotalLocked() (abi.TokenAmount, error) { + return s.TotalPledgeCollateral, nil +} + +func (s *state7) 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 *state7) TotalCommitted() (Claim, error) { + return Claim{ + RawBytePower: s.TotalBytesCommitted, + QualityAdjPower: s.TotalQABytesCommitted, + }, nil +} + +func (s *state7) MinerPower(addr address.Address) (Claim, bool, error) { + claims, err := s.claims() + if err != nil { + return Claim{}, false, err + } + var claim power7.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 *state7) MinerNominalPowerMeetsConsensusMinimum(a address.Address) (bool, error) { + return s.State.MinerNominalPowerMeetsConsensusMinimum(s.store, a) +} + +func (s *state7) TotalPowerSmoothed() (builtin.FilterEstimate, error) { + return builtin.FromV7FilterEstimate(s.State.ThisEpochQAPowerSmoothed), nil +} + +func (s *state7) MinerCounts() (uint64, uint64, error) { + return uint64(s.State.MinerAboveMinPowerCount), uint64(s.State.MinerCount), nil +} + +func (s *state7) 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 *state7) ForEachClaim(cb func(miner address.Address, claim Claim) error) error { + claims, err := s.claims() + if err != nil { + return err + } + + var claim power7.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 *state7) ClaimsChanged(other State) (bool, error) { + other7, ok := other.(*state7) + if !ok { + // treat an upgrade as a change, always + return true, nil + } + return !s.State.Claims.Equals(other7.State.Claims), nil +} + +func (s *state7) SetTotalQualityAdjPower(p abi.StoragePower) error { + s.State.TotalQualityAdjPower = p + return nil +} + +func (s *state7) SetTotalRawBytePower(p abi.StoragePower) error { + s.State.TotalRawBytePower = p + return nil +} + +func (s *state7) SetThisEpochQualityAdjPower(p abi.StoragePower) error { + s.State.ThisEpochQualityAdjPower = p + return nil +} + +func (s *state7) SetThisEpochRawBytePower(p abi.StoragePower) error { + s.State.ThisEpochRawBytePower = p + return nil +} + +func (s *state7) GetState() interface{} { + return &s.State +} + +func (s *state7) claims() (adt.Map, error) { + return adt7.AsMap(s.store, s.Claims, builtin7.DefaultHamtBitwidth) +} + +func (s *state7) decodeClaim(val *cbg.Deferred) (Claim, error) { + var ci power7.Claim + if err := ci.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return Claim{}, err + } + return fromV7Claim(ci), nil +} + +func fromV7Claim(v7 power7.Claim) Claim { + return Claim{ + RawBytePower: v7.RawBytePower, + QualityAdjPower: v7.QualityAdjPower, + } +} diff --git a/chain/actors/builtin/reward/reward.go b/chain/actors/builtin/reward/reward.go index 38d5b5b87..b6ee2f146 100644 --- a/chain/actors/builtin/reward/reward.go +++ b/chain/actors/builtin/reward/reward.go @@ -21,6 +21,8 @@ import ( builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/types" @@ -51,11 +53,15 @@ func init() { builtin.RegisterActorState(builtin6.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { return load6(store, root) }) + + builtin.RegisterActorState(builtin7.RewardActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load7(store, root) + }) } var ( - Address = builtin6.RewardActorAddr - Methods = builtin6.MethodsReward + Address = builtin7.RewardActorAddr + Methods = builtin7.MethodsReward ) func Load(store adt.Store, act *types.Actor) (State, error) { @@ -79,6 +85,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin6.RewardActorCodeID: return load6(store, act.Head) + case builtin7.RewardActorCodeID: + return load7(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } @@ -104,6 +113,9 @@ func MakeState(store adt.Store, av actors.Version, currRealizedPower abi.Storage case actors.Version6: return make6(store, currRealizedPower) + case actors.Version7: + return make7(store, currRealizedPower) + } return nil, xerrors.Errorf("unknown actor version %d", av) } @@ -129,6 +141,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { case actors.Version6: return builtin6.RewardActorCodeID, nil + case actors.Version7: + return builtin7.RewardActorCodeID, nil + } return cid.Undef, xerrors.Errorf("unknown actor version %d", av) diff --git a/chain/actors/builtin/reward/v7.go b/chain/actors/builtin/reward/v7.go new file mode 100644 index 000000000..368bb3abd --- /dev/null +++ b/chain/actors/builtin/reward/v7.go @@ -0,0 +1,98 @@ +package reward + +import ( + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + + miner7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/miner" + reward7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/reward" + smoothing7 "github.com/filecoin-project/specs-actors/v7/actors/util/smoothing" +) + +var _ State = (*state7)(nil) + +func load7(store adt.Store, root cid.Cid) (State, error) { + out := state7{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +func make7(store adt.Store, currRealizedPower abi.StoragePower) (State, error) { + out := state7{store: store} + out.State = *reward7.ConstructState(currRealizedPower) + return &out, nil +} + +type state7 struct { + reward7.State + store adt.Store +} + +func (s *state7) ThisEpochReward() (abi.TokenAmount, error) { + return s.State.ThisEpochReward, nil +} + +func (s *state7) ThisEpochRewardSmoothed() (builtin.FilterEstimate, error) { + + return builtin.FilterEstimate{ + PositionEstimate: s.State.ThisEpochRewardSmoothed.PositionEstimate, + VelocityEstimate: s.State.ThisEpochRewardSmoothed.VelocityEstimate, + }, nil + +} + +func (s *state7) ThisEpochBaselinePower() (abi.StoragePower, error) { + return s.State.ThisEpochBaselinePower, nil +} + +func (s *state7) TotalStoragePowerReward() (abi.TokenAmount, error) { + return s.State.TotalStoragePowerReward, nil +} + +func (s *state7) EffectiveBaselinePower() (abi.StoragePower, error) { + return s.State.EffectiveBaselinePower, nil +} + +func (s *state7) EffectiveNetworkTime() (abi.ChainEpoch, error) { + return s.State.EffectiveNetworkTime, nil +} + +func (s *state7) CumsumBaseline() (reward7.Spacetime, error) { + return s.State.CumsumBaseline, nil +} + +func (s *state7) CumsumRealized() (reward7.Spacetime, error) { + return s.State.CumsumRealized, nil +} + +func (s *state7) InitialPledgeForPower(qaPower abi.StoragePower, networkTotalPledge abi.TokenAmount, networkQAPower *builtin.FilterEstimate, circSupply abi.TokenAmount) (abi.TokenAmount, error) { + return miner7.InitialPledgeForPower( + qaPower, + s.State.ThisEpochBaselinePower, + s.State.ThisEpochRewardSmoothed, + smoothing7.FilterEstimate{ + PositionEstimate: networkQAPower.PositionEstimate, + VelocityEstimate: networkQAPower.VelocityEstimate, + }, + circSupply, + ), nil +} + +func (s *state7) PreCommitDepositForPower(networkQAPower builtin.FilterEstimate, sectorWeight abi.StoragePower) (abi.TokenAmount, error) { + return miner7.PreCommitDepositForPower(s.State.ThisEpochRewardSmoothed, + smoothing7.FilterEstimate{ + PositionEstimate: networkQAPower.PositionEstimate, + VelocityEstimate: networkQAPower.VelocityEstimate, + }, + sectorWeight), nil +} + +func (s *state7) GetState() interface{} { + return &s.State +} diff --git a/chain/actors/builtin/system/system.go b/chain/actors/builtin/system/system.go index 3d6105c38..fb7515f35 100644 --- a/chain/actors/builtin/system/system.go +++ b/chain/actors/builtin/system/system.go @@ -17,10 +17,12 @@ import ( builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" ) var ( - Address = builtin6.SystemActorAddr + Address = builtin7.SystemActorAddr ) func MakeState(store adt.Store, av actors.Version) (State, error) { @@ -44,6 +46,9 @@ func MakeState(store adt.Store, av actors.Version) (State, error) { case actors.Version6: return make6(store) + case actors.Version7: + return make7(store) + } return nil, xerrors.Errorf("unknown actor version %d", av) } @@ -69,6 +74,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { case actors.Version6: return builtin6.SystemActorCodeID, nil + case actors.Version7: + return builtin7.SystemActorCodeID, nil + } return cid.Undef, xerrors.Errorf("unknown actor version %d", av) diff --git a/chain/actors/builtin/system/v7.go b/chain/actors/builtin/system/v7.go new file mode 100644 index 000000000..813add5fb --- /dev/null +++ b/chain/actors/builtin/system/v7.go @@ -0,0 +1,35 @@ +package system + +import ( + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/lotus/chain/actors/adt" + + system7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/system" +) + +var _ State = (*state7)(nil) + +func load7(store adt.Store, root cid.Cid) (State, error) { + out := state7{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +func make7(store adt.Store) (State, error) { + out := state7{store: store} + out.State = system7.State{} + return &out, nil +} + +type state7 struct { + system7.State + store adt.Store +} + +func (s *state7) GetState() interface{} { + return &s.State +} diff --git a/chain/actors/builtin/verifreg/v7.go b/chain/actors/builtin/verifreg/v7.go new file mode 100644 index 000000000..9b2ca928a --- /dev/null +++ b/chain/actors/builtin/verifreg/v7.go @@ -0,0 +1,75 @@ +package verifreg + +import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/actors/adt" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + verifreg7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/verifreg" + adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" +) + +var _ State = (*state7)(nil) + +func load7(store adt.Store, root cid.Cid) (State, error) { + out := state7{store: store} + err := store.Get(store.Context(), root, &out) + if err != nil { + return nil, err + } + return &out, nil +} + +func make7(store adt.Store, rootKeyAddress address.Address) (State, error) { + out := state7{store: store} + + s, err := verifreg7.ConstructState(store, rootKeyAddress) + if err != nil { + return nil, err + } + + out.State = *s + + return &out, nil +} + +type state7 struct { + verifreg7.State + store adt.Store +} + +func (s *state7) RootKey() (address.Address, error) { + return s.State.RootKey, nil +} + +func (s *state7) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) { + return getDataCap(s.store, actors.Version7, s.verifiedClients, addr) +} + +func (s *state7) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) { + return getDataCap(s.store, actors.Version7, s.verifiers, addr) +} + +func (s *state7) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { + return forEachCap(s.store, actors.Version7, s.verifiers, cb) +} + +func (s *state7) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error { + return forEachCap(s.store, actors.Version7, s.verifiedClients, cb) +} + +func (s *state7) verifiedClients() (adt.Map, error) { + return adt7.AsMap(s.store, s.VerifiedClients, builtin7.DefaultHamtBitwidth) +} + +func (s *state7) verifiers() (adt.Map, error) { + return adt7.AsMap(s.store, s.Verifiers, builtin7.DefaultHamtBitwidth) +} + +func (s *state7) GetState() interface{} { + return &s.State +} diff --git a/chain/actors/builtin/verifreg/verifreg.go b/chain/actors/builtin/verifreg/verifreg.go index 31e8e5a08..f6281334d 100644 --- a/chain/actors/builtin/verifreg/verifreg.go +++ b/chain/actors/builtin/verifreg/verifreg.go @@ -21,6 +21,8 @@ import ( builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" @@ -53,11 +55,15 @@ func init() { return load6(store, root) }) + builtin.RegisterActorState(builtin7.VerifiedRegistryActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) { + return load7(store, root) + }) + } var ( - Address = builtin6.VerifiedRegistryActorAddr - Methods = builtin6.MethodsVerifiedRegistry + Address = builtin7.VerifiedRegistryActorAddr + Methods = builtin7.MethodsVerifiedRegistry ) func Load(store adt.Store, act *types.Actor) (State, error) { @@ -81,6 +87,9 @@ func Load(store adt.Store, act *types.Actor) (State, error) { case builtin6.VerifiedRegistryActorCodeID: return load6(store, act.Head) + case builtin7.VerifiedRegistryActorCodeID: + return load7(store, act.Head) + } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } @@ -106,6 +115,9 @@ func MakeState(store adt.Store, av actors.Version, rootKeyAddress address.Addres case actors.Version6: return make6(store, rootKeyAddress) + case actors.Version7: + return make7(store, rootKeyAddress) + } return nil, xerrors.Errorf("unknown actor version %d", av) } @@ -131,6 +143,9 @@ func GetActorCodeID(av actors.Version) (cid.Cid, error) { case actors.Version6: return builtin6.VerifiedRegistryActorCodeID, nil + case actors.Version7: + return builtin7.VerifiedRegistryActorCodeID, nil + } return cid.Undef, xerrors.Errorf("unknown actor version %d", av) diff --git a/chain/actors/policy/policy.go b/chain/actors/policy/policy.go index e00a6ae10..f51da7aa7 100644 --- a/chain/actors/policy/policy.go +++ b/chain/actors/policy/policy.go @@ -40,14 +40,19 @@ import ( miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner" verifreg6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/verifreg" - paych6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/paych" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + market7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/market" + miner7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/miner" + verifreg7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/verifreg" + + paych7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/paych" ) const ( - ChainFinality = miner6.ChainFinality + ChainFinality = miner7.ChainFinality SealRandomnessLookback = ChainFinality - PaychSettleDelay = paych6.SettleDelay - MaxPreCommitRandomnessLookback = builtin6.EpochsInDay + SealRandomnessLookback + PaychSettleDelay = paych7.SettleDelay + MaxPreCommitRandomnessLookback = builtin7.EpochsInDay + SealRandomnessLookback ) // SetSupportedProofTypes sets supported proof types, across all actor versions. @@ -72,6 +77,8 @@ func SetSupportedProofTypes(types ...abi.RegisteredSealProof) { miner6.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types)) + miner7.PreCommitSealProofTypesV8 = make(map[abi.RegisteredSealProof]struct{}, len(types)) + AddSupportedProofTypes(types...) } @@ -119,6 +126,15 @@ func AddSupportedProofTypes(types ...abi.RegisteredSealProof) { miner6.WindowPoStProofTypes[wpp] = struct{}{} + miner7.PreCommitSealProofTypesV8[t+abi.RegisteredSealProof_StackedDrg2KiBV1_1] = struct{}{} + wpp, err = t.RegisteredWindowPoStProof() + if err != nil { + // Fine to panic, this is a test-only method + panic(err) + } + + miner7.WindowPoStProofTypes[wpp] = struct{}{} + } } @@ -139,11 +155,13 @@ func SetPreCommitChallengeDelay(delay abi.ChainEpoch) { miner6.PreCommitChallengeDelay = delay + miner7.PreCommitChallengeDelay = delay + } // TODO: this function shouldn't really exist. Instead, the API should expose the precommit delay. func GetPreCommitChallengeDelay() abi.ChainEpoch { - return miner6.PreCommitChallengeDelay + return miner7.PreCommitChallengeDelay } // SetConsensusMinerMinPower sets the minimum power of an individual miner must @@ -173,6 +191,10 @@ func SetConsensusMinerMinPower(p abi.StoragePower) { policy.ConsensusMinerMinPower = p } + for _, policy := range builtin7.PoStProofPolicies { + policy.ConsensusMinerMinPower = p + } + } // SetMinVerifiedDealSize sets the minimum size of a verified deal. This should @@ -191,6 +213,8 @@ func SetMinVerifiedDealSize(size abi.StoragePower) { verifreg6.MinVerifiedDealSize = size + verifreg7.MinVerifiedDealSize = size + } func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) (abi.ChainEpoch, error) { @@ -220,6 +244,10 @@ func GetMaxProveCommitDuration(ver actors.Version, t abi.RegisteredSealProof) (a return miner6.MaxProveCommitDuration[t], nil + case actors.Version7: + + return miner7.MaxProveCommitDuration[t], nil + default: return 0, xerrors.Errorf("unsupported actors version") } @@ -255,6 +283,11 @@ func SetProviderCollateralSupplyTarget(num, denom big.Int) { Denominator: denom, } + market7.ProviderCollateralSupplyTarget = builtin7.BigFrac{ + Numerator: num, + Denominator: denom, + } + } func DealProviderCollateralBounds( @@ -298,13 +331,18 @@ func DealProviderCollateralBounds( min, max := market6.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil) return min, max, nil + case actors.Version7: + + min, max := market7.DealProviderCollateralBounds(size, verified, rawBytePower, qaPower, baselinePower, circulatingFil) + return min, max, nil + default: return big.Zero(), big.Zero(), xerrors.Errorf("unsupported actors version") } } func DealDurationBounds(pieceSize abi.PaddedPieceSize) (min, max abi.ChainEpoch) { - return market6.DealDurationBounds(pieceSize) + return market7.DealDurationBounds(pieceSize) } // Sets the challenge window and scales the proving period to match (such that @@ -345,6 +383,13 @@ func SetWPoStChallengeWindow(period abi.ChainEpoch) { // scale it if we're scaling the challenge period. miner6.WPoStDisputeWindow = period * 30 + miner7.WPoStChallengeWindow = period + miner7.WPoStProvingPeriod = period * abi.ChainEpoch(miner7.WPoStPeriodDeadlines) + + // by default, this is 2x finality which is 30 periods. + // scale it if we're scaling the challenge period. + miner7.WPoStDisputeWindow = period * 30 + } func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch { @@ -357,15 +402,15 @@ func GetWinningPoStSectorSetLookback(nwVer network.Version) abi.ChainEpoch { } func GetMaxSectorExpirationExtension() abi.ChainEpoch { - return miner6.MaxSectorExpirationExtension + return miner7.MaxSectorExpirationExtension } func GetMinSectorExpiration() abi.ChainEpoch { - return miner6.MinSectorExpiration + return miner7.MinSectorExpiration } func GetMaxPoStPartitions(nv network.Version, p abi.RegisteredPoStProof) (int, error) { - sectorsPerPart, err := builtin6.PoStProofWindowPoStPartitionSectors(p) + sectorsPerPart, err := builtin7.PoStProofWindowPoStPartitionSectors(p) if err != nil { return 0, err } @@ -378,8 +423,8 @@ func GetMaxPoStPartitions(nv network.Version, p abi.RegisteredPoStProof) (int, e func GetDefaultSectorSize() abi.SectorSize { // supported sector sizes are the same across versions. - szs := make([]abi.SectorSize, 0, len(miner6.PreCommitSealProofTypesV8)) - for spt := range miner6.PreCommitSealProofTypesV8 { + szs := make([]abi.SectorSize, 0, len(miner7.PreCommitSealProofTypesV8)) + for spt := range miner7.PreCommitSealProofTypesV8 { ss, err := spt.SectorSize() if err != nil { panic(err) @@ -404,7 +449,7 @@ func GetSectorMaxLifetime(proof abi.RegisteredSealProof, nwVer network.Version) return builtin4.SealProofPoliciesV0[proof].SectorMaxLifetime } - return builtin6.SealProofPoliciesV11[proof].SectorMaxLifetime + return builtin7.SealProofPoliciesV11[proof].SectorMaxLifetime } func GetAddressedSectorsMax(nwVer network.Version) (int, error) { @@ -432,6 +477,9 @@ func GetAddressedSectorsMax(nwVer network.Version) (int, error) { case actors.Version6: return miner6.AddressedSectorsMax, nil + case actors.Version7: + return miner7.AddressedSectorsMax, nil + default: return 0, xerrors.Errorf("unsupported network version") } @@ -469,6 +517,10 @@ func GetDeclarationsMax(nwVer network.Version) (int, error) { return miner6.DeclarationsMax, nil + case actors.Version7: + + return miner7.DeclarationsMax, nil + default: return 0, xerrors.Errorf("unsupported network version") } @@ -505,6 +557,10 @@ func AggregateProveCommitNetworkFee(nwVer network.Version, aggregateSize int, ba return miner6.AggregateProveCommitNetworkFee(aggregateSize, baseFee), nil + case actors.Version7: + + return miner7.AggregateProveCommitNetworkFee(aggregateSize, baseFee), nil + default: return big.Zero(), xerrors.Errorf("unsupported network version") } @@ -541,6 +597,10 @@ func AggregatePreCommitNetworkFee(nwVer network.Version, aggregateSize int, base return miner6.AggregatePreCommitNetworkFee(aggregateSize, baseFee), nil + case actors.Version7: + + return miner7.AggregatePreCommitNetworkFee(aggregateSize, baseFee), nil + default: return big.Zero(), xerrors.Errorf("unsupported network version") } diff --git a/chain/actors/version.go b/chain/actors/version.go index 7b7a6393a..af51161c9 100644 --- a/chain/actors/version.go +++ b/chain/actors/version.go @@ -20,9 +20,9 @@ const ({{range .actorVersions}} /* inline-gen start */ -var LatestVersion = 6 +var LatestVersion = 7 -var Versions = []int{0, 2, 3, 4, 5, 6} +var Versions = []int{0, 2, 3, 4, 5, 6, 7} const ( Version0 Version = 0 @@ -31,6 +31,7 @@ const ( Version4 Version = 4 Version5 Version = 5 Version6 Version = 6 + Version7 Version = 7 ) /* inline-gen end */ @@ -50,6 +51,8 @@ func VersionForNetwork(version network.Version) (Version, error) { return Version5, nil case network.Version14: return Version6, nil + case network.Version15: + return Version7, nil default: return -1, fmt.Errorf("unsupported network version %d", version) } diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index 3c333298e..847d41d47 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -28,6 +28,7 @@ import ( exported4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/exported" exported5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/exported" exported6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/exported" + exported7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/exported" /* inline-gen end */ @@ -59,6 +60,7 @@ func NewActorRegistry() *vm.ActorRegistry { inv.Register(vm.ActorsVersionPredicate(actors.Version4), exported4.BuiltinActors()...) inv.Register(vm.ActorsVersionPredicate(actors.Version5), exported5.BuiltinActors()...) inv.Register(vm.ActorsVersionPredicate(actors.Version6), exported6.BuiltinActors()...) + inv.Register(vm.ActorsVersionPredicate(actors.Version7), exported7.BuiltinActors()...) /* inline-gen end */ diff --git a/chain/consensus/filcns/upgrades.go b/chain/consensus/filcns/upgrades.go index cf4c62bf3..43f50311f 100644 --- a/chain/consensus/filcns/upgrades.go +++ b/chain/consensus/filcns/upgrades.go @@ -156,6 +156,22 @@ func DefaultUpgradeSchedule() stmgr.UpgradeSchedule { StopWithin: 5, }}, Expensive: true, + }, { + Height: build.UpgradeSnapDealsHeight, + Network: network.Version15, + Migration: UpgradeActorsV7, + PreMigrations: []stmgr.PreMigration{{ + PreMigration: PreUpgradeActorsV7, + StartWithin: 120, + DontStartWithin: 60, + StopWithin: 35, + }, { + PreMigration: PreUpgradeActorsV7, + StartWithin: 30, + DontStartWithin: 15, + StopWithin: 5, + }}, + Expensive: true, }, } @@ -1170,7 +1186,97 @@ func upgradeActorsV6Common( // Perform the migration newHamtRoot, err := nv14.MigrateStateTree(ctx, store, stateRoot.Actors, epoch, config, migrationLogger{}, cache) if err != nil { - return cid.Undef, xerrors.Errorf("upgrading to actors v5: %w", err) + return cid.Undef, xerrors.Errorf("upgrading to actors v6: %w", err) + } + + // Persist the result. + newRoot, err := store.Put(ctx, &types.StateRoot{ + Version: types.StateTreeVersion4, + Actors: newHamtRoot, + Info: stateRoot.Info, + }) + if err != nil { + return cid.Undef, xerrors.Errorf("failed to persist new state root: %w", err) + } + + // Persist the new tree. + + { + from := buf + to := buf.Read() + + if err := vm.Copy(ctx, from, to, newRoot); err != nil { + return cid.Undef, xerrors.Errorf("copying migrated tree: %w", err) + } + } + + return newRoot, nil +} + +func UpgradeActorsV7(ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache, cb stmgr.ExecMonitor, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) { + // Use all the CPUs except 3. + workerCount := runtime.NumCPU() - 3 + if workerCount <= 0 { + workerCount = 1 + } + + config := nv14.Config{ + MaxWorkers: uint(workerCount), + JobQueueSize: 1000, + ResultQueueSize: 100, + ProgressLogPeriod: 10 * time.Second, + } + + newRoot, err := upgradeActorsV7Common(ctx, sm, cache, root, epoch, ts, config) + if err != nil { + return cid.Undef, xerrors.Errorf("migrating actors v6 state: %w", err) + } + + return newRoot, nil +} + +func PreUpgradeActorsV7(ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) error { + // Use half the CPUs for pre-migration, but leave at least 3. + workerCount := runtime.NumCPU() + if workerCount <= 4 { + workerCount = 1 + } else { + workerCount /= 2 + } + + //TODO: nv15 + config := nv14.Config{MaxWorkers: uint(workerCount)} + _, err := upgradeActorsV7Common(ctx, sm, cache, root, epoch, ts, config) + return err +} + +func upgradeActorsV7Common( + ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache, + root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet, + //TODO: nv15 + config nv14.Config, +) (cid.Cid, error) { + buf := blockstore.NewTieredBstore(sm.ChainStore().StateBlockstore(), blockstore.NewMemorySync()) + store := store.ActorStore(ctx, buf) + + // Load the state root. + var stateRoot types.StateRoot + if err := store.Get(ctx, root, &stateRoot); err != nil { + return cid.Undef, xerrors.Errorf("failed to decode state root: %w", err) + } + + if stateRoot.Version != types.StateTreeVersion4 { + return cid.Undef, xerrors.Errorf( + "expected state root version 4 for actors v7 upgrade, got %d", + stateRoot.Version, + ) + } + + // Perform the migration + //TODO: nv15 + newHamtRoot, err := nv14.MigrateStateTree(ctx, store, stateRoot.Actors, epoch, config, migrationLogger{}, cache) + if err != nil { + return cid.Undef, xerrors.Errorf("upgrading to actors v7: %w", err) } // Persist the result. diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 69ab32d58..60dd142e9 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -9,6 +9,8 @@ import ( "sync/atomic" "time" + proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" + "github.com/filecoin-project/lotus/chain/rand" "github.com/filecoin-project/go-state-types/network" @@ -686,6 +688,10 @@ func (m genFakeVerifier) VerifyAggregateSeals(aggregate proof5.AggregateSealVeri panic("not supported") } +func (m genFakeVerifier) VerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) (bool, error) { + panic("not supported") +} + func (m genFakeVerifier) VerifyWinningPoSt(ctx context.Context, info proof5.WinningPoStVerifyInfo) (bool, error) { panic("not supported") } diff --git a/chain/gen/genesis/miners.go b/chain/gen/genesis/miners.go index edacfe304..666912058 100644 --- a/chain/gen/genesis/miners.go +++ b/chain/gen/genesis/miners.go @@ -6,6 +6,8 @@ import ( "fmt" "math/rand" + runtime7 "github.com/filecoin-project/specs-actors/v7/actors/runtime" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" "github.com/ipfs/go-cid" @@ -29,7 +31,6 @@ import ( market4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/market" power4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/power" reward4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/reward" - runtime5 "github.com/filecoin-project/specs-actors/v5/actors/runtime" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" @@ -57,7 +58,7 @@ func MinerAddress(genesisIndex uint64) address.Address { } type fakedSigSyscalls struct { - runtime5.Syscalls + runtime7.Syscalls } func (fss *fakedSigSyscalls) VerifySignature(signature crypto.Signature, signer address.Address, plaintext []byte) error { @@ -65,7 +66,7 @@ func (fss *fakedSigSyscalls) VerifySignature(signature crypto.Signature, signer } func mkFakedSigSyscalls(base vm.SyscallBuilder) vm.SyscallBuilder { - return func(ctx context.Context, rt *vm.Runtime) runtime5.Syscalls { + return func(ctx context.Context, rt *vm.Runtime) runtime7.Syscalls { return &fakedSigSyscalls{ base(ctx, rt), } diff --git a/chain/state/statetree.go b/chain/state/statetree.go index f230f7faa..9a518a622 100644 --- a/chain/state/statetree.go +++ b/chain/state/statetree.go @@ -159,7 +159,7 @@ func VersionForNetwork(ver network.Version) (types.StateTreeVersion, error) { /* inline-gen start */ - case network.Version13, network.Version14: + case network.Version13, network.Version14, network.Version15: /* inline-gen end */ return types.StateTreeVersion4, nil diff --git a/chain/vm/gas.go b/chain/vm/gas.go index 206a55d36..27d9c8d94 100644 --- a/chain/vm/gas.go +++ b/chain/vm/gas.go @@ -3,13 +3,14 @@ package vm import ( "fmt" + vmr "github.com/filecoin-project/specs-actors/v7/actors/runtime" + proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" + "github.com/filecoin-project/go-address" addr "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/build" - vmr5 "github.com/filecoin-project/specs-actors/v5/actors/runtime" - proof5 "github.com/filecoin-project/specs-actors/v5/actors/runtime/proof" "github.com/ipfs/go-cid" ) @@ -73,9 +74,10 @@ type Pricelist interface { OnVerifySignature(sigType crypto.SigType, planTextSize int) (GasCharge, error) OnHashing(dataSize int) GasCharge OnComputeUnsealedSectorCid(proofType abi.RegisteredSealProof, pieces []abi.PieceInfo) GasCharge - OnVerifySeal(info proof5.SealVerifyInfo) GasCharge - OnVerifyAggregateSeals(aggregate proof5.AggregateSealVerifyProofAndInfos) GasCharge - OnVerifyPost(info proof5.WindowPoStVerifyInfo) GasCharge + OnVerifySeal(info proof7.SealVerifyInfo) GasCharge + OnVerifyAggregateSeals(aggregate proof7.AggregateSealVerifyProofAndInfos) GasCharge + OnVerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) GasCharge + OnVerifyPost(info proof7.WindowPoStVerifyInfo) GasCharge OnVerifyConsensusFault() GasCharge } @@ -227,7 +229,7 @@ func PricelistByEpoch(epoch abi.ChainEpoch) Pricelist { } type pricedSyscalls struct { - under vmr5.Syscalls + under vmr.Syscalls pl Pricelist chargeGas func(GasCharge) } @@ -261,7 +263,7 @@ func (ps pricedSyscalls) ComputeUnsealedSectorCID(reg abi.RegisteredSealProof, p } // Verifies a sector seal proof. -func (ps pricedSyscalls) VerifySeal(vi proof5.SealVerifyInfo) error { +func (ps pricedSyscalls) VerifySeal(vi proof7.SealVerifyInfo) error { ps.chargeGas(ps.pl.OnVerifySeal(vi)) defer ps.chargeGas(gasOnActorExec) @@ -269,7 +271,7 @@ func (ps pricedSyscalls) VerifySeal(vi proof5.SealVerifyInfo) error { } // Verifies a proof of spacetime. -func (ps pricedSyscalls) VerifyPoSt(vi proof5.WindowPoStVerifyInfo) error { +func (ps pricedSyscalls) VerifyPoSt(vi proof7.WindowPoStVerifyInfo) error { ps.chargeGas(ps.pl.OnVerifyPost(vi)) defer ps.chargeGas(gasOnActorExec) @@ -286,14 +288,14 @@ func (ps pricedSyscalls) VerifyPoSt(vi proof5.WindowPoStVerifyInfo) error { // the "parent grinding fault", in which case it must be the sibling of h1 (same parent tipset) and one of the // blocks in the parent of h2 (i.e. h2's grandparent). // Returns nil and an error if the headers don't prove a fault. -func (ps pricedSyscalls) VerifyConsensusFault(h1 []byte, h2 []byte, extra []byte) (*vmr5.ConsensusFault, error) { +func (ps pricedSyscalls) VerifyConsensusFault(h1 []byte, h2 []byte, extra []byte) (*vmr.ConsensusFault, error) { ps.chargeGas(ps.pl.OnVerifyConsensusFault()) defer ps.chargeGas(gasOnActorExec) return ps.under.VerifyConsensusFault(h1, h2, extra) } -func (ps pricedSyscalls) BatchVerifySeals(inp map[address.Address][]proof5.SealVerifyInfo) (map[address.Address][]bool, error) { +func (ps pricedSyscalls) BatchVerifySeals(inp map[address.Address][]proof7.SealVerifyInfo) (map[address.Address][]bool, error) { count := int64(0) for _, svis := range inp { count += int64(len(svis)) @@ -307,9 +309,16 @@ func (ps pricedSyscalls) BatchVerifySeals(inp map[address.Address][]proof5.SealV return ps.under.BatchVerifySeals(inp) } -func (ps pricedSyscalls) VerifyAggregateSeals(aggregate proof5.AggregateSealVerifyProofAndInfos) error { +func (ps pricedSyscalls) VerifyAggregateSeals(aggregate proof7.AggregateSealVerifyProofAndInfos) error { ps.chargeGas(ps.pl.OnVerifyAggregateSeals(aggregate)) defer ps.chargeGas(gasOnActorExec) return ps.under.VerifyAggregateSeals(aggregate) } + +func (ps pricedSyscalls) VerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) error { + ps.chargeGas(ps.pl.OnVerifyReplicaUpdate(update)) + defer ps.chargeGas(gasOnActorExec) + + return ps.under.VerifyReplicaUpdate(update) +} diff --git a/chain/vm/gas_v0.go b/chain/vm/gas_v0.go index 13c5fdd86..548227a33 100644 --- a/chain/vm/gas_v0.go +++ b/chain/vm/gas_v0.go @@ -3,8 +3,7 @@ package vm import ( "fmt" - proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" - proof5 "github.com/filecoin-project/specs-actors/v5/actors/runtime/proof" + proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" @@ -206,14 +205,14 @@ func (pl *pricelistV0) OnComputeUnsealedSectorCid(proofType abi.RegisteredSealPr } // OnVerifySeal -func (pl *pricelistV0) OnVerifySeal(info proof2.SealVerifyInfo) GasCharge { +func (pl *pricelistV0) OnVerifySeal(info proof7.SealVerifyInfo) GasCharge { // TODO: this needs more cost tunning, check with @lotus // this is not used return newGasCharge("OnVerifySeal", pl.verifySealBase, 0) } // OnVerifyAggregateSeals -func (pl *pricelistV0) OnVerifyAggregateSeals(aggregate proof5.AggregateSealVerifyProofAndInfos) GasCharge { +func (pl *pricelistV0) OnVerifyAggregateSeals(aggregate proof7.AggregateSealVerifyProofAndInfos) GasCharge { proofType := aggregate.SealProof perProof, ok := pl.verifyAggregateSealPer[proofType] if !ok { @@ -228,8 +227,14 @@ func (pl *pricelistV0) OnVerifyAggregateSeals(aggregate proof5.AggregateSealVeri return newGasCharge("OnVerifyAggregateSeals", perProof*num+step.Lookup(num), 0) } +// OnVerifyReplicaUpdate +func (pl *pricelistV0) OnVerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) GasCharge { + // TODO: do the thing + return GasCharge{} +} + // OnVerifyPost -func (pl *pricelistV0) OnVerifyPost(info proof2.WindowPoStVerifyInfo) GasCharge { +func (pl *pricelistV0) OnVerifyPost(info proof7.WindowPoStVerifyInfo) GasCharge { sectorSize := "unknown" var proofType abi.RegisteredPoStProof diff --git a/chain/vm/invoker.go b/chain/vm/invoker.go index 85357e51b..8a7a4c8c9 100644 --- a/chain/vm/invoker.go +++ b/chain/vm/invoker.go @@ -16,7 +16,7 @@ import ( cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - vmr "github.com/filecoin-project/specs-actors/v5/actors/runtime" + vmr "github.com/filecoin-project/specs-actors/v7/actors/runtime" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/exitcode" diff --git a/chain/vm/mkactor.go b/chain/vm/mkactor.go index ea49abff3..5716b5006 100644 --- a/chain/vm/mkactor.go +++ b/chain/vm/mkactor.go @@ -26,6 +26,7 @@ import ( builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" /* inline-gen end */ @@ -130,6 +131,8 @@ func newAccountActor(ver actors.Version) *types.Actor { code = builtin5.AccountActorCodeID case actors.Version6: code = builtin6.AccountActorCodeID + case actors.Version7: + code = builtin7.AccountActorCodeID /* inline-gen end */ default: panic("unsupported actors version") diff --git a/chain/vm/runtime.go b/chain/vm/runtime.go index 6e94030bd..583c99593 100644 --- a/chain/vm/runtime.go +++ b/chain/vm/runtime.go @@ -17,7 +17,7 @@ import ( rtt "github.com/filecoin-project/go-state-types/rt" rt0 "github.com/filecoin-project/specs-actors/actors/runtime" rt5 "github.com/filecoin-project/specs-actors/v5/actors/runtime" - rt6 "github.com/filecoin-project/specs-actors/v6/actors/runtime" + rt7 "github.com/filecoin-project/specs-actors/v7/actors/runtime" "github.com/ipfs/go-cid" ipldcbor "github.com/ipfs/go-ipld-cbor" "go.opencensus.io/trace" @@ -55,8 +55,8 @@ func (m *Message) ValueReceived() abi.TokenAmount { var EnableGasTracing = false type Runtime struct { - rt5.Message - rt5.Syscalls + rt7.Message + rt7.Syscalls ctx context.Context @@ -142,7 +142,7 @@ func (rt *Runtime) StorePut(x cbor.Marshaler) cid.Cid { var _ rt0.Runtime = (*Runtime)(nil) var _ rt5.Runtime = (*Runtime)(nil) -var _ rt6.Runtime = (*Runtime)(nil) +var _ rt7.Runtime = (*Runtime)(nil) func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) { defer func() { diff --git a/chain/vm/syscalls.go b/chain/vm/syscalls.go index 0cbefd1fd..b8c027bd7 100644 --- a/chain/vm/syscalls.go +++ b/chain/vm/syscalls.go @@ -7,6 +7,8 @@ import ( goruntime "runtime" "sync" + proof5 "github.com/filecoin-project/specs-actors/v5/actors/runtime/proof" + "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" "github.com/minio/blake2b-simd" @@ -26,8 +28,8 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/lib/sigs" - runtime5 "github.com/filecoin-project/specs-actors/v5/actors/runtime" - proof5 "github.com/filecoin-project/specs-actors/v5/actors/runtime/proof" + runtime7 "github.com/filecoin-project/specs-actors/v7/actors/runtime" + proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" ) func init() { @@ -36,10 +38,10 @@ func init() { // Actual type is defined in chain/types/vmcontext.go because the VMContext interface is there -type SyscallBuilder func(ctx context.Context, rt *Runtime) runtime5.Syscalls +type SyscallBuilder func(ctx context.Context, rt *Runtime) runtime7.Syscalls func Syscalls(verifier ffiwrapper.Verifier) SyscallBuilder { - return func(ctx context.Context, rt *Runtime) runtime5.Syscalls { + return func(ctx context.Context, rt *Runtime) runtime7.Syscalls { return &syscallShim{ ctx: ctx, @@ -90,7 +92,7 @@ func (ss *syscallShim) HashBlake2b(data []byte) [32]byte { // Checks validity of the submitted consensus fault with the two block headers needed to prove the fault // and an optional extra one to check common ancestry (as needed). // Note that the blocks are ordered: the method requires a.Epoch() <= b.Epoch(). -func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime5.ConsensusFault, error) { +func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime7.ConsensusFault, error) { // Note that block syntax is not validated. Any validly signed block will be accepted pursuant to the below conditions. // Whether or not it could ever have been accepted in a chain is not checked/does not matter here. // for that reason when checking block parent relationships, rather than instantiating a Tipset to do so @@ -133,14 +135,14 @@ func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime5.Conse } // (2) check for the consensus faults themselves - var consensusFault *runtime5.ConsensusFault + var consensusFault *runtime7.ConsensusFault // (a) double-fork mining fault if blockA.Height == blockB.Height { - consensusFault = &runtime5.ConsensusFault{ + consensusFault = &runtime7.ConsensusFault{ Target: blockA.Miner, Epoch: blockB.Height, - Type: runtime5.ConsensusFaultDoubleForkMining, + Type: runtime7.ConsensusFaultDoubleForkMining, } } @@ -148,10 +150,10 @@ func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime5.Conse // strictly speaking no need to compare heights based on double fork mining check above, // but at same height this would be a different fault. if types.CidArrsEqual(blockA.Parents, blockB.Parents) && blockA.Height != blockB.Height { - consensusFault = &runtime5.ConsensusFault{ + consensusFault = &runtime7.ConsensusFault{ Target: blockA.Miner, Epoch: blockB.Height, - Type: runtime5.ConsensusFaultTimeOffsetMining, + Type: runtime7.ConsensusFaultTimeOffsetMining, } } @@ -171,10 +173,10 @@ func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte) (*runtime5.Conse if types.CidArrsEqual(blockA.Parents, blockC.Parents) && blockA.Height == blockC.Height && types.CidArrsContains(blockB.Parents, blockC.Cid()) && !types.CidArrsContains(blockB.Parents, blockA.Cid()) { - consensusFault = &runtime5.ConsensusFault{ + consensusFault = &runtime7.ConsensusFault{ Target: blockA.Miner, Epoch: blockB.Height, - Type: runtime5.ConsensusFaultParentGrinding, + Type: runtime7.ConsensusFaultParentGrinding, } } } @@ -286,6 +288,7 @@ func (ss *syscallShim) VerifyAggregateSeals(aggregate proof5.AggregateSealVerify if err != nil { return xerrors.Errorf("failed to verify aggregated PoRep: %w", err) } + if !ok { return fmt.Errorf("invalid aggregate proof") } @@ -293,6 +296,19 @@ func (ss *syscallShim) VerifyAggregateSeals(aggregate proof5.AggregateSealVerify return nil } +func (ss *syscallShim) VerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) error { + ok, err := ss.verifier.VerifyReplicaUpdate(update) + if err != nil { + return xerrors.Errorf("failed to verify replica update: %w", err) + } + + if !ok { + return fmt.Errorf("invalid replica update") + } + + return nil +} + func (ss *syscallShim) VerifySignature(sig crypto.Signature, addr address.Address, input []byte) error { // TODO: in genesis setup, we are currently faking signatures diff --git a/cmd/lotus-bench/caching_verifier.go b/cmd/lotus-bench/caching_verifier.go index f4cc0f837..7d5e993a0 100644 --- a/cmd/lotus-bench/caching_verifier.go +++ b/cmd/lotus-bench/caching_verifier.go @@ -5,10 +5,11 @@ import ( "context" "errors" + proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" - proof5 "github.com/filecoin-project/specs-actors/v5/actors/runtime/proof" "github.com/ipfs/go-datastore" "github.com/minio/blake2b-simd" cbg "github.com/whyrusleeping/cbor-gen" @@ -97,8 +98,12 @@ func (cv *cachingVerifier) GenerateWinningPoStSectorChallenge(ctx context.Contex return cv.backend.GenerateWinningPoStSectorChallenge(ctx, proofType, a, rnd, u) } -func (cv cachingVerifier) VerifyAggregateSeals(aggregate proof5.AggregateSealVerifyProofAndInfos) (bool, error) { +func (cv cachingVerifier) VerifyAggregateSeals(aggregate proof7.AggregateSealVerifyProofAndInfos) (bool, error) { return cv.backend.VerifyAggregateSeals(aggregate) } +func (cv cachingVerifier) VerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) (bool, error) { + return cv.backend.VerifyReplicaUpdate(update) +} + var _ ffiwrapper.Verifier = (*cachingVerifier)(nil) diff --git a/cmd/lotus-sim/simulation/mock/mock.go b/cmd/lotus-sim/simulation/mock/mock.go index 38648f758..7656aaa28 100644 --- a/cmd/lotus-sim/simulation/mock/mock.go +++ b/cmd/lotus-sim/simulation/mock/mock.go @@ -6,6 +6,8 @@ import ( "encoding/binary" "fmt" + proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" @@ -70,6 +72,12 @@ func (mockVerifier) VerifyAggregateSeals(aggregate proof5.AggregateSealVerifyPro ) return false, nil } + +// TODO: do the thing +func (mockVerifier) VerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) (bool, error) { + return false, nil +} + func (mockVerifier) VerifyWinningPoSt(ctx context.Context, info proof5.WinningPoStVerifyInfo) (bool, error) { panic("should not be called") } diff --git a/documentation/en/api-v0-methods.md b/documentation/en/api-v0-methods.md index 4d9530821..42bb945d0 100644 --- a/documentation/en/api-v0-methods.md +++ b/documentation/en/api-v0-methods.md @@ -4698,7 +4698,7 @@ Inputs: ] ``` -Response: `14` +Response: `15` ### StateReadState StateReadState returns the indicated actor's state. diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index b03f75e9d..3578a4492 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -4948,7 +4948,7 @@ Inputs: ] ``` -Response: `14` +Response: `15` ### StateReadState StateReadState returns the indicated actor's state. diff --git a/extern/sector-storage/ffiwrapper/types.go b/extern/sector-storage/ffiwrapper/types.go index a5b2fdf1f..1da7ea832 100644 --- a/extern/sector-storage/ffiwrapper/types.go +++ b/extern/sector-storage/ffiwrapper/types.go @@ -4,6 +4,8 @@ import ( "context" "io" + proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" + proof5 "github.com/filecoin-project/specs-actors/v5/actors/runtime/proof" "github.com/ipfs/go-cid" @@ -36,6 +38,7 @@ type Storage interface { type Verifier interface { VerifySeal(proof5.SealVerifyInfo) (bool, error) VerifyAggregateSeals(aggregate proof5.AggregateSealVerifyProofAndInfos) (bool, error) + VerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) (bool, error) VerifyWinningPoSt(ctx context.Context, info proof5.WinningPoStVerifyInfo) (bool, error) VerifyWindowPoSt(ctx context.Context, info proof5.WindowPoStVerifyInfo) (bool, error) diff --git a/extern/sector-storage/ffiwrapper/verifier_cgo.go b/extern/sector-storage/ffiwrapper/verifier_cgo.go index ff35ddc1f..37256b26f 100644 --- a/extern/sector-storage/ffiwrapper/verifier_cgo.go +++ b/extern/sector-storage/ffiwrapper/verifier_cgo.go @@ -6,6 +6,8 @@ package ffiwrapper import ( "context" + proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" + "go.opencensus.io/trace" "golang.org/x/xerrors" @@ -120,6 +122,11 @@ func (proofVerifier) VerifyAggregateSeals(aggregate proof5.AggregateSealVerifyPr return ffi.VerifyAggregateSeals(aggregate) } +func (proofVerifier) VerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) (bool, error) { + //TODO: do the thing + return false, nil +} + func (proofVerifier) VerifyWinningPoSt(ctx context.Context, info proof5.WinningPoStVerifyInfo) (bool, error) { info.Randomness[31] &= 0x3f _, span := trace.StartSpan(ctx, "VerifyWinningPoSt") diff --git a/extern/sector-storage/mock/mock.go b/extern/sector-storage/mock/mock.go index 273f0928e..8fb356d0b 100644 --- a/extern/sector-storage/mock/mock.go +++ b/extern/sector-storage/mock/mock.go @@ -10,6 +10,8 @@ import ( "math/rand" "sync" + proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" + proof5 "github.com/filecoin-project/specs-actors/v5/actors/runtime/proof" ffiwrapper2 "github.com/filecoin-project/go-commp-utils/ffiwrapper" @@ -547,6 +549,11 @@ func (m mockVerifProver) VerifyAggregateSeals(aggregate proof5.AggregateSealVeri return ok, nil } +// TODO: do the thing +func (m mockVerifProver) VerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) (bool, error) { + return false, nil +} + func (m mockVerifProver) AggregateSealProofs(aggregateInfo proof5.AggregateSealVerifyProofAndInfos, proofs [][]byte) ([]byte, error) { out := make([]byte, m.aggLen(len(aggregateInfo.Infos))) // todo: figure out more real length for pi, proof := range proofs { diff --git a/gen/inlinegen-data.json b/gen/inlinegen-data.json index e26b1b28f..ef97db651 100644 --- a/gen/inlinegen-data.json +++ b/gen/inlinegen-data.json @@ -1,7 +1,7 @@ { - "actorVersions": [0, 2, 3, 4, 5, 6], - "latestActorsVersion": 6, + "actorVersions": [0, 2, 3, 4, 5, 6, 7], + "latestActorsVersion": 7, - "networkVersions": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], - "latestNetworkVersion": 14 + "networkVersions": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], + "latestNetworkVersion": 15 } diff --git a/go.mod b/go.mod index 37e6bb916..fd898ab5f 100644 --- a/go.mod +++ b/go.mod @@ -50,6 +50,7 @@ require ( github.com/filecoin-project/specs-actors/v4 v4.0.1 github.com/filecoin-project/specs-actors/v5 v5.0.4 github.com/filecoin-project/specs-actors/v6 v6.0.1 + github.com/filecoin-project/specs-actors/v7 v7.0.0-20211110223913-e2abd33b42d4 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.1 diff --git a/go.sum b/go.sum index 6019140fc..c9f2d33cb 100644 --- a/go.sum +++ b/go.sum @@ -391,8 +391,13 @@ github.com/filecoin-project/specs-actors/v4 v4.0.1/go.mod h1:TkHXf/l7Wyw4ZejyXIP github.com/filecoin-project/specs-actors/v5 v5.0.0-20210512015452-4fe3889fff57/go.mod h1:283yBMMUSDB2abcjP/hhrwTkhb9h3sfM6KGrep/ZlBI= github.com/filecoin-project/specs-actors/v5 v5.0.4 h1:OY7BdxJWlUfUFXWV/kpNBYGXNPasDIedf42T3sGx08s= github.com/filecoin-project/specs-actors/v5 v5.0.4/go.mod h1:5BAKRAMsOOlD8+qCw4UvT/lTLInCJ3JwOWZbX8Ipwq4= +github.com/filecoin-project/specs-actors/v6 v6.0.0/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= github.com/filecoin-project/specs-actors/v6 v6.0.1 h1:laxvHNsvrq83Y9n+W7znVCePi3oLyRf0Rkl4jFO8Wew= github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= +github.com/filecoin-project/specs-actors/v7 v7.0.0-20211109185520-8807da1012c5 h1:8SCNu2TkLCfsS8BpRfeOVt5e4pw2Ej3GInDlFEWqKHo= +github.com/filecoin-project/specs-actors/v7 v7.0.0-20211109185520-8807da1012c5/go.mod h1:F3/N4dIRgwEcSk7xp3RizaVyBE/Jlzhv9Le1/ZH50ZA= +github.com/filecoin-project/specs-actors/v7 v7.0.0-20211110223913-e2abd33b42d4 h1:5sswsw6rhw/JFG5+xU4En5na4K5QPf3jZ33zvAzGrY8= +github.com/filecoin-project/specs-actors/v7 v7.0.0-20211110223913-e2abd33b42d4/go.mod h1:F3/N4dIRgwEcSk7xp3RizaVyBE/Jlzhv9Le1/ZH50ZA= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 h1:Ur/l2+6qN+lQiqjozWWc5p9UDaAMDZKTlDS98oRnlIw= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= diff --git a/itests/kit/ensemble_opts_nv.go b/itests/kit/ensemble_opts_nv.go index 0d7d87e6a..45ed51443 100644 --- a/itests/kit/ensemble_opts_nv.go +++ b/itests/kit/ensemble_opts_nv.go @@ -49,12 +49,12 @@ func LatestActorsAt(upgradeHeight abi.ChainEpoch) EnsembleOpt { }) /* inline-gen start */ return UpgradeSchedule(stmgr.Upgrade{ - Network: network.Version13, + Network: network.Version14, Height: -1, }, stmgr.Upgrade{ - Network: network.Version14, + Network: network.Version15, Height: upgradeHeight, - Migration: filcns.UpgradeActorsV6, + Migration: filcns.UpgradeActorsV7, }) /* inline-gen end */ } diff --git a/lotuspond/front/src/chain/methods.json b/lotuspond/front/src/chain/methods.json index c0f69d58c..1f6191a94 100644 --- a/lotuspond/front/src/chain/methods.json +++ b/lotuspond/front/src/chain/methods.json @@ -622,5 +622,112 @@ "AddVerifiedClient", "UseBytes", "RestoreBytes" + ], + "fil/7/account": [ + "Send", + "Constructor", + "PubkeyAddress" + ], + "fil/7/cron": [ + "Send", + "Constructor", + "EpochTick" + ], + "fil/7/init": [ + "Send", + "Constructor", + "Exec" + ], + "fil/7/multisig": [ + "Send", + "Constructor", + "Propose", + "Approve", + "Cancel", + "AddSigner", + "RemoveSigner", + "SwapSigner", + "ChangeNumApprovalsThreshold", + "LockBalance" + ], + "fil/7/paymentchannel": [ + "Send", + "Constructor", + "UpdateChannelState", + "Settle", + "Collect" + ], + "fil/7/reward": [ + "Send", + "Constructor", + "AwardBlockReward", + "ThisEpochReward", + "UpdateNetworkKPI" + ], + "fil/7/storagemarket": [ + "Send", + "Constructor", + "AddBalance", + "WithdrawBalance", + "PublishStorageDeals", + "VerifyDealsForActivation", + "ActivateDeals", + "OnMinerSectorsTerminate", + "ComputeDataCommitment", + "CronTick" + ], + "fil/7/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", + "PreCommitSectorBatch", + "ProveCommitAggregate", + "ProveReplicaUpdates" + ], + "fil/7/storagepower": [ + "Send", + "Constructor", + "CreateMiner", + "UpdateClaimedPower", + "EnrollCronEvent", + "OnEpochTickEnd", + "UpdatePledgeTotal", + "SubmitPoRepForBulkVerify", + "CurrentTotalPower" + ], + "fil/7/system": [ + "Send", + "Constructor" + ], + "fil/7/verifiedregistry": [ + "Send", + "Constructor", + "AddVerifier", + "RemoveVerifier", + "AddVerifiedClient", + "UseBytes", + "RestoreBytes" ] } \ No newline at end of file diff --git a/storage/wdpost_run_test.go b/storage/wdpost_run_test.go index 78d9431d4..9ece295ca 100644 --- a/storage/wdpost_run_test.go +++ b/storage/wdpost_run_test.go @@ -5,6 +5,8 @@ import ( "context" "testing" + proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner" @@ -22,12 +24,6 @@ import ( "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/go-state-types/network" - builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" - miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" - proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" - tutils "github.com/filecoin-project/specs-actors/v2/support/testing" - proof5 "github.com/filecoin-project/specs-actors/v5/actors/runtime/proof" - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" @@ -35,6 +31,10 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/extern/sector-storage/storiface" "github.com/filecoin-project/lotus/journal" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" + proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" + tutils "github.com/filecoin-project/specs-actors/v2/support/testing" ) type mockStorageMinerAPI struct { @@ -149,7 +149,11 @@ func (m mockVerif) VerifyWindowPoSt(ctx context.Context, info proof2.WindowPoStV return true, nil } -func (m mockVerif) VerifyAggregateSeals(aggregate proof5.AggregateSealVerifyProofAndInfos) (bool, error) { +func (m mockVerif) VerifyAggregateSeals(aggregate proof7.AggregateSealVerifyProofAndInfos) (bool, error) { + panic("implement me") +} + +func (m mockVerif) VerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) (bool, error) { panic("implement me") } diff --git a/testplans/lotus-soup/go.mod b/testplans/lotus-soup/go.mod index 7f4a53630..fdf53cfc2 100644 --- a/testplans/lotus-soup/go.mod +++ b/testplans/lotus-soup/go.mod @@ -3,15 +3,15 @@ module github.com/filecoin-project/lotus/testplans/lotus-soup go 1.16 require ( - contrib.go.opencensus.io/exporter/prometheus v0.1.0 + contrib.go.opencensus.io/exporter/prometheus v0.4.0 github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe github.com/davecgh/go-spew v1.1.1 github.com/drand/drand v1.2.1 - github.com/filecoin-project/go-address v0.0.5 - github.com/filecoin-project/go-data-transfer v1.10.1 - github.com/filecoin-project/go-fil-markets v1.12.0 - github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec - github.com/filecoin-project/go-state-types v0.1.1-0.20210915140513-d354ccf10379 + github.com/filecoin-project/go-address v0.0.6 + github.com/filecoin-project/go-data-transfer v1.11.4 + github.com/filecoin-project/go-fil-markets v1.13.3 + github.com/filecoin-project/go-jsonrpc v0.1.5 + github.com/filecoin-project/go-state-types v0.1.1 github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b github.com/filecoin-project/lotus v0.0.0-00010101000000-000000000000 github.com/filecoin-project/specs-actors v0.9.14 @@ -21,17 +21,17 @@ require ( github.com/influxdata/influxdb v1.9.4 // indirect github.com/ipfs/go-cid v0.1.0 github.com/ipfs/go-datastore v0.4.6 - github.com/ipfs/go-ipfs-files v0.0.8 + github.com/ipfs/go-ipfs-files v0.0.9 github.com/ipfs/go-ipld-format v0.2.0 github.com/ipfs/go-log/v2 v2.3.0 - github.com/ipfs/go-merkledag v0.3.2 + github.com/ipfs/go-merkledag v0.4.1 github.com/ipfs/go-unixfs v0.2.6 - github.com/ipld/go-car v0.3.1-null-padded-files + github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823 github.com/kpacha/opencensus-influxdb v0.0.0-20181102202715-663e2683a27c github.com/libp2p/go-libp2p v0.15.0 github.com/libp2p/go-libp2p-core v0.9.0 github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6 - github.com/multiformats/go-multiaddr v0.4.0 + github.com/multiformats/go-multiaddr v0.4.1 github.com/testground/sdk-go v0.2.6 go.opencensus.io v0.23.0 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c diff --git a/testplans/lotus-soup/go.sum b/testplans/lotus-soup/go.sum index b6246d634..b31a93753 100644 --- a/testplans/lotus-soup/go.sum +++ b/testplans/lotus-soup/go.sum @@ -38,8 +38,10 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= contrib.go.opencensus.io/exporter/jaeger v0.1.0/go.mod h1:VYianECmuFPwU37O699Vc1GOcy+y8kOsfaxHRImmjbA= +contrib.go.opencensus.io/exporter/jaeger v0.2.1/go.mod h1:Y8IsLgdxqh1QxYxPC5IgXVmBaeLUeQFfBeBi9PbeZd0= contrib.go.opencensus.io/exporter/prometheus v0.1.0 h1:SByaIoWwNgMdPSgl5sMqM2KDE5H/ukPWBRo314xiDvg= contrib.go.opencensus.io/exporter/prometheus v0.1.0/go.mod h1:cGFniUXGZlKRjzOyuZJ6mgB+PgBcCIa79kEKR8YCW+A= +contrib.go.opencensus.io/exporter/prometheus v0.4.0/go.mod h1:o7cosnyfuPVK0tB8q0QmaQNhGnptITnPQB+z1+qeFB0= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -80,6 +82,7 @@ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbt github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= @@ -90,10 +93,12 @@ github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/ github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.0 h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voiMLQ= github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= +github.com/GeertJohan/go.rice v1.0.2/go.mod h1:af5vUNlDNkCjOZeSGFgIJxDje9qdjsO6hshx0gTmZt4= github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee h1:8doiS7ib3zi6/K172oDhSKU0dJ/miJramo9NITOMyZQ= github.com/Gurpartap/async v0.0.0-20180927173644-4f7f499dd9ee/go.mod h1:W0GbEAA4uFNYOGG2cJpmFJ04E6SD1NLELPYZB57/7AY= github.com/HdrHistogram/hdrhistogram-go v1.1.0 h1:6dpdDPTRoo78HxAJ6T1HfMiKSnqhgRRqzCuPshRkQ7I= github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= github.com/Kubuxu/imtui v0.0.0-20210401140320-41663d68d0fa h1:1PPxEyGdIGVkX/kqMvLJ95a1dGS1Sz7tpNEgehEYYt0= @@ -115,6 +120,7 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/Stebalien/go-bitfield v0.0.1 h1:X3kbSSPUaJK60wV2hjOPZwmpljr6VGCqdq4cBLhbQBo= github.com/Stebalien/go-bitfield v0.0.1/go.mod h1:GNjFpasyUVkHMsfEOk8EFLJ9syQ6SI+XWrX9Wf2XH0s= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= @@ -146,7 +152,9 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= @@ -159,12 +167,15 @@ github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN github.com/aws/aws-sdk-go v1.29.16/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= github.com/aws/aws-sdk-go v1.30.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go v1.32.11/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v1.3.2/go.mod h1:7OaACgj2SX3XGWnrIjGlJM22h6yD6MEWKvm7levnnM8= +github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2/config v1.1.5/go.mod h1:P3F1hku7qzC81txjwXnwOM6Ex6ezkU6+/557Teyb64E= github.com/aws/aws-sdk-go-v2/credentials v1.1.5/go.mod h1:Ir1R6tPiR1/2y1hes8yOijFMz54hzSmgcmCDo6F45Qc= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.6/go.mod h1:0+fWMitrmIpENiY8/1DyhdYPUCAPvd9UNz9mtCsEoLQ= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.1.2/go.mod h1:Azf567f5wBUfUbwpyJJnLM/geFFIzEulGR30L+nQZOE= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.4/go.mod h1:BCfU3Uo2fhKcMZFp9zU5QQGQxqWCOYmZ/27Dju3S/do= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.6/go.mod h1:L0KWr0ASo83PRZu9NaZaDsw3koS6PspKv137DMDZjHo= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.2.2/go.mod h1:nnutjMLuna0s3GVY/MAkpLX03thyNER06gXvnMAPj5g= @@ -172,6 +183,7 @@ github.com/aws/aws-sdk-go-v2/service/s3 v1.5.0/go.mod h1:uwA7gs93Qcss43astPUb1eq github.com/aws/aws-sdk-go-v2/service/sso v1.1.5/go.mod h1:bpGz0tidC4y39sZkQSkpO/J0tzWCMXHbw6FZ0j1GkWM= github.com/aws/aws-sdk-go-v2/service/sts v1.2.2/go.mod h1:ssRzzJ2RZOVuKj2Vx1YE7ypfil/BIlgmQnCSW4DistU= github.com/aws/smithy-go v1.3.1/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= github.com/benbjohnson/clock v1.0.1/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.0.2/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= @@ -214,10 +226,12 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 h1:gfAMKE626QEuKG3si0pdTRcr/YEbBoxY+3GOH3gWvl4= github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U= +github.com/buger/goterm v1.0.3/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/cactus/go-statsd-client/statsd v0.0.0-20191106001114-12b4e2b38748/go.mod h1:l/bIBLeOl9eX+wxJAzxS4TveKRtAqlyDpHjhkfO0MEI= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= github.com/cenkalti/backoff v0.0.0-20181003080854-62661b46c409/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= @@ -228,6 +242,7 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= @@ -239,6 +254,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -271,6 +287,7 @@ github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pq github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/corpix/uarand v0.1.1/go.mod h1:SFKZvkcRoLqVRFZ4u25xPmp6m9ktANfbpXZ7SJ0/FNU= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= @@ -346,10 +363,12 @@ github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7j github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elastic/go-sysinfo v1.3.0 h1:eb2XFGTMlSwG/yyU9Y8jVAYLIzU2sFzWXwo2gmetyrE= github.com/elastic/go-sysinfo v1.3.0/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6eh0ikPT9F0= +github.com/elastic/go-sysinfo v1.7.0/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6eh0ikPT9F0= github.com/elastic/go-windows v1.0.0 h1:qLURgZFkkrYyTTkvYpsZIgf83AUsdIHfvlJaqaZ7aSY= github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6CcloAxnPgU= github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/elastic/gosigar v0.14.1/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/ema/qdisc v0.0.0-20190904071900-b82c76788043/go.mod h1:ix4kG2zvdUd8kEKSW0ZTr1XLks0epFpI4j745DXxlNE= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -358,6 +377,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etclabscore/go-jsonschema-walk v0.0.6/go.mod h1:VdfDY72AFAiUhy0ZXEaWSpveGjMT5JcDIm903NGqFwQ= @@ -369,12 +389,15 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fatih/color v1.8.0/go.mod h1:3l45GVGkyrnYNl9HoIjnp2NnNWvh6hLAqD8yTfGjnw8= github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/filecoin-project/dagstore v0.4.2/go.mod h1:WY5OoLfnwISCk6eASSF927KKPqLPIlTwmG1qHpA08KY= github.com/filecoin-project/dagstore v0.4.3 h1:yeFl6+2BRY1gOVp/hrZuFa24s7LY0Qqkqx/Gh8lidZs= github.com/filecoin-project/dagstore v0.4.3/go.mod h1:dm/91AO5UaDd3bABFjg/5fmRH99vvpS7g1mykqvz6KQ= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= github.com/filecoin-project/go-address v0.0.5 h1:SSaFT/5aLfPXycUlFyemoHYhRgdyXClXCyDdNJKPlDM= github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= +github.com/filecoin-project/go-address v0.0.6/go.mod h1:7B0/5DA13n6nHkB8bbGx1gWzG/dbTsZ0fgOJVGsM3TE= github.com/filecoin-project/go-amt-ipld/v2 v2.1.0 h1:t6qDiuGYYngDqaLc2ZUvdtAg4UNxPeOYaXhBWSNsVaM= github.com/filecoin-project/go-amt-ipld/v2 v2.1.0/go.mod h1:nfFPoGyX0CU9SkXX8EoCcSuHN1XcbN0c6KBh7yvP5fs= github.com/filecoin-project/go-amt-ipld/v3 v3.0.0/go.mod h1:Qa95YNAbtoVCTSVtX38aAC1ptBnJfPma1R/zZsKmx4o= @@ -386,14 +409,18 @@ github.com/filecoin-project/go-bitfield v0.2.4 h1:uZ7MeE+XfM5lqrHJZ93OnhQKc/rveW github.com/filecoin-project/go-bitfield v0.2.4/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM= github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:av5fw6wmm58FYMgJeoB/lK9XXrgdugYiTqkdxjTy9k8= github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg= +github.com/filecoin-project/go-cbor-util v0.0.1/go.mod h1:pqTiPHobNkOVM5thSRsHYjyQfq7O5QSCMhvuu9JoDlg= github.com/filecoin-project/go-commp-utils v0.1.1-0.20210427191551-70bf140d31c7 h1:U9Z+76pHCKBmtdxFV7JFZJj7OVm12I6dEKwtMVbq5p0= github.com/filecoin-project/go-commp-utils v0.1.1-0.20210427191551-70bf140d31c7/go.mod h1:6s95K91mCyHY51RPWECZieD3SGWTqIFLf1mPOes9l5U= +github.com/filecoin-project/go-commp-utils v0.1.2/go.mod h1:6s95K91mCyHY51RPWECZieD3SGWTqIFLf1mPOes9l5U= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= +github.com/filecoin-project/go-crypto v0.0.1/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-data-transfer v1.0.1/go.mod h1:UxvfUAY9v3ub0a21BSK9u3pB2aq30Y0KMsG+w9/ysyo= github.com/filecoin-project/go-data-transfer v1.10.0/go.mod h1:uQtqy6vUAY5v70ZHdkF5mJ8CjVtjj/JA3aOoaqzWTVw= github.com/filecoin-project/go-data-transfer v1.10.1 h1:YQNLwhizxkdfFxegAyrnn3l7WjgMjqDlqFzr18iWiYI= github.com/filecoin-project/go-data-transfer v1.10.1/go.mod h1:CSDMCrPK2lVGodNB1wPEogjFvM9nVGyiL1GNbBRTSdw= +github.com/filecoin-project/go-data-transfer v1.11.4/go.mod h1:2MitLI0ebCkLlPKM7NRggP/t9d+gCcREUKkCKqWRCwU= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= @@ -405,6 +432,7 @@ github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0 github.com/filecoin-project/go-fil-markets v1.0.5-0.20201113164554-c5eba40d5335/go.mod h1:AJySOJC00JRWEZzRG2KsfUnqEf5ITXxeX09BE9N4f9c= github.com/filecoin-project/go-fil-markets v1.12.0 h1:RpU5bLaMADVrU4CgLxKMGHC2ZUocNV35uINxogQCf00= github.com/filecoin-project/go-fil-markets v1.12.0/go.mod h1:XuuZFaFujI47nrgfQJiq7jWB+6rRya6nm7Sj6uXQ80U= +github.com/filecoin-project/go-fil-markets v1.13.3/go.mod h1:38zuj8AgDvOfdakFLpC/syYIYgXTzkq7xqBJ6T1AuG4= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -414,10 +442,12 @@ github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AG github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec h1:rGI5I7fdU4viManxmDdbk5deZO7afe6L1Wc04dAmlOM= github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= +github.com/filecoin-project/go-jsonrpc v0.1.5/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= github.com/filecoin-project/go-multistore v0.0.3/go.mod h1:kaNqCC4IhU4B1uyr7YWFHd23TL4KM32aChS0jNkyUvQ= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1 h1:0BogtftbcgyBx4lP2JWM00ZK7/pXmgnrDqKp9aLTgVs= github.com/filecoin-project/go-padreader v0.0.0-20210723183308-812a16dc01b1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= +github.com/filecoin-project/go-padreader v0.0.1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= github.com/filecoin-project/go-paramfetch v0.0.2 h1:a6W3Ij6CKhwHYYlx+5mqvBIyw4CabZH2ojdEaoAZ6/g= github.com/filecoin-project/go-paramfetch v0.0.2/go.mod h1:1FH85P8U+DUEmWk1Jkw3Bw7FrwTVUNHk/95PSPG+dts= github.com/filecoin-project/go-state-types v0.0.0-20200903145444-247639ffa6ad/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= @@ -428,6 +458,8 @@ github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psS github.com/filecoin-project/go-state-types v0.1.1-0.20210506134452-99b279731c48/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.1-0.20210810190654-139e0e79e69e h1:XAgb6HmgXaGRklNjhZoNMSIYriKLqjWXIqYMotg6iSs= github.com/filecoin-project/go-state-types v0.1.1-0.20210810190654-139e0e79e69e/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= +github.com/filecoin-project/go-state-types v0.1.1-0.20210915140513-d354ccf10379/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= +github.com/filecoin-project/go-state-types v0.1.1/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statemachine v1.0.1 h1:LQ60+JDVjMdLxXmVFM2jjontzOYnfVE7u02CXV3WKSw= github.com/filecoin-project/go-statemachine v1.0.1/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= @@ -454,6 +486,9 @@ github.com/filecoin-project/specs-actors/v4 v4.0.1/go.mod h1:TkHXf/l7Wyw4ZejyXIP github.com/filecoin-project/specs-actors/v5 v5.0.0-20210512015452-4fe3889fff57/go.mod h1:283yBMMUSDB2abcjP/hhrwTkhb9h3sfM6KGrep/ZlBI= github.com/filecoin-project/specs-actors/v5 v5.0.4 h1:OY7BdxJWlUfUFXWV/kpNBYGXNPasDIedf42T3sGx08s= github.com/filecoin-project/specs-actors/v5 v5.0.4/go.mod h1:5BAKRAMsOOlD8+qCw4UvT/lTLInCJ3JwOWZbX8Ipwq4= +github.com/filecoin-project/specs-actors/v6 v6.0.0/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= +github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= +github.com/filecoin-project/specs-actors/v7 v7.0.0-20211104150953-8bd473fc487a/go.mod h1:F3/N4dIRgwEcSk7xp3RizaVyBE/Jlzhv9Le1/ZH50ZA= 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/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= @@ -467,6 +502,7 @@ github.com/foxcpp/go-mockdns v0.0.0-20201212160233-ede2f9158d15/go.mod h1:tPg4cp github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= @@ -475,6 +511,7 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 h1:EzDjxMg43q1tA2c0MV3tNbaontnHLplHyFF6M5KiVP0= github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1/go.mod h1:0eHX/BVySxPc6SE2mZRoppGq7qcEagxdmQnA3dzork8= +github.com/gbrlsnchs/jwt/v3 v3.0.1/go.mod h1:AncDcjXz18xetI3A6STfXq2w+LuTx8pQ8bGEwRN8zVM= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell/v2 v2.2.0 h1:vSyEgKwraXPSOkvCk7IwOSyX+Pv3V2cV9CikJMXg4U4= @@ -500,15 +537,19 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -581,6 +622,7 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= @@ -609,6 +651,7 @@ github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968 h1:s+PDl6lozQ+dEUtUtQn github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= @@ -627,6 +670,7 @@ github.com/gogo/status v1.0.3/go.mod h1:SavQ51ycCLnc7dGyJxp8YAmudx8xqiVrRf+6IXRs github.com/gogo/status v1.1.0 h1:+eIkrewn5q6b30y+g/BJINVVdi2xH7je5MPJ3ZPK3JA= github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= @@ -637,6 +681,7 @@ github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -670,6 +715,7 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf h1:gFVkHXmVAhEbxZVDln5V9GKrLaluNoFHDbrZwAWZgws= github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -687,6 +733,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -759,16 +806,21 @@ github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e h1:3YKHER4n github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e/go.mod h1:I8h3MITA53gN9OnWGCgaMa0JWVRdXthWw4M3CPM54OY= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/api v1.4.0/go.mod h1:xc8u05kyMa3Wjr9eEAsIAo3dg8+LywT5E/Cl7cNS5nU= +github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.4.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.12.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.2.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= @@ -796,12 +848,15 @@ github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.2.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.9.0/go.mod h1:YL0HO+FifKOW2u1ke99DGVu1zhcpZzNwrLIqBC7vbYU= +github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hodgesds/perf-utils v0.0.8/go.mod h1:F6TfvsbtrF88i++hou29dTXlI2sfsJv+gRZDtmTJkAs= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goupnp v1.0.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= @@ -810,6 +865,8 @@ github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0 github.com/iancoleman/orderedmap v0.1.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428/go.mod h1:uhpZMVGznybq1itEKXj6RYw9I71qK4kH+OGMjRC4KEo= +github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94/go.mod h1:GYeBD1CF7AqnKZK+UCytLcY3G+UKo0ByXX/3xfdNyqQ= +github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA= github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -823,6 +880,7 @@ github.com/influxdata/influxdb-client-go/v2 v2.3.1-0.20210518120617-5d1fff431040 github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxdb1-client v0.0.0-20200515024757-02f0bf5dbca3 h1:k3/6a1Shi7GGCp9QpyYuXsMM6ncTOjCzOE9Fd6CDA+Q= github.com/influxdata/influxdb1-client v0.0.0-20200515024757-02f0bf5dbca3/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxql v1.1.0/go.mod h1:KpVI7okXjK6PRi3Z5B+mtKZli+R1DnZgb3N+tzevNgo= github.com/influxdata/influxql v1.1.1-0.20210223160523-b6ab99450c93/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= @@ -852,6 +910,7 @@ github.com/ipfs/go-blockservice v0.1.3/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYI github.com/ipfs/go-blockservice v0.1.4-0.20200624145336-a978cec6e834/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-blockservice v0.1.5 h1:euqZu96CCbToPyYVwVshu8ENURi8BhFd7FUFfTLi+fQ= github.com/ipfs/go-blockservice v0.1.5/go.mod h1:yLk8lBJCBRWRqerqCSVi3cE/Dncdt3vGC/PJMVKhLTY= +github.com/ipfs/go-blockservice v0.1.7/go.mod h1:GmS+BAt4hrwBKkzE11AFDQUrnvqjwFatGS2MY7wOjEM= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= @@ -910,10 +969,13 @@ github.com/ipfs/go-graphsync v0.4.3/go.mod h1:mPOwDYv128gf8gxPFgXnz4fNrSYPsWyqis github.com/ipfs/go-graphsync v0.9.0/go.mod h1:J62ahWT9JbPsFL2UWsUM5rOu0lZJ0LOIH1chHdxGGcw= github.com/ipfs/go-graphsync v0.9.1 h1:jo7ZaAZ3lal89RhKxKoRkPzIO8lmOY6KUWA1mDRZ2+U= github.com/ipfs/go-graphsync v0.9.1/go.mod h1:J62ahWT9JbPsFL2UWsUM5rOu0lZJ0LOIH1chHdxGGcw= +github.com/ipfs/go-graphsync v0.10.0/go.mod h1:cKIshzTaa5rCZjryH5xmSKZVGX9uk1wvwGvz2WEha5Y= +github.com/ipfs/go-graphsync v0.10.4/go.mod h1:oei4tnWAKnZ6LPnapZGPYVVbyiKV1UP3f8BeLU7Z4JQ= github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= github.com/ipfs/go-ipfs-blockstore v0.1.0/go.mod h1:5aD0AvHPi7mZc6Ci1WCAhiBQu2IsfTduLl+422H6Rqw= github.com/ipfs/go-ipfs-blockstore v0.1.4/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86HgIYJW/D/MwqeYQ= +github.com/ipfs/go-ipfs-blockstore v0.1.6/go.mod h1:Jxm3XMVjh6R17WvxFEiyKBLUGr86HgIYJW/D/MwqeYQ= github.com/ipfs/go-ipfs-blockstore v1.0.0/go.mod h1:knLVdhVU9L7CC4T+T4nvGdeUIPAXlnd9zmXfp+9MIjU= github.com/ipfs/go-ipfs-blockstore v1.0.1/go.mod h1:MGNZlHNEnR4KGgPHM3/k8lBySIOK2Ve+0KjZubKlaOE= github.com/ipfs/go-ipfs-blockstore v1.0.3/go.mod h1:MGNZlHNEnR4KGgPHM3/k8lBySIOK2Ve+0KjZubKlaOE= @@ -943,6 +1005,7 @@ github.com/ipfs/go-ipfs-files v0.0.3/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjN github.com/ipfs/go-ipfs-files v0.0.4/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= github.com/ipfs/go-ipfs-files v0.0.8 h1:8o0oFJkJ8UkO/ABl8T6ac6tKF3+NIpj67aAB6ZpusRg= github.com/ipfs/go-ipfs-files v0.0.8/go.mod h1:wiN/jSG8FKyk7N0WyctKSvq3ljIa2NNTiZB55kpTdOs= +github.com/ipfs/go-ipfs-files v0.0.9/go.mod h1:aFv2uQ/qxWpL/6lidWvnSQmaVqCrf0TBGoUr+C1Fo84= github.com/ipfs/go-ipfs-http-client v0.0.6 h1:k2QllZyP7Fz5hMgsX5hvHfn1WPG9Ngdy5WknQ7JNhBM= github.com/ipfs/go-ipfs-http-client v0.0.6/go.mod h1:8e2dQbntMZKxLfny+tyXJ7bJHZFERp/2vyzZdvkeLMc= github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= @@ -966,6 +1029,7 @@ github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dC github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k= github.com/ipfs/go-ipld-format v0.2.0 h1:xGlJKkArkmBvowr+GMCX0FEZtkro71K1AwiKnL37mwA= github.com/ipfs/go-ipld-format v0.2.0/go.mod h1:3l3C1uKoadTPbeNfrDi+xMInYKlx2Cvg1BuydPSdzQs= +github.com/ipfs/go-ipld-legacy v0.1.0/go.mod h1:86f5P/srAmh9GcIcWQR9lfFLZPrIyyXQeVlOWeeWEuI= github.com/ipfs/go-ipns v0.1.2 h1:O/s/0ht+4Jl9+VoxoUo0zaHjnZUS+aBQIKTuzdZ/ucI= github.com/ipfs/go-ipns v0.1.2/go.mod h1:ioQ0j02o6jdIVW+bmi18f4k2gRf0AV3kZ9KeHYHICnQ= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= @@ -993,6 +1057,7 @@ github.com/ipfs/go-merkledag v0.2.4/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB github.com/ipfs/go-merkledag v0.3.1/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= github.com/ipfs/go-merkledag v0.3.2 h1:MRqj40QkrWkvPswXs4EfSslhZ4RVPRbxwX11js0t1xY= github.com/ipfs/go-merkledag v0.3.2/go.mod h1:fvkZNNZixVW6cKSZ/JfLlON5OlgTXNdRLz0p6QG/I2M= +github.com/ipfs/go-merkledag v0.4.1/go.mod h1:56biPaS6e+IS0eXkEt6A8tG+BUQaEIFqDqJuFfQDBoE= github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= github.com/ipfs/go-metrics-prometheus v0.0.2/go.mod h1:ELLU99AQQNi+zX6GCGm2lAgnzdSH3u5UVlCdqSXnEks= @@ -1003,6 +1068,7 @@ github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3 github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-peertaskqueue v0.2.0 h1:2cSr7exUGKYyDeUyQ7P/nHPs9P7Ht/B+ROrpN1EJOjc= github.com/ipfs/go-peertaskqueue v0.2.0/go.mod h1:5/eNrBEbtSKWCG+kQK8K8fGNixoYUnr+P7jivavs9lY= +github.com/ipfs/go-peertaskqueue v0.6.0/go.mod h1:M/akTIE/z1jGNXMU7kFB4TeSEFvj68ow0Rrb04donIU= github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb/go.mod h1:IwAAgul1UQIcNZzKPYZWOCijryFBeCV79cNubPzol+k= github.com/ipfs/go-unixfs v0.2.4/go.mod h1:SUdisfUjNoSDzzhGVxvCL9QO/nKdwXdr+gbMUdqcbYw= @@ -1022,6 +1088,7 @@ github.com/ipld/go-car v0.1.1-0.20201119040415-11b6074b6d4d/go.mod h1:2Gys8L8MJ6 github.com/ipld/go-car v0.3.1-0.20210601190600-f512dac51e8e/go.mod h1:wUxBdwOLA9/0HZBi3fnTBzla0MuwlqgJLyrhOg1XaKI= github.com/ipld/go-car v0.3.1-null-padded-files h1:FMD0Ce4tAM9P5aq7yklw2jnVK3ZuoJ4xK6vkL9VLmxs= github.com/ipld/go-car v0.3.1-null-padded-files/go.mod h1:wUxBdwOLA9/0HZBi3fnTBzla0MuwlqgJLyrhOg1XaKI= +github.com/ipld/go-car v0.3.2-0.20211001225732-32d0d9933823/go.mod h1:jSlTph+i/q1jLFoiKKeN69KGG0fXpwrcD0izu5C1Tpo= github.com/ipld/go-car/v2 v2.0.0-beta1.0.20210721090610-5a9d1b217d25/go.mod h1:I2ACeeg6XNBe5pdh5TaR7Ambhfa7If9KXxmXgZsYENU= github.com/ipld/go-car/v2 v2.0.2/go.mod h1:I2ACeeg6XNBe5pdh5TaR7Ambhfa7If9KXxmXgZsYENU= github.com/ipld/go-car/v2 v2.0.3-0.20210811121346-c514a30114d7 h1:6Z0beJSZNsRY+7udoqUl4gQ/tqtrPuRvDySrlsvbqZA= @@ -1034,13 +1101,18 @@ github.com/ipld/go-ipld-prime v0.0.2-0.20200428162820-8b59dc292b8e/go.mod h1:uVI github.com/ipld/go-ipld-prime v0.5.1-0.20200828233916-988837377a7f/go.mod h1:0xEgdD6MKbZ1vF0GC+YcR/C4SQCAlRuOjIJ2i0HxqzM= github.com/ipld/go-ipld-prime v0.5.1-0.20201021195245-109253e8a018/go.mod h1:0xEgdD6MKbZ1vF0GC+YcR/C4SQCAlRuOjIJ2i0HxqzM= github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= +github.com/ipld/go-ipld-prime v0.9.1-0.20210324083106-dc342a9917db/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= +github.com/ipld/go-ipld-prime v0.10.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8= github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8= github.com/ipld/go-ipld-prime v0.12.0 h1:JapyKWTsJgmhrPI7hfx4V798c/RClr85sXfBZnH1VIw= github.com/ipld/go-ipld-prime v0.12.0/go.mod h1:hy8b93WleDMRKumOJnTIrr0MbbFbx9GD6Kzxa53Xppc= +github.com/ipld/go-ipld-prime v0.12.3-0.20210930132912-0b3aef3ca569/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= +github.com/ipld/go-ipld-prime v0.12.3/go.mod h1:PaeLYq8k6dJLmDUSLrzkEpoGV4PEfe/1OtFN/eALOc8= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU= github.com/ipld/go-ipld-prime-proto v0.0.0-20200428191222-c1ffdadc01e1/go.mod h1:OAV6xBmuTLsPZ+epzKkPB1e25FHk/vCtyatkdHcArLs= github.com/ipld/go-ipld-prime-proto v0.0.0-20200922192210-9a2bfd4440a6/go.mod h1:3pHYooM9Ea65jewRwrb2u5uHZCNkNTe9ABsVB+SrkH0= github.com/ipld/go-ipld-prime-proto v0.1.0/go.mod h1:11zp8f3sHVgIqtb/c9Kr5ZGqpnCLF1IVTNOez9TopzE= +github.com/ipld/go-ipld-selector-text-lite v0.0.0/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= @@ -1086,6 +1158,7 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= @@ -1117,6 +1190,8 @@ github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.11.7 h1:0hzRabrMN4tSTvMfnL3SCv1ZGeAP23ynzodBgaHeMeg= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -1324,6 +1399,7 @@ github.com/libp2p/go-libp2p-peerstore v0.2.7/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuD github.com/libp2p/go-libp2p-peerstore v0.2.8/go.mod h1:gGiPlXdz7mIHd2vfAsHzBNAMqSDkt2UBFwgcITgw1lA= github.com/libp2p/go-libp2p-peerstore v0.2.9 h1:tVa7siDymmzOl3b3+SxPYpQUCnicmK13y6Re1PqWK+g= github.com/libp2p/go-libp2p-peerstore v0.2.9/go.mod h1:zhBaLzxiWpNGQ3+uI17G/OIjmOD8GxKyFuHbrZbgs0w= +github.com/libp2p/go-libp2p-peerstore v0.3.0/go.mod h1:fNX9WlOENMvdx/YD7YO/5Hkrn8+lQIk5A39BHa1HIrM= github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= @@ -1333,6 +1409,7 @@ github.com/libp2p/go-libp2p-pubsub v0.3.2-0.20200527132641-c0712c6e92cf/go.mod h github.com/libp2p/go-libp2p-pubsub v0.3.2/go.mod h1:Uss7/Cfz872KggNb+doCVPHeCDmXB7z500m/R8DaAUk= github.com/libp2p/go-libp2p-pubsub v0.5.4 h1:rHl9/Xok4zX3zgi0pg0XnUj9Xj2OeXO8oTu85q2+YA8= github.com/libp2p/go-libp2p-pubsub v0.5.4/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= +github.com/libp2p/go-libp2p-pubsub v0.5.6/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6 h1:2lH7rMlvDPSvXeOR+g7FE6aqiEwxtpxWKQL8uigk5fQ= github.com/libp2p/go-libp2p-pubsub-tracer v0.0.0-20200626141350-e730b32bf1e6/go.mod h1:8ZodgKS4qRLayfw9FDKDd9DX4C16/GMofDxSldG8QPI= github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU= @@ -1507,6 +1584,7 @@ github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i github.com/lufia/iostat v1.1.0/go.mod h1:rEPNA0xXgjHQjuI5Cy05sLlS2oRcSlWHRLrvh/AQ+Pg= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magefile/mage v1.9.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -1542,6 +1620,7 @@ github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -1553,6 +1632,7 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -1590,6 +1670,8 @@ github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4S github.com/mileusna/useragent v0.0.0-20190129205925-3e331f0949a5/go.mod h1:JWhYAp2EXqUtsxTKdeGlY8Wp44M7VxThC9FEoNGi2IE= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= +github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= @@ -1598,6 +1680,7 @@ github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -1608,10 +1691,12 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.2.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= @@ -1622,6 +1707,7 @@ github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjW github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= +github.com/multiformats/go-base32 v0.0.4/go.mod h1:jNLFzjPZtp3aIARHbJRZIaPuspdH0J6q39uUM5pnABM= github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= @@ -1637,6 +1723,7 @@ github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWz github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= github.com/multiformats/go-multiaddr v0.4.0 h1:hL/K4ZJhJ5PTw3nwylq9lGU5yArzcAroZmex1ghSEkQ= github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc= +github.com/multiformats/go-multiaddr v0.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.3/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= @@ -1673,6 +1760,7 @@ github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUj github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multihash v0.0.15 h1:hWOPdrNqDjwHDx82vsYGSDZNyktOJJ2dzZJzFkOV1jM= github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= +github.com/multiformats/go-multihash v0.0.16/go.mod h1:zhfEIgVnB/rPMfxgFw15ZmGoNaKyNUIE4IWHG/kC+Ag= github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.0.4/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= @@ -1692,10 +1780,16 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q= +github.com/nats-io/jwt/v2 v2.0.3/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY= github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats-server/v2 v2.5.0/go.mod h1:Kj86UtrXAL6LwYRA6H4RqzkHhK0Vcv2ZnKD5WbQ1t3g= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nats.go v1.12.1/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= +github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= @@ -1705,6 +1799,7 @@ github.com/nikkolasg/hexjson v0.0.0-20181101101858-78e39397e00c h1:5bFTChQxSKNwy github.com/nikkolasg/hexjson v0.0.0-20181101101858-78e39397e00c/go.mod h1:7qN3Y0BvzRUf4LofcoJplQL10lsFDb4PYlePTVwrP28= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229 h1:E2B8qYyeSgv5MXpmzZXRNp8IAQ4vjxIjhpAf5hv/tAg= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= +github.com/nkovacs/streamquote v1.0.0/go.mod h1:BN+NaZ2CmdKqUuTUXUEm9j95B2TRbpOWpxbJYzzgUsc= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -1758,6 +1853,7 @@ github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTm github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1766,6 +1862,7 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM= github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk= github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -1789,6 +1886,7 @@ github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a/go.mod h1:uIp+gprXx github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e h1:ZOcivgkkFRnjfoTcGsDq3UQYiBmekwLA+qg0OjyB/ls= github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/alertmanager v0.20.0/go.mod h1:9g2i48FAyZW6BtbsnvHtMHQXl2aVtrORKwKVCQ+nbrg= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -1825,6 +1923,7 @@ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB8 github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.30.0 h1:JEkYlQnpzrzQFxi6gnukFPdQ+ac82oRhzMcIduJu/Ug= github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/node_exporter v1.0.0-rc.0.0.20200428091818-01054558c289/go.mod h1:FGbBv5OPKjch+jNUJmEQpMZytIdyW0NdBtWFcfSKusc= @@ -1845,6 +1944,7 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/prometheus v0.0.0-20200609090129-a6600f564e3c/go.mod h1:S5n0C6tSgdnwWshBUceRx5G1OsjLv/EeZ9t3wIfEtsY= +github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= github.com/raulk/clock v1.1.0 h1:dpb29+UKMbLqiU/jqIJptgLR1nn23HLgMY0sTCDza5Y= github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0= github.com/raulk/go-watchdog v1.0.1 h1:qgm3DIJAeb+2byneLrQJ7kvmDLGxN2vy3apXyGaDKN4= @@ -1957,7 +2057,9 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -1993,6 +2095,7 @@ github.com/uber/athenadriver v1.1.4/go.mod h1:tQjho4NzXw55LGfSZEcETuYydpY1vtmixU github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.23.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.23.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.28.0+incompatible h1:G4QSBfvPKvg5ZM2j9MrJFdfI5iSljY/WnJqOGFao6HI= github.com/uber/jaeger-client-go v2.28.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v1.5.1-0.20181102163054-1fc5c315e03c/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= @@ -2045,6 +2148,7 @@ github.com/whyrusleeping/cbor-gen v0.0.0-20200812213548-958ddffe352c/go.mod h1:f github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210219115102-f37d292932f2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8 h1:TEv7MId88TyIqIUL4hbf9otOookIolMxlEbN0ro671Y= github.com/whyrusleeping/cbor-gen v0.0.0-20210713220151-be142a5ae1a8/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= @@ -2103,6 +2207,10 @@ go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= @@ -2140,6 +2248,7 @@ go.uber.org/fx v1.9.0/go.mod h1:mFdUyAUuJ3w4jAckiKSKbldsxy1ojpAMJ+dVZg5Y0Aw= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= @@ -2155,9 +2264,11 @@ go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= go4.org v0.0.0-20200411211856-f5505b9728dd h1:BNJlw5kRTzdmyfh5U8F93HA2OwkP7ZGwA51eJ/0wKOU= go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg= @@ -2187,6 +2298,7 @@ golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -2195,6 +2307,7 @@ golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200422194213-44a606286825/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -2206,12 +2319,15 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e h1:VvfwVmMH40bpMeizC9/K7ipM5Qjucuu16RWfneFPyhQ= golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20181106170214-d68db9428509/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2247,6 +2363,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= @@ -2329,8 +2446,10 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -2367,6 +2486,7 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2399,6 +2519,7 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2454,6 +2575,8 @@ golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2465,6 +2588,7 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M= @@ -2486,6 +2610,7 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2518,6 +2643,7 @@ golang.org/x/tools v0.0.0-20190813034749-528a2984e271/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -2566,6 +2692,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1-0.20210225150353-54dc8c5edb56/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2651,6 +2778,8 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= @@ -2678,6 +2807,7 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -2774,6 +2904,7 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/structured-merge-diff/v2 v2.0.1/go.mod h1:Wb7vfKAodbKgf6tn1Kl0VvGj7mRH6DGaRcixXEJXTsE= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= From 07f1be0ff6634d9329f1736e5a8162fd18e51a4b Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Tue, 16 Nov 2021 19:09:10 -0500 Subject: [PATCH 02/12] Plug in the FFI call --- extern/filecoin-ffi | 2 +- extern/sector-storage/ffiwrapper/verifier_cgo.go | 4 ++-- go.mod | 2 +- go.sum | 7 +++---- itests/ccupgrade_test.go | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 791238933..e8857b32c 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 7912389334e347bbb2eac0520c836830875c39de +Subproject commit e8857b32c348d92258d1452f1e8738ff03d72c6d diff --git a/extern/sector-storage/ffiwrapper/verifier_cgo.go b/extern/sector-storage/ffiwrapper/verifier_cgo.go index 37256b26f..5d537870d 100644 --- a/extern/sector-storage/ffiwrapper/verifier_cgo.go +++ b/extern/sector-storage/ffiwrapper/verifier_cgo.go @@ -123,8 +123,8 @@ func (proofVerifier) VerifyAggregateSeals(aggregate proof5.AggregateSealVerifyPr } func (proofVerifier) VerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) (bool, error) { - //TODO: do the thing - return false, nil + v := ffi.FunctionsSectorUpdate{} + return v.VerifyUpdateProof(update.UpdateProof, update.Proof, update.OldSealedSectorCID, update.NewSealedSectorCID, update.NewUnsealedSectorCID) } func (proofVerifier) VerifyWinningPoSt(ctx context.Context, info proof5.WinningPoStVerifyInfo) (bool, error) { diff --git a/go.mod b/go.mod index fd898ab5f..1202fd200 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/filecoin-project/specs-actors/v4 v4.0.1 github.com/filecoin-project/specs-actors/v5 v5.0.4 github.com/filecoin-project/specs-actors/v6 v6.0.1 - github.com/filecoin-project/specs-actors/v7 v7.0.0-20211110223913-e2abd33b42d4 + github.com/filecoin-project/specs-actors/v7 v7.0.0-20211116235548-301b685341ad 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.1 diff --git a/go.sum b/go.sum index c9f2d33cb..7747074b9 100644 --- a/go.sum +++ b/go.sum @@ -363,6 +363,7 @@ github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc/go github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.1-0.20210506134452-99b279731c48/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.1-0.20210810190654-139e0e79e69e/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= +github.com/filecoin-project/go-state-types v0.1.1-0.20211102152656-6027e22b77fd/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.1 h1:LR260vya4p++atgf256W6yV3Lxl5mKrBFcEZePWQrdg= github.com/filecoin-project/go-state-types v0.1.1/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= @@ -394,10 +395,8 @@ github.com/filecoin-project/specs-actors/v5 v5.0.4/go.mod h1:5BAKRAMsOOlD8+qCw4U github.com/filecoin-project/specs-actors/v6 v6.0.0/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= github.com/filecoin-project/specs-actors/v6 v6.0.1 h1:laxvHNsvrq83Y9n+W7znVCePi3oLyRf0Rkl4jFO8Wew= github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= -github.com/filecoin-project/specs-actors/v7 v7.0.0-20211109185520-8807da1012c5 h1:8SCNu2TkLCfsS8BpRfeOVt5e4pw2Ej3GInDlFEWqKHo= -github.com/filecoin-project/specs-actors/v7 v7.0.0-20211109185520-8807da1012c5/go.mod h1:F3/N4dIRgwEcSk7xp3RizaVyBE/Jlzhv9Le1/ZH50ZA= -github.com/filecoin-project/specs-actors/v7 v7.0.0-20211110223913-e2abd33b42d4 h1:5sswsw6rhw/JFG5+xU4En5na4K5QPf3jZ33zvAzGrY8= -github.com/filecoin-project/specs-actors/v7 v7.0.0-20211110223913-e2abd33b42d4/go.mod h1:F3/N4dIRgwEcSk7xp3RizaVyBE/Jlzhv9Le1/ZH50ZA= +github.com/filecoin-project/specs-actors/v7 v7.0.0-20211116235548-301b685341ad h1:uUl9I4MCOAkbrY/JI3y6Php3t5c3tu1nux5VkCBwO4E= +github.com/filecoin-project/specs-actors/v7 v7.0.0-20211116235548-301b685341ad/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 h1:Ur/l2+6qN+lQiqjozWWc5p9UDaAMDZKTlDS98oRnlIw= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= diff --git a/itests/ccupgrade_test.go b/itests/ccupgrade_test.go index c5b380835..12bc1fc86 100644 --- a/itests/ccupgrade_test.go +++ b/itests/ccupgrade_test.go @@ -32,7 +32,7 @@ func runTestCCUpgrade(t *testing.T, upgradeHeight abi.ChainEpoch) { ctx := context.Background() blockTime := 5 * time.Millisecond - client, miner, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.LatestActorsAt(upgradeHeight)) + client, miner, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.TurboUpgradeAt(upgradeHeight)) ens.InterconnectAll().BeginMining(blockTime) maddr, err := miner.ActorAddress(ctx) From 8665e32221cd1e73435d8a62f9718a655590ea4c Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Wed, 17 Nov 2021 12:41:42 -0500 Subject: [PATCH 03/12] Update deps --- chain/consensus/filcns/upgrades.go | 12 +++++------- extern/filecoin-ffi | 2 +- extern/sector-storage/ffiwrapper/verifier_cgo.go | 3 +-- extern/sector-storage/mock/mock.go | 3 +-- go.mod | 2 +- go.sum | 6 ++---- itests/ccupgrade_test.go | 1 + itests/wdpost_test.go | 2 +- 8 files changed, 13 insertions(+), 18 deletions(-) diff --git a/chain/consensus/filcns/upgrades.go b/chain/consensus/filcns/upgrades.go index 43f50311f..a8e85d78f 100644 --- a/chain/consensus/filcns/upgrades.go +++ b/chain/consensus/filcns/upgrades.go @@ -6,6 +6,7 @@ import ( "time" "github.com/filecoin-project/specs-actors/v6/actors/migration/nv14" + "github.com/filecoin-project/specs-actors/v7/actors/migration/nv15" "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" @@ -1220,7 +1221,7 @@ func UpgradeActorsV7(ctx context.Context, sm *stmgr.StateManager, cache stmgr.Mi workerCount = 1 } - config := nv14.Config{ + config := nv15.Config{ MaxWorkers: uint(workerCount), JobQueueSize: 1000, ResultQueueSize: 100, @@ -1244,8 +1245,7 @@ func PreUpgradeActorsV7(ctx context.Context, sm *stmgr.StateManager, cache stmgr workerCount /= 2 } - //TODO: nv15 - config := nv14.Config{MaxWorkers: uint(workerCount)} + config := nv15.Config{MaxWorkers: uint(workerCount)} _, err := upgradeActorsV7Common(ctx, sm, cache, root, epoch, ts, config) return err } @@ -1253,8 +1253,7 @@ func PreUpgradeActorsV7(ctx context.Context, sm *stmgr.StateManager, cache stmgr func upgradeActorsV7Common( ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet, - //TODO: nv15 - config nv14.Config, + config nv15.Config, ) (cid.Cid, error) { buf := blockstore.NewTieredBstore(sm.ChainStore().StateBlockstore(), blockstore.NewMemorySync()) store := store.ActorStore(ctx, buf) @@ -1273,8 +1272,7 @@ func upgradeActorsV7Common( } // Perform the migration - //TODO: nv15 - newHamtRoot, err := nv14.MigrateStateTree(ctx, store, stateRoot.Actors, epoch, config, migrationLogger{}, cache) + newHamtRoot, err := nv15.MigrateStateTree(ctx, store, stateRoot.Actors, epoch, config, migrationLogger{}, cache) if err != nil { return cid.Undef, xerrors.Errorf("upgrading to actors v7: %w", err) } diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index e8857b32c..fe2a31757 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit e8857b32c348d92258d1452f1e8738ff03d72c6d +Subproject commit fe2a317571931b31fb1ca6dd2adf1414e375b902 diff --git a/extern/sector-storage/ffiwrapper/verifier_cgo.go b/extern/sector-storage/ffiwrapper/verifier_cgo.go index 5d537870d..94e04f26a 100644 --- a/extern/sector-storage/ffiwrapper/verifier_cgo.go +++ b/extern/sector-storage/ffiwrapper/verifier_cgo.go @@ -123,8 +123,7 @@ func (proofVerifier) VerifyAggregateSeals(aggregate proof5.AggregateSealVerifyPr } func (proofVerifier) VerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) (bool, error) { - v := ffi.FunctionsSectorUpdate{} - return v.VerifyUpdateProof(update.UpdateProof, update.Proof, update.OldSealedSectorCID, update.NewSealedSectorCID, update.NewUnsealedSectorCID) + return ffi.SectorUpdate.VerifyUpdateProof(update) } func (proofVerifier) VerifyWinningPoSt(ctx context.Context, info proof5.WinningPoStVerifyInfo) (bool, error) { diff --git a/extern/sector-storage/mock/mock.go b/extern/sector-storage/mock/mock.go index 8fb356d0b..64568dc2d 100644 --- a/extern/sector-storage/mock/mock.go +++ b/extern/sector-storage/mock/mock.go @@ -549,9 +549,8 @@ func (m mockVerifProver) VerifyAggregateSeals(aggregate proof5.AggregateSealVeri return ok, nil } -// TODO: do the thing func (m mockVerifProver) VerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) (bool, error) { - return false, nil + return true, nil } func (m mockVerifProver) AggregateSealProofs(aggregateInfo proof5.AggregateSealVerifyProofAndInfos, proofs [][]byte) ([]byte, error) { diff --git a/go.mod b/go.mod index 1202fd200..e0dc40583 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/filecoin-project/specs-actors/v4 v4.0.1 github.com/filecoin-project/specs-actors/v5 v5.0.4 github.com/filecoin-project/specs-actors/v6 v6.0.1 - github.com/filecoin-project/specs-actors/v7 v7.0.0-20211116235548-301b685341ad + github.com/filecoin-project/specs-actors/v7 v7.0.0-20211117170924-fd07a4c7dff9 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.1 diff --git a/go.sum b/go.sum index 7747074b9..b91544f8d 100644 --- a/go.sum +++ b/go.sum @@ -363,7 +363,6 @@ github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc/go github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.1-0.20210506134452-99b279731c48/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.1-0.20210810190654-139e0e79e69e/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= -github.com/filecoin-project/go-state-types v0.1.1-0.20211102152656-6027e22b77fd/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.1 h1:LR260vya4p++atgf256W6yV3Lxl5mKrBFcEZePWQrdg= github.com/filecoin-project/go-state-types v0.1.1/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= @@ -389,14 +388,13 @@ github.com/filecoin-project/specs-actors/v3 v3.1.1/go.mod h1:mpynccOLlIRy0QnR008 github.com/filecoin-project/specs-actors/v4 v4.0.0/go.mod h1:TkHXf/l7Wyw4ZejyXIPS2rK8bBO0rdwhTZyQQgaglng= github.com/filecoin-project/specs-actors/v4 v4.0.1 h1:AiWrtvJZ63MHGe6rn7tPu4nSUY8bA1KDNszqJaD5+Fg= github.com/filecoin-project/specs-actors/v4 v4.0.1/go.mod h1:TkHXf/l7Wyw4ZejyXIPS2rK8bBO0rdwhTZyQQgaglng= -github.com/filecoin-project/specs-actors/v5 v5.0.0-20210512015452-4fe3889fff57/go.mod h1:283yBMMUSDB2abcjP/hhrwTkhb9h3sfM6KGrep/ZlBI= github.com/filecoin-project/specs-actors/v5 v5.0.4 h1:OY7BdxJWlUfUFXWV/kpNBYGXNPasDIedf42T3sGx08s= github.com/filecoin-project/specs-actors/v5 v5.0.4/go.mod h1:5BAKRAMsOOlD8+qCw4UvT/lTLInCJ3JwOWZbX8Ipwq4= github.com/filecoin-project/specs-actors/v6 v6.0.0/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= github.com/filecoin-project/specs-actors/v6 v6.0.1 h1:laxvHNsvrq83Y9n+W7znVCePi3oLyRf0Rkl4jFO8Wew= github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= -github.com/filecoin-project/specs-actors/v7 v7.0.0-20211116235548-301b685341ad h1:uUl9I4MCOAkbrY/JI3y6Php3t5c3tu1nux5VkCBwO4E= -github.com/filecoin-project/specs-actors/v7 v7.0.0-20211116235548-301b685341ad/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= +github.com/filecoin-project/specs-actors/v7 v7.0.0-20211117170924-fd07a4c7dff9 h1:H10WnEAJQH3JwHyaHwMEgaaj00z+/QMCb9Sjd/SUW1w= +github.com/filecoin-project/specs-actors/v7 v7.0.0-20211117170924-fd07a4c7dff9/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 h1:Ur/l2+6qN+lQiqjozWWc5p9UDaAMDZKTlDS98oRnlIw= github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= diff --git a/itests/ccupgrade_test.go b/itests/ccupgrade_test.go index 12bc1fc86..b5ca41416 100644 --- a/itests/ccupgrade_test.go +++ b/itests/ccupgrade_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" ) +// TODO: This needs to be repurposed into a SnapDeals test suite func TestCCUpgrade(t *testing.T) { kit.QuietMiningLogs() diff --git a/itests/wdpost_test.go b/itests/wdpost_test.go index d87059bb4..b1420e6a3 100644 --- a/itests/wdpost_test.go +++ b/itests/wdpost_test.go @@ -23,7 +23,7 @@ import ( ) func TestWindowedPost(t *testing.T) { - kit.Expensive(t) + //kit.Expensive(t) kit.QuietMiningLogs() From 91fb1114624e56f5d4fd86e29998ae509c0a1ff1 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Wed, 17 Nov 2021 17:50:36 -0500 Subject: [PATCH 04/12] Update FFI --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index fe2a31757..58c014a42 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit fe2a317571931b31fb1ca6dd2adf1414e375b902 +Subproject commit 58c014a42b7a21e73560879841a71e679126a852 From a5847fd06f34325d240fda97f4c758a94957873e Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Wed, 17 Nov 2021 20:33:18 -0500 Subject: [PATCH 05/12] Update actors --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index e0dc40583..ce52b7975 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/filecoin-project/specs-actors/v4 v4.0.1 github.com/filecoin-project/specs-actors/v5 v5.0.4 github.com/filecoin-project/specs-actors/v6 v6.0.1 - github.com/filecoin-project/specs-actors/v7 v7.0.0-20211117170924-fd07a4c7dff9 + github.com/filecoin-project/specs-actors/v7 v7.0.0-20211118013026-3dce48197cec 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.1 diff --git a/go.sum b/go.sum index b91544f8d..06341ce01 100644 --- a/go.sum +++ b/go.sum @@ -393,8 +393,9 @@ github.com/filecoin-project/specs-actors/v5 v5.0.4/go.mod h1:5BAKRAMsOOlD8+qCw4U github.com/filecoin-project/specs-actors/v6 v6.0.0/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= github.com/filecoin-project/specs-actors/v6 v6.0.1 h1:laxvHNsvrq83Y9n+W7znVCePi3oLyRf0Rkl4jFO8Wew= github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVivoICZh3wtwPxDVuds+fbfQtk= -github.com/filecoin-project/specs-actors/v7 v7.0.0-20211117170924-fd07a4c7dff9 h1:H10WnEAJQH3JwHyaHwMEgaaj00z+/QMCb9Sjd/SUW1w= github.com/filecoin-project/specs-actors/v7 v7.0.0-20211117170924-fd07a4c7dff9/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= +github.com/filecoin-project/specs-actors/v7 v7.0.0-20211118013026-3dce48197cec h1:KV9vE+Sl2Y3qKsrpba4HcE7wHwK7v6O5U/S0xHbje6A= +github.com/filecoin-project/specs-actors/v7 v7.0.0-20211118013026-3dce48197cec/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= 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= From 5f1783c9a5965f1820e568a66da6200e9cbadc17 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Thu, 18 Nov 2021 18:35:06 -0500 Subject: [PATCH 06/12] Address review --- build/openrpc/full.json.gz | Bin 25453 -> 25465 bytes chain/actors/builtin/miner/actor.go.template | 1 + chain/actors/builtin/miner/miner.go | 1 + chain/actors/builtin/miner/state.go.template | 23 ++++++++++++++----- chain/actors/builtin/miner/v0.go | 18 ++++++++++++--- chain/actors/builtin/miner/v2.go | 6 ++--- chain/actors/builtin/miner/v3.go | 6 ++--- chain/actors/builtin/miner/v4.go | 6 ++--- chain/actors/builtin/miner/v5.go | 6 ++--- chain/actors/builtin/miner/v6.go | 8 +++---- chain/actors/builtin/miner/v7.go | 15 ++++++------ chain/vm/runtime.go | 9 ++++++++ documentation/en/api-v0-methods.md | 3 ++- documentation/en/api-v1-unstable-methods.md | 3 ++- itests/wdpost_test.go | 2 +- 15 files changed, 72 insertions(+), 35 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 8f71ee8a973b9f29d91d16893c3cbe8bf3db8356..8719b71713e8587d8e7ec8ea03f23b0d6486fd6c 100644 GIT binary patch delta 24728 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 D;PdR} delta 24759 zcmV);K!(5h#sTfd0gxO4c*``>#Ua}V|QduNn~3|yQafrInYUcYyX0){D(HFkzugO@J4?fvNYW{6Lz%X<4? zzxN27iK-{qLk`7c>kvVQlJ|(eBRp92`aKshC%`^e4gLA&pA&jb#vyUQe=`PNoP?hD ziMr^L2cg5CgKYI@{x)zZ;pmQU9jSl&z~2FIgtv~S5R-R4b*9h3vlo2fBc?l-Rr>%1 z0S%sm@7Ls-<1t`cr-Y+`Krcrl_}9Mx!JaC3%>%^4fQTo3@Gb~GQGOZvJ`Ff>MS&mU z|8$wkCZGA+g3jmH^1qs|Qo3CA9Y zt6!55a_9^(0B<4o;K)PQq}T8HFn}}lWx_yw<!+wAq$iPF8BP(g6gquAF&t}m7s=mcHEV#)SI_Ue4I`&o4bU6=uLD0OS{pU@XTlrYZxmy`= z5sPDVhQJ6if9wDudV(1glL_F6hFtN#xLzavQ?`H0hh6xLmBmc+r3^k$` zj25zNNL&ei*-Chgv(91wep7h6nb8X*p?4dVm_A7p7+4l_U>-Y+CD}e;^_0} zuXd|Cu3m+J9qeu$VRzZuj@#*ERi~+{#<#hSUHO-Qr!E2k8lwOaCs~mS-5#ADcZN9i z)GUXZe{wzv2d6F~9FK7c>^#CQ2*m1Rh;V^D8S=(2Rhg04MUHL*x^93NLoUE^Yg^!y z3&bimvl=i2e<+oz4e-=YH+~cDmyFoMmFM9X4A1>(3|7$cG zqs4f*JI2Fsu@{DDcW}Ea;b*i}HBf91rJo#Uc=f7=GrUJ!^7?j+A*#KUFT^UbDE$FJ z7X?c(Wz={l8gZW7B@83(JEITFC(K8V*ic2D(M)PtrtyH7MsfL8>ff0nCb<10CMf9b zfA_}QJA>hFuiv}E&JB{i|8a409#A?i)yez4cOG&?@4C$Q-WN=cXh?W(|80L+<-|}R z6#&8L`l5kzddYP?_3Ru5V&!CienEIL<-PshcCX+2pnpiSM^xfcK)?%19Xe z5o2(IE|7z;&slfP>xMgQ@$l^OU@{5Ne*|(QTD_9%vChyUzWxj`4rjhH$;kC|i6^Gj zPiP>D6X;1xi)cbk+aYA=1R?p!8rpO6!?-U~kQ#3TOHi!27MAz-9_DDq?vwiFhO89% z`T-0AxRAq1ErW+J{RP(4farvAwIn=YgYAgV?V;t3BrMRRY?{y13i86hw5V7zlRE|* zf0#(A*{tO`NrEo!Z%dYKvXq=N*)&;X(vF>H8d%21Ym#^)A7B?LMv)Rz_HH|?*q(#e__DGH^>wEE#&f`Hk z`-K7MF$#Rj7#?{@9vBy!2b_W_yhYc<#barGBpmt639JQ#-(hFuhhe~&0A zM|a2x#j=z$`1$JHKDhdDdI>(hyZZ3?7+ik%{QKE4`26YY-{9~a`2F(TF*x~r0p7p6 zx;p*z9(;Uvd3o^u-6c5v1P;LE`MaajlhY$`c=q||H__tpXYlFsm8h3#_Uf}}Azl0E z?Dyk$$EumD)AP%BSJ&ishT^S|f050s50rqBqtb?Z;LspIPBJAfioTp2o;6uKQjH6hfYWl3@3j3ErV_B}y z>DD?`h3O?38^}oir<<*y#&H(<8%BgGIee*#deQs!M}Z5 zzu+Sg*ml9|`o>4;y1dEif7eAjUHu8U%S{+j{{e!o#5nQqy#GyNzc@NQj_m>0M0%B_ z{K@Q5`{UJHGt0Y*mnE-Fm{|-)b_WUsC5P<_gC@T<7!w6G@{vc}337a!L7>sg7%0jI z5&GLn5L@xEw%dyBIiD`rM039paN71Llnm!(<>BB-a3(=PG>fO3K%rUo#y>wUO)loAhygF-`(>2XG zchpra=PvDI9tA$08lNd2kLir~co01p(;#8$CEQ#^NXc_^a5Y7f>k1ivEGtqX&MCvI za9SaDa zFT1}cK>f#Q{3rO|Ya$O&0pJG*;_?4RkNM$&EPQZyO~C)YeEIUl%a{MFE9!sw#f5J9 z3k^M24+H%9RgwRUA09mK138Fi{NOP4_rddTe_8|Ynhm_kp7jTRcG6Z8jtNUB6N#C( z>lK8t`&nM+`2%`Qj{%>6@Y-7v*P_B1%2a%*>gES~jeXKo$xf};G0n@h8Qpu@DNRe7 ziU1e!Si4gdETd}d7Gpj9*2hp@@0l=^gE2>eo}txvOR6Qa(6SXUxh3aGb-xBClpUNI zU@p?-QF_C`2s$?p67Xs=0=kPI7tCecm7$k@^y8+-^sX)WNieEgyC z@i$8@p{vp7s|CvaSVI;^Z~5yLEXic3k2QPa#B||@$eZf`0`U&-Cpe}tZ1nD@oPfq z5}6s1pst%@-*aWScV>3qRBnoElE_gh9b#{PA2c<8y`-RJ% zZRy)ohO}GfGJc78dx@(n8y~#Yr<~BOb&_x*p==2QiaH(Bz(M2C^A><1&SDv?kh+k> zTi|!5UHTj-v`(-u^GitU|nB3&KiQapO z|Ix8W&M*;5@9v=C4M<(j#5r1Z_T++pL=5)ooSqe2`m(~wV7di!?=kh{5Km6Yaw(YZ zqDB;^+iWfmbK_V7c{3zAbmoU*pU>6rD0gt8ZMTVgX0dKJSU0^aDkd_1X`t$E_nwp` z?sb*dsfQ8aN6>SQ=xlc0oOfjFFAtO;i(M=+J!c#3#sFO)w1ze0`gfq`gr0Q= zhsr-7;SJ)$bjBDqBhEtft%}C+)El#0-CgF>QV3vYd$8LOWwguR@>BuGn<~Fjy*r45 zykp4WRR9SammqXg-jQ#piix<8L$1qgMTJj~rB3c66l}@AhhRjhS7%_W=yqjeTlH`v z)m)HQ&vFVxIr5RvJ;d-qH2&m&KCC)dkDs3&OC>~JxstQe8BeO1{NWyFNVvi9KPYm$$v7Qh zqIA2dXs8lq=ranaoT9g39?)dyPfnQ}4y!!DV(wMC;LMq~sBXr%&AGNHxrAe{z^*mL z%UE?xNQzSjC_+aum$nS~F*D>!ZrmL!z8A*%RN3EdRfJ->#ZNGQab*UmcI+>zZsNQ0 zBJCOb-ysSXpT}bqEa!(&C$%23NrNqTVrm#mTv@UN#Tp_PGWlpx@1gV}TIiSj6TX{{OX#S{NDI^a)-&d14qDse&1yj*i!z91-#M)VPr z^8h<7GLwA71O+XBtDPf*s@VY?s72DeL#>pQ>K!dKma^o4=WsDYgiFqStHL{(cJ^mP1!&g;q_EK`cN8|{$JuXz0tDuhP=>m-< z)QNl!mKe!ZgWcH0W8zEzjP7`X2nsY$KRURONTtN}NIdR;4w&e9GS(dUG~OrL(V*Wu zWk&}WYHc>u9dyl@S4D?Zl2?eX3S6wUK2V1NHp0o`$(i!^s$BT>rjQ1YQ!=Kl8ARNI zK~l=7=yC-p)ozClNm*)_*@DtEq;JVes}Kj62oNa)vuc0-=-R!Dpl8*ZN1@h~dTLef zne-bYRv%D*pEBrmnic1gL#`df<2(p?X(G*>JWA#s{U!LFkO~34#jZfoNybZ|`wJ1a z|GgJEqg&VrxE zvF_j9`N-kOO~8oV9Nlh?%*-xbV|5&P1*euQ{A{|2a_UCYz9X%mX}9JwUaKxm_(=vM zH?fKtGK(^~oHBeTh}wuvB}l(0#vj`${OhVKv}xmt7C9>!pHv%F=BE%7zPI}vJX7C) z#n|+uS}iv|UH7hgt*uWnxrX*9O-MS5M98$I2?B?@-FYLaxmuf7_U@odx9r%U{FCj> zo4Wtr)LugU0NELJT3@G#s&^1OHPc>K;ZyTOF57Ey|B2ypK1K3cSK`)kbb2fnwsLf4j zTy<+3zKFeKth8a)Wd)sOvg?7rrL4W<0E~Hi0_m$3s^+*G}+((SbsP@2|df=Lk)38kXrmJm~}EHi^H zisHUYJs&u-mDLjg>rC);oCzM8 zD)g%MmcM}g%38XLGNfCmQis%QGi69ORjUrEGA)&%gw|#1P(+HSGDFT(C+Yw~9@6nC z!T|^<<>2V_n0280RGbW@UaVQ~Ik>1ebLdyzVHPW@veIv8u})Rvl7@jPQ>$b=-i^Ii zd!JP-;5e$`DtkL=q-uM|CCp78Nu#wJJ=1c_{hpzJ*^|H)7DvsN`2|Pp9AfuGOXZ~- zTGqHg4#Kyl>W8%gJYa3eDmqWo3Sde`t#+p3cD0XSxRPckI8`gfF4oP;Hn;irq#SyJ zwKk{WVUryfF+wSHTXB%484vOVMo(*$u|$!O-ooCRjDstivEazQc zkts0y^`ExvdRu!__yW!7En4YnU%H7Z8K!T_Z5d=*OE=d|DA^o=%P#k22ngg4eZ^0W zqBF6ROv?IFrES|>Y3=vUtL@sntrvnPe+9gQ#H}SQ-Am@yl773|a%BTDwPco&1vy7E zpEJNI2-JI<$kirtwTWEsg%R%5CUVtI9c^=tMb)cVUhFgSIdD;+a___u1D0|))pl2G zEvD2&y^TA^>LgMphD@@u(lLNhJ{^|QZ!wVtsTgl}YHoHOf6DFnj5$~E_ZfAOe|HY~ z^b&cmIu@w+K1IAEf|O& zhQ&A{zOnmE`6nv#r_6kea^ti$FDmlfPdOCJlfy!T+9*kp%)bg2 zT8%j+EF6!qBQx!V#BJ-=Y|yfye@l!pYO3j~TR>GmrsWo!<>Z#>kBmdlLvGqNnvyut zhp!keaFmoM5z8Kf9 z+RQKF66bOaJqOQT#Qtr|&ivxK9Ul6nDPFc!lm2~q#ZY?4$n?w7cmumWf7;7WmZ6B2 zDP$i&I+QPhfz>M|@&;(`985ODvbjwn&)_5Kd61(ZR-W`F=z#0Hr25e71g0*Y#JM^2 z$%|b7ZLmx<@ir1gvq%)VZ)8GTdSNt0;JJ@qddH-=%+`7aSzNtM+sH27vN1*5?S6EQ z(&O~R9n$(qcI79zsX$||fA$izyaMkb##RFxNgL||97zw|f{qO32EZdl#~26bB_!_4 zF%2e&zf8ag0dzd}Fi|n11isgpL;@5Va=^k7Lw|>IVFu8-!DM3bip47yuUNcd@ruPO zPZ+Pfu8Qp-Z*U(%=O*-<1C>HB~e_()67lDy_MoU7* zOGh&?fm`5eimu5F@hKInTP_L)_!M#-xPgZZxDd@K5z99S2@y*@a)P-gXP>Wrzx=<$ zgQMSmKmWhOgUfgScYbj70U&aV14^WA^A-jejywby;sWb1IzuvQeP4%)f&7|?-ee^E zgv$985#T`26Fp|ee~Fo-K%ZcbAX9Za14uU0_|MqcZz`_$zK84`<9G%+Izi|NHs9Wb z7Amz6F`aBnU&xnUATptm^mbG4uCRZJ_-|Vcy$+D}U&P6u&$V&Wi zq{O3<@1n_VFvPnKWoXW)3pROmcXQ|eJtl+s*!gE~b~~8P=nbEb+`Aiix667>T`kn8 zn_{`txLZ`!fAeR8SJM;P*cU_3y-7d%W1D$4sPFi_H$yI#OKgM*3>NQ*LtVkC#Ybdl zZ#NZ|B&B}P7SLI(zZQs_8EOV=aWq(O2Di5zIF}Z^G;^%kh^=&VA-!K<0RE6oc|dlD zH?JqdkOav6=k@rG>`wlAH5|G_x;x~5lYu|L{@vX)f4Fs~x2X5y+r1s7rUgvJM8+=- z@Xz*|A}MSrNO@avOEV=$V_vxeOo`fP091&0+G}(>U~+uD9Hkm zkSV=cApV&ewp1VDV03)znw)YlhS*~OkK;n>0jB`nAt&S=h99w5#$p+ZWi}bhSX^L^ z3nJY2e=yMCX2OHL?TU-AS@{+*l+^%&ZlykLby-9QY0ZeNa$I!Z6h=Aw0%R2 z#RObLWG3)pK80Lj3_rjQ0&Ge{&jll-Fvpk%0A7;_PH+mQ@D_n7o=ky$Zx+0c;h+@s__RIJ_>gD&|7fg<5NR%_dl3IrdI+VzxU=~H9(#{X@ z?`$BbR5G#ML0@!6FqxdwORoEo0rs2u3uLMI-oqTtmdBni4<*&={QQE3#OP4JEEjPPkOmNw(BNuE273q#{M2j z9(_v2wA}$is)0u5&Lg~aG=-Q*D`(Z^^N(0)0BC&wtM~FC&cG8xJf^{l!=lPlMW4TP#`{6%EY9~sN@{O-QlaZuZM4jdvAm!Mz@JV zw-5wq?P|B)?oet@dgtK@9(m}0ga&H3t@4~aG6l0_QYvzS#Gkq;0?)3B=J`PiYv4gl zbb3*npw4)sv|CY^G7q#d#udep+aim1M5yBXU9G|tTeznn44VlQUvF1L?)~Uf>K#Jv zOwU7^{J$Yg%v7%eiC@3z(}PPqA;{Ib$aC=Q>o*ez#7rMG4v2AU&0G+F^Fye)f0m_W zB>n<^$fi=2VRCRF6)JCrW}-%Sf$z#E(nzZ6Y&e<)e6@%1_AuTa#y35TPYHvR>Y=1f zdk`J-t&;t|)UC8`i$6k_(}H_w%kQwMa(bsCgl<;!RD~vLCa!fWOQm*QXhA8&%Y>4- zMAsE+1$!xeXfNfHkuSM_sai^CPVR@~J|+Ks$$Trlt@N&l&(xOXKH=DWm8W!_!FxDJY1hLMdp5F-%LdM$!DJpO0KCDD>XKOYWr3YndH%e$TH6W?GtYKV_ z(J*jOhY1y|jIlDt%9w{NW2{}t+Lh{L{je%7t&lHAQ{*HbVy(n~e5Q#S39pNs2b5Fw zF`j+>_Vt^7EL*wckcVuktk3jVE9T3ZZ!YumBU~cxv*h_G5Q~@rk4~@yJ>ZDf3{V1~ zh5}iOIQ;tX+ndagUOXR#B|QUTd}Mge-6DaUle# z*sWS~2H!c@yFWR?e4@CS{o% zlpQ+a|5=6lAOqZrvYm-IF%w2xTCA(o(u-ED%^_gC(%)1?j20jCJ>o}{jBzm(lhJCA ztCy_!RPJYgxy)p_r4TZ1v77t1c_M4}LDI8ohk<7hIMiPNI({y`NF(FJ#R)ps^B^SXh*Hm`bJE-2+m8QBaNXxy6zC+Ab0$Q8-mVERlMR=%vh6mEEFyG? zOpkk(smlnuIgG7P~80m$hLJ6qs) zhSbER-PJK+96`4`Z=nZaT2u?6KzsanJy8jE2dzUAZ07EMvt1QoL@qOhN!x91UAby+ z^FqjwmKRNbbU*iSza$ya5+)Fl6v3GU+baMQVf^m)EVn@|tYf~lBU(G6b(-9KnY&XL ztf76JhPn_96|VQDj`vF(46PY|hJDBTc6XroMH0D4vFqfw=3Anm zW)d<8Qo>~4W|(#KGUloBLBuF`66RJ6a@6nX;4L|SnLYAdG`S6ic-Nr}&G~e}Ca>;p z?)<;UWH28)|Lo0f2h$n7;q#GucLVQsncS-x?qU+!xy$YwUJ104)k;;~4g#_m#bW8e9BdMT zWhJ|CgV-xsdNv^7iWS9H6kAbjMX?pd)_`mc$SY%}-MZ*Dm&g-Ku@zWSbq!tAq}_Pz zQONgp+quZLa`A5Ceo)>y19-#>fBg= zhqg64wAEV1^x`y{tewHuu&pzz^{TVb%|f?_4&5G^SKX_+=sB0G-L|`|xowv@VNNcJ zExT=cS%2NGv9M1FTw*LqI%bHon~39Jua*?+5g@g&$6Trh21X!i8r;5Z&?fcS~NsDtWf2ulGMIM8mAr z#xg{An_k-9OdcD^7b+IYGO18hn|&jlkSbkYDphFsOo z&ErcyWQ6~=D&~-X!j?ynIH;)e7y^7%d(HTM1uU=V>k`VxBQ8VowJ2WG z;>dqC0mCaw+CX><(k)20AbpJ>-NIfAdoAp>u-C%gmazBjc2$r%1;)-5#%YUtb@f$& zZ}HjgDri?z)g|0b2AapawOBWzL_haK*P>X9VmF%F zB6_uW(BeUh2Q417c(5%V+^Gs{DgetWUJlJ&9Aa~40RXnbeO>vpuIZhgqMje zF@kQ9QE{{YJb;8jN6a=jJ?;bp#{K2mmW3jms32&j{u9M)55boA0I-_{P8K*>;ADZ* zV+2lvs@SxN?7zArA7Gn*Ahm@ix`9!ZC&|jY{18u0372l7#X_%>cHe-n-$o0LRzPKX zSY3m&WVWjONySLS5SHS$h{A^Ot)GtR7BT_TMwCx;uuI=LZlgoObD3mU3`bb0{S1l>V@hkFazTbdkEl20+Y zk$=GeZFP${3#aA4#NRbQ4)$^C&T;njt>AECxN;=p*i;$WFdKU3>S^T^IMDMVD{OuU zIr`;fh&u9`r;F;VStMZG|2(zgz zXj5%NH&~t2>ZDeGC$&21W7J89Rq?|ao~+=|+}xXai4L06H_NXo#%;V_LEr4y(Ye;k zInpnyb;}x8=W3O5{r3O0>ReUc)K=xPD%V4ql1m06IXBw{u8RRjZVkSlJkWuir{t(nolI>u3rwdFNASYOckk3$;>U zB-!05FwrbD54fT!apXU709T=L%%SHYZm6fk{^E%Xxl$Z*+J-u-koI#t=QUyMGa5ouJYPP}C4uZKNQ{EoOM^NM zt7%W0z$b$?cW0EF;At>&-Bt9qgsL&{3Fnr5r9-D4OUg4@LQS{0S@GzOD(z{vPo^ zP`f0c>DnvEI(a;>vcjOqSfiQ{kJIe>azavCEr2r`5}EJn?s+$v!l1{@%tI@9b6MBMaaD;=$WbTmB)u#;xhw)+ueZ?~5UGE63y&J?+! z*V^!vYi2byPPC~TG?Zegu4}|us@=BIEIURcMJ`WYTDIM)cfds)Vvi})S5}#`N|)u3 z%Q$3eVHf5x`_ANK?o|0PM5b_cW_Bq+kUF;Bm*>m<-tW>G;#m7a=*JC@weo#6RbSG7 zWSMAKd79Uk(rPp1!C-s4CIz#}gv`2&MsIQ|h^?u=^gJqX4;Jv;dT#YXUtg8o_*jn(1E8 z$WygxZ8EhF{dTks%Wtuy#gZ0FS}fTXOAczn@?XxOze;HSRQ)w)C@s4X+d*jm)Brkz zoY_ffZZ%HRR2nljF`9~^3Zkwty;EhV)8$!A>jSe&tXYyBDxWpV!pe=K*5)kz8P?%V zruG5EJ+&y`qI`?;Ey{n4D1TUglS4wF#1&$8Ce`m3n48IJ`*CY9wK%Hec zzEi)DW??j!!+8tXEnv5R{UHN(3xO>Jwh-7t;KvAocWXk{3xKtX8+5AvI$S0?LcU%5 zK4(X5?mLmDC3c-)bLjg5!4Bg5{@MpP32?AB%v*G3wwU%2V%kln_5olES&I%WI<)A} zqQl3NtT8KpnxX*7AX0>Kus|F@vH%X9%@E;HT&g&C>{dsJ=;!(P)qMQSD-&^cxgd_N zu>ZZMFRuzQb%>^zxZ-cYT@VVAQsNi8qUYhr!)*GIO;~S#XE5yNUL1PVxlylv^m{VY zbkc@;d5(fB>@&pAAmcmR+oJH+uwVA}1QY0CzEDL)el!$Ax!xPptRnP#kq6gOT_|71 z+_LlBfXecjHxe8rAF~~2&Mu`UQ>>So3Ax7CtBVvqHrcRO5k~eLE}ZFs=TSlN8Izkb z9)IGos>EfoB0ev9D90!py4hY=1RPZ>FN!355)!vLA}eXbe8assnnFU5m#x2i17?bM zVtXqehTVqJ9#Q(0ibjd5VkS^d*X`~1bVRtB&lk!JSYnaL+AEGI8RKAv+=Cg{)&?E( zwea8z#QYKwj%8mY^t^uWze5zJ>;6GQXMc)<3xr&RQmr;eZE8eKbj=9`C7Eux#*D37YGlLC(QMTrLARdB0`bZ7C3cBYHjr)W2)iH<)G&Dp z00BeZ_@yc{!epXWPZE6&xd6wlZGlq`usl1MsYntK=!2_1fZ&L_$N|shQ|wHE4pfl@ z%5%iqmp*iEkQ?_R=I*(Uaq&@Zr@(`DC&vYTN=bQ!tL&M<3G8B)JTZG7DUD#Q*M&2e6@Y+=0Vs(7dZ- z$YE=5aC0B^GC#nNm|P+*>zR1;UEvuzqt4Aoc-OE3Zk;owr5q?#a#PH#sN`l}Zjh22 zA6hVVaCKiwZ_=x2^3!g%UUZu1x-B--)7ZDtRn#zzY%oEsKcRU)#((!;%7&vK#5rP;atfF?dJL3_;<~>wWhR0 zDR@#mb&we7$yN)Mw=pVV(+Onl*sx?3{FpsSnE7RAwmBN>Dy=Y+vCDLa>Ni-f8g z^pWYHF$2jA+$Z3#kzs0JK)0^pc9n zp){~!^;osu9b^K5M5YWC+as@?YU(0YTR9hJltZPo4Qe`W$UCiV#oAV^ZRJVYR=Pcl z`3ZSdYeQCTw3l3txDBOzQ&H=ix_j9gM;uL&b93n<;=)l|<5y`@U1QlefBcA2&lJ68 zNh$}j>U*`su78CwTNrC$tc9@_##$I_VXTF*_XlHt3Poj*RfoR&8S(Ho6^Fj93;mD= zQZjz!>KIfuvnu|4t{|on!jv7BqstXwWi$*M%)vrQ3neX-v{2GQ$p;A~OXKv0UJ)kg zhbiY8-JRfP4;usxcItwDL}EWckgsTjlT9=MKiN~^I6kM}bMWj%rp*ia35_jpvQBr- zCi&snn<=HhXmf1h4>D0*sb5dYE+_)h@!(|+%AN&`NIlkGPbe`AeX zHyG3fo6>BueSm;e1Lh9UU%!=~9h-sFrEvsG4TEj5s~(y4mPXQEUtz<`oAq0p`hLbG zW-Gm|^tRIbK}+vP8xdtNtcxQSg@_18GrXDrS52(V{mb;`WQLk`T%gPk*Lr^0<2rj> zXCaM+G#1iqETplXU+eSyvLOU)e+U6%Fuq$6W%H6ljt(402s9n#$)|CmKpiIxz#Q`_CcvZg zW(1uZfW#!_*e92HzPn?cf0+-mHrElUn77W)Yq@D>heLAFl^q8~FV=eiWSmM}s>cT2 zAqGdokIdY>R}pJZvYsPY;{IvGzeUX|uKhx7vX6){I6)O$`^71_rOtA1#<;gmoEX!z z8?a{CZxCvzsyOOQ4NIz95wFIQZ;PQwrc6VXw#XM+9pge%n?f={e{AcTT$7|_==&Z< zs`02n5eV`uBPakL`5-^Ns?46E}-Nkr~XUL{&gV+Fi|)g3N`d4 zCf7u@z15je$bN5Ae>=hFq7yt=!&^Zy=`!F=re zvp2gPOlS0l&qwav4ZPcBjV;6N@>r(E-J+_VKNJ3%p3tT}ncH<6SuCUP*w$#+CXJ?A ze~qg}i~U~Ag%=v0y+o0$lf7wJd_5}E+9P5Q6KhC>5 z%#Wyxdi&e`-h~vq~|)<@LR>Sjwq82MAE6V?+|w+r{@qdbb`>KqDwsae2ap2 zjN=&;YbW(WBGq$5pvM>KM^`wS{0lS=N!0Qc<541n zClHaI%612@pCp4WY1)~X5r^)odsHH#Ah|v2v?W)lTBYQkgd_>!ntyqQ%}$q1j*OY% zyl~TUhFI~|^n=`*Qg~}dqR~0J>eC`~i_BXh^Yr}1f6}OlRVx-;hM!kSFO$NN7;H81 zWdlsaUBUzlo2sm03VJn|nhcC;v2CK6YPt(zY}h0%M;^*G?lwk!O>356%cgBaAhT(` z6drA9Y|ZW;%Zx2E?u;30O}pVPe%ws_vE6@rU6J-f+0~_?-Id;}Esv%%O)N>pEe|)6 zwA?f3e}7dU;+rzL$wrnRZ=`#yIhQVPzWFJ2euO3`AsG_WXViR(0923XQ_7G!s$lxa z1B?)#Bc#qC_?+rP6j=rwogTAma`pN6^FFwo($I4OpJE0$yopXgzzte3fC=LWy8nM? zM;6u@@Mk&$)|sm9m)Wq4?&VCUFxQpEOl;(Qe|u*z-0R8YIBthF+7AeJXn9W=O%I_5 z<&WOBI_UEu7aaCHgAuk~G**9fvyHEZ}R-~*@yO7TOutj{lbmayP zzhA!<{K&Ujh63pcJND2W9(f2jbT$(VM*8}u zoy0O8XoCBcGqaTU7Yq;xLIR*@fQFN)tntT3Fc;iSb3;F%x7bB4n98e#(o5~j6cOM+ z&qHoM^Xb4Gd*1#vc?r%abhGsp4ShfZ!A9jfCk&(mn$M>CCjoSk7z88>HI0I2xS=QHhMG{MRxb^N{2-y{iIxBudDOXKKPd{e<@Kr;z<|6Wgw*Xx$L48=`eXw9sRtpoeusv~Gyj4bi$GT4ua)%-Fgi)|~xUf}%&} z9WdOkNVqAL&toLN?k#pva6~;1auh)CkcPx<>9<(dV%>S$Idom*o@3;oOZ<f33#JpscUvo(4-M#_*`Fb_i)dgc&B%YCD5>z=;b22pFdUoWzG& z!8LIp0hqB6NoO+-Z}d5zi=YP>{zpZbxJ7|7D>Dvx$N*%C^_X>Q49=~EHClv+t+PYb z8iemD#jmy5bz`$D+u(%>tte!4`5wo&uHjvqj8!@+Y-2>-e;SoO64^JX$g`+fsY6|) z0bxs7m$c9%xTfH73g3PTXZhgvMOlZ192r9gjhsbT984ExvBoX9ySrNm8r z#@*dro1no779hA=a0!q`g1b(C|14)So7&f=p1SA0=M8!{r`p3w?Yd?f!&qeN3QD0E z70!J;Zd}OVY<9s{l(-4$_qcR-4JJFaJfdWuxhQ+c*X$TmSp3l=P2A!ROL7vfV#8mj zrt3|`L@9+}&nh@|V8b8FjsG7_l2Fu*8@jO{qWz#e7<+1;YO6TqO+S$CGO&N9uR--X z%(U7S?BR@&4y&3GZAgdufT{Y}6!;Z#GN*w6%cYSJv}M(UV$&f0Xzy1@^W^Z=maDEKh+ zTS3AW8sbPrYs39)ouK0&H1PAU=SlW76+@PMqsh@d5@XYRTIWIQ5IW;H<7QrTBacOv zv5g9tZzTa-RTVN&AL}%kx=xq+$TTe9Lx!e6ymG9HtP2`w9k{wBL;lprin*+Q-$5mp z`8~aUdh!IRlGg=nwNVS2Fw+LMK;tEn&b-7rt#=YuWtDeg5tclXwelm;7hf)`>q(7{ z>?+DK5_LrkkFrw|8&1AR6`23hLn+E$6vWcLxiwlKt5V=>l`~QSdFrQ?dVJ z?RiDZdtG9L$JQbaU^sGv7to$nlXq)pGq*E{spri0@lNrT?wkVUb@|p=%zUQCS-Z}w zju?;k?CO^romhxg%r5{)r?L;r-6EbcCEloyB$w(p)e&hpWJivi6L*O!x)LSVNG*(= z6#u0!;f1nVSOi{f4W6H90KVjr^AD6K@V{!#`~; zUzLUrpS$F!)oVeDq6j9{#(@~+iUio^6+U*!J6;V%nXX(ZL^3Rkrph1@Iqn_tEOAWjem=Bk_ES(i)ZOgn zh=dSV2$q2SH&Q@0=Y%w9D~oCb`v%X|^?vg8Co@}`O*z7o zTEVI-ONTPj(`KcIKZik&7}lX5z4ZFUf9@b&jt+zI87KLgNIp*TwWg=Ne}V)v+^%Kb?QnOvbkhO9V5gsea^TxV4MbikR_q zo(UZO-=t?4!yeq&Dx;xoydT^l8|JPbXPJ zdMcc2Htpn^aSKeRhCi6{Fk78c_?>BcW|gbi&92$uIx5;6MV~d|i>{E<<}mFW(c=Ps z*~Le&+iA15V%X~`_T1U+uDWbaeWiDrHt%l=3zA>+ec!6QqPDC1!a*3)V+k!(2mh$$qWcwQ9`XcL>U zmDJ=yR;|2TOZFa8ViJa|2KK)YPJ&y_GWWiBLHyH##uMhKPVzOwnqv->>+?8fd^15~ zX(b|0H0SFrFmgV<%HRNWLP8!dk7ouNsvT;dc^cWp?vIp$3dcU+dBpaAXPWeG#g;Sj@lBN9P@mxa;t!l<7-!F!*e8MQKBXG0ev7USS>iHG7&-a)jVa)YyhQzGbr(K5o0GGh6Lu2 z*5dV)Eml90W*)82g62;a;&$M({UbwPO&lC``yF>^eU!p_-s-A=uFiOAns%WqvsWOB2OMz7h?G_Sj|p7>*48R#VXC5fQKW zJ{+O^WYA}6i|p>Je4ekwi8k5X%41iaD{5HCeRXlw)SZ(k=sn9E918HYm!}^NE#pOf zPOz_WFQbT0bWK(+{z-MSulk6}YHigq#}NxgGsR5nS`WoD!&z#$eORC3$x>n?ZFkxT zPaxFw<6bdWKnZ&cT-r9!@=O3tS!Fe}orKbiCYU(*^4VsVJ~@2TG!XjpYm%sf$>1+? zw)1!Tv_m!G zldGRo#Xilg6T%3Czw$*`g*Mj{{zV29UiM4#38q&R(( z_wd8epA6k6s$r{_qL=urXG}X7Hfx(r#5rS(I+4jdx-nV7?Rq+_R~fsWOeXg+Mw`z% z^f68=PejVz=5VGcqx>(3Yss#b?&h&gYoeSv$Nz)C-Tf>pc*uyp2SNGphl@4ew<0!~ zvRL-2Z&pR0I`b(TypMl^?NqZx7?d6Xb)l|`Mow^k^Ku=3VMR*66Ca`;r`zPXeg$eu z?)%TEfNg(qNm#NUt>Wo7qhDB;cv?J;Dvk#3SBqZGNyg2K7cotPz{c*8Ow?Y+FASja zX8|A4jf54j-4)znkGy3S8~|oM>ac4FaPz*Vl<8vBb#jrDF$KO*XV8Jw%_AlvuQIQmge`)mnNU zunk*_R+C~F&IUfG8EU zK8^ihf&<0pmwsPijLlhm(qI2nzscd^ZgAMUw(Azk9$PhdtKjUbk zXIMp0S6fskbr1LgVaJ)Rw#H3*_k3P*an5ER`+f8y{Fx7gU0C`SE8LnEi5^jb{@TVt0!tTMaL75wxm3QCt4p-tjRf60}ak+w<| zP0_tBOJ2AX`g$iL@;;`TT3gzD#JR?L;ZqX!&0}>+*`p%b{(wsr& zOQAE={?%!16&-{+_nZLLY^;_o5 z82?C<9f!Q)9%MhtGzqviwJ#f-+VX+|72{SSZw3#(Gx#e8{Tv0qH45LaS4gHUZmD0Y z>K?2$XW%b%G1RfExfh&waWpxCH#0{CKgw!B@)$UsleO5SsMeA9EmBcMs)&W8jctlz zCIcoJJX_=4{G?VEEjSN7rh56BmJ4=`g5JO{z@_bRZk?CS*>rq<3nyX2>j> z1L3>2tY3PDpMZXG>Ia;Plf?Lf!n$$5H(ZM>!m`Xf+PnGe1L12~HrU?;LOQ>axbK8e zHFa?-r>l$q4$~kYA_Mn)OX4=F{HwK$y=|H;0#rnLWbOqJyAuXnEF0H}PQ_tK{w)q` zK8HW#BMKG`b?c5YElHqo`D20#J7Wi`#@S`~YMS|jD}TFrP^DG$B6gQ6j8`}Ag^1-+ zgX5p_y5uid+o&+Vz*Z$B%M+h-VzyrlD8>=(;B_YY*H|~)?+=>Zhjlf6^iO<~fMxC0 zTeUhm5tvLvm8P^6OLyt_G=l8$e=I8vTVAIn-c8m1DU8ZXD&v}H^oj|pyc8Sxnx#vQ z#ymxBJ#5I#B9U>h?2+Dh4Zbz_8F^J^Zjv2?hG3Gx(tytzTiXDU^)J?fTpmb?oHc*k zp1WZ}cbY%}tX3P%W#}^@UZcS)r~82`VJ6T>AAA@l`s_5ve(*LC$)O~8X6hf8V!DzZ zealt3{`rfKfBFJE=2{J!TVj0I-ad5SzTXJYAtaSFB{OU}cr2}_K21m89ynY6;0-7f zr*B{EOeXCQUWiNVvbxT7qov?{#@rWY8?%Zb3d3DQN^WwC976zN9wrZGnt7!PT~&K% zp%a(y94>qx2|qs1aL_YEaDC8SyhSZxBsHWJR3@9vm-%6fOHsJRPG})+_^!h zz2h}N768q5z{KR5^zTRs-`nqyw(>{Czx>n*$fc5EWyawz;k@$95F7=R zG>rcG6J6dx$`x{I9sC0GQ9~>JNBRxpFv1aS`Crn`9s2&yEp!WCxyuW1hi8+~G~?_} zX!FR-KY2?DXG?<4l&#$_^-*;{iC#{I6h^^uMTJB4HE50}M3po0taz{|;_Ubwo11u> zh9BEADnFT4Pvsdd@a6SNvGc8(KoRm2y|_;r5;MIw`N^Vy%-rWBH*g>joJhsBz@ETV zbZCc-s{}7PfZ)$9$=iWlgfIXj;jN+%5sGedhxo;1&w_kQpMhe-)7rW?X6U{Th_J}U zB#ELosgKbeUrZ>{IX`AUX$G>e>|GK8LUAbzDB{%mU_8;cq$}qOc{@q!6*S{_Q9|He zZU&h4yNGAt)73PJdvW)efXDE$XGPp3h?q}HGVzu)7)h^=QcUjZW;(#2;EwON8!T>) zi0rNMYTO?82P6hHr_*ipZSg?-XzC_uYTzhopSHEEg@#ZU21X=cFu`aYuFCjw6c}mD zWeAgou1NXkq-Pp>( zzeNb1nK4aj^uBn2ckELc%k}%@f?eXnE0@=RQB`b_(63ilq7uAh(>GyBnu>RKK2JR! zQ|SKh3|n^~4y-E7#|Gx7bI_|2%whBTAQE&G`W_F`sq1_jL62{$@m^4n(PKqWQ#PX@-w+~m}7z%c$bZnV5wh5d948~v4C`8Ru8 z3)%dxgcXU}fA^yQfo(|qe_(qk#+L8>YLe?r#^9p*WlR{vn@{LsIDIj`TX%%i$zO4? z9RE2@VQ#W{EGm8Sd(A)kVKJzq<@DRiWj?UeUhM;#;E~(}dYKZ~kgR3$jmAoEA;pe+ zxx-wlMJ zvb1|4@1}n~@jdisZdiUePSQLnqAb*+EWr{26oP=UEU8-g+mhr;)g7v1=4vd(xS0k8 zDjDLDvxpK=m|{kD`c``S?^U~u&>z#P%%VV2=Pj2hz-m7~ z8bmYo$zQ$L$If%!w)%wCmND*==F{x`h-}RjJb0i**^4f8ej^_+8;x zNmMa`wOc!vT2gN+S5Bi6CH_V( zyFtetKrT&&>hM*Bv8DCFQB_#5{4HXPh#LP~5ysxl_k-Qn$C9k`I~p7?n=M=%NGy$2 zRH+ou7Z%cP$9U|eQ+CnPwNOP^vae!7rhALBO>63()fa*{uky_Zfj>qqmHL|_Y$Byl7(1#{#r_UDNBPMO zGAu;M97Y)D-?-3ysrxb#we&$Y2;L2qA$kPA0Y!03VZdRy5 zOP2FCkbf%o_-tr(&zEA-vT|Z>0!~M%oT&UgX|?23`02ak_?YY%4P_3Ie~$@aPPgcz zV}M4wiyg*ZHJ_!k2d_fpWG=SaM3*DQNljpGE=m*nrTx0%%dg1}3;Ns)yCkDh_Vqp+ z;-|>R!;5sR}m;_tfY|YT+)GghM{C z+~h&}=OsEU8-z$23074H@)?or*qcabZco}HP+y;czJ6^OhXMHlApkV$h(Xes4?L%3 zI4X)Vm+-y1ju#O;TB%7)iz19J*&!ge6hIAQ%2trRN%P#)cG<6S&=4oFjsyEY87{I- z8^+0&HaxaOY!!nz#)HB?B#Oo(6DIx4j0qk$G~_<4UwpbXrz|J~c0!<&P<5w| z2et}UXTTTgsQ!?#0%7`ZrG8xuO-dMdFqxX1$ty+3fanY0hs}sM(mg19sP1%3ZMmWQ zC#TylAf!3!+P&v41)aJZ`g$s{`bq+Q^s}s~_mBzgLP5k>1cd3w5uI=+Q~b+R=Te1~ zq*trPQC=~G&7WG-Iao$Il%dXO0Ka_-&xZ^o4YfWlY;_jtX~X_^-YYIVx~WQ~QVeVP zZZCU+n`SJL;NSr@0B9f=Xf_LX0U$UwsBRzlwj|Z#B6MPE!Vt!ZeZ4&J#q)s0G&g*h zI2c-@0cu}22`Ah1@`>joRtkd%eZY6N{Nr>q1p5S5paj;ZQgUJAB=#te!xAAp5Hx8Q zlgb-&NwO@)?bj>dkVmC*dw+1pc1xM5G7?Bm#3;9fKXUS=A}7VQ;kEdQ7m}B1=6HR& zM*eNMbwakeDaFZ&j+Aulmu&N+-|@-`*scO?4@8Dy<&C^~c&rD$!nr*W_N^3ity9f# zXfUqoIy1Q^Vb(D~bv)fUs;AeshN`q|Zg6TdK&oN{JeEvSdc}nlsppheMS4{@pBtG?iL260Iz51~*2MoRVxF=yFPhg5&Sx?vIm$!3ZB zH@Y@n(RnYcW?8%XkE56c$ZHv(O{hK(>)`0mXnTR-l8&M!Cma#DtpSFD^TUy_Yn-TVs=;lZobat~6ZV$}VD(oYayX2APZ z-N67{cm|CgPNc^F3j195z_CS1i50j#XmP;bi%?`=Z!+I4J-Qa&qY)F0AO{Nl(Z20L zEypQbSi+O1WHhL{dxbZX6X;NH=T7A2f!YA%vUhoe+(YROB49NRSXv)BJ6{cJ4+As!nU0EBMn z9#JJEW;cvr7$vUU3=C`*K^h0k{M6Ai5gbERuo#S5UJ&`}b(7KU4Pz3X5iI1cW5aUg zmP}PpKtus)tK@r!&|Le+I9ZQ@Y*9KbuU~=^eZViDrAvACIcfr1dt{)F#5!3VvC zjtTedcNO}3V@5#CSBrAu#)+kUwWSne(G>lB7}3DyQ~a&&d0s0&KrS7F1Xwd1SPW?} zD&eym?_1reY);UUA8Ab1-U<9d>R-E)dRY?(&0Ryd3&)In*uy9{<-#U%g_7YX`w<$2 zhtf&(f0o9=QvPgPQ3~MA<;b#f28-jp7O$Esnf{-E!;vXT)BhLZc5b9f7kU$DZQ8w7^#=R_^fkVBL; zC?|Ikev4%C~T^;8Ek_67pn)p z-YU3S_mp-${PFhrL&a9}LbucULA;ELr}Ud9RafEIK19B4BrtaWQ_|!nNr4X;?=TPs z8amz(xqLxjr1FKRYy$o?y^sK(hB7;D z5)r3-txS60)!QiZ4NMX2$CDIH+!y?Z=kBzT)@w=#N}3~zq-a1Tw`j}wo{-+X%NJd& zwG7Fn`Kvu^)}H6#nE@DASk%+QPdvk#u|})yKK~ufN$#B3j$e2@S9Pb37S-ZuZF#9% z!&zlyq+>Fz(WdNnq-ye*6w6Vo*Ks4@+FeTdL&D#|VR!u>s*h`{^44Zd#LAbv>hVJ+ z_3mA07Y@OMW?A|A`A{vd+(q+dS%4}UvUq=cGOb&fRdw)Uq@kpQ=)=GC*K(aiy)j4J zzFJoD>upOO+^~G_5|}K%1wN0j3W9B5N{Qj4>2l!^Yne;yw_#W;sS%!oNx`%(_9*l*O|qDZUx#>sUt5no zF0nJy&dfNFSY0@)r#vFlXn_o%I=Y?-0$+3ah#7TVi$@y5+~fAI`xLiJqtslji&~nx zex#pHm->u$|CROLGxE81K0w2guVa5*?cC{;Ci2i$)a-h7$G~=G47vdP<3dcWd++h3 z4LbJL&~9|Kp^otm>Li9COK5JptXW)L57;y9wso~DWTNBiq9`hFz=2$vHJt&## z772GM!3pk#H?4HU>Q{2}^=5ALYJL$B^I4*thjxCrZ&sX#W`vSohUnpMX*<-J{bGb; zUzMDf&}-W(A9gt%CPvMIey#tG4}~xW_6?W=Of|`$`I8@4&9-%m?mzba~}`wl-lfm6^j-8OyzSa(k>PBrZ(8iNt|7 zr?O&ck>^%_v)oi~)zDnJ=cjEh#`0kfMmwpk-poqp(z`g}h!&V64{XRHe>iL&W5Xk|(ev7W0Cl8QQ1I!Zh&zOu0OzAXl^D56MNv zY(O`AlE?q=^cM&k|LUPs;f)>F5bVLtA@PC!jo#4zT>ipcYpJq3Q+b-BT!(lUy(Kyy zj9%g0M5I7&S2_$^ey=dLI!t%+=65*UAENQ2U%n!=dGuxVGYl3JiznrkizOULW+Juj zOCEikI%@4}Qh#qk)CN7bE!T*2!L{V-dDUmI&`Sgr3V@;jotVr1Zt7%{Jkl10T@W~% zJtp`v4|sefqY(^`6ls%#AdCSrzb&PpI1Q{)-nyNw!5|~n_ciYuw}9?tT;s}Gr@}xX zlg`crO&c)l@96lTHSP9-uGV2%g}+s`n?tdPn65l;e}Z5Z#v1n%97LqYi)(ru6<_!E z6fYCT>I59WWOVuOY7SZPbTj`*sCN;^-|n2^jaz1jY+hD7!CJ+?-y%lMI30OMgMoQ} Nw@J1LHh4gQ`9C{nHm3jp diff --git a/chain/actors/builtin/miner/actor.go.template b/chain/actors/builtin/miner/actor.go.template index 2669a05a6..2b6b78ebc 100644 --- a/chain/actors/builtin/miner/actor.go.template +++ b/chain/actors/builtin/miner/actor.go.template @@ -177,6 +177,7 @@ type SectorOnChainInfo struct { InitialPledge abi.TokenAmount ExpectedDayReward abi.TokenAmount ExpectedStoragePledge abi.TokenAmount + SectorKeyCID *cid.Cid } type SectorPreCommitInfo = miner0.SectorPreCommitInfo diff --git a/chain/actors/builtin/miner/miner.go b/chain/actors/builtin/miner/miner.go index f6d633880..e60ff8da8 100644 --- a/chain/actors/builtin/miner/miner.go +++ b/chain/actors/builtin/miner/miner.go @@ -266,6 +266,7 @@ type SectorOnChainInfo struct { InitialPledge abi.TokenAmount ExpectedDayReward abi.TokenAmount ExpectedStoragePledge abi.TokenAmount + SectorKeyCID *cid.Cid } type SectorPreCommitInfo = miner0.SectorPreCommitInfo diff --git a/chain/actors/builtin/miner/state.go.template b/chain/actors/builtin/miner/state.go.template index 2ea6a905e..775631961 100644 --- a/chain/actors/builtin/miner/state.go.template +++ b/chain/actors/builtin/miner/state.go.template @@ -138,11 +138,22 @@ func (s *state{{.v}}) GetSectorExpiration(num abi.SectorNumber) (*SectorExpirati return nil, err } // NOTE: this can be optimized significantly. - // 1. If the sector is non-faulty, it will either expire on-time (can be +{{if (ge .v 7) -}} + // 1. If the sector is non-faulty, it will expire on-time (can be + // learned from the sector info). +{{- else -}} + // 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. +{{- end}} +{{if (ge .v 6) -}} + // 2. If it's faulty, it will expire early within the first 42 entries + // of the expiration queue. +{{- else -}} // 2. If it's faulty, it will expire early within the first 14 entries // of the expiration queue. +{{- end}} + stopErr := errors.New("stop") out := SectorExpiration{} err = dls.ForEach(s.store, func(dlIdx uint64, dl *miner{{.v}}.Deadline) error { @@ -554,8 +565,7 @@ func (p *partition{{.v}}) UnprovenSectors() (bitfield.BitField, error) { } func fromV{{.v}}SectorOnChainInfo(v{{.v}} miner{{.v}}.SectorOnChainInfo) SectorOnChainInfo { -{{if (ge .v 2)}} - return SectorOnChainInfo{ + info := SectorOnChainInfo{ SectorNumber: v{{.v}}.SectorNumber, SealProof: v{{.v}}.SealProof, SealedCID: v{{.v}}.SealedCID, @@ -567,10 +577,11 @@ func fromV{{.v}}SectorOnChainInfo(v{{.v}} miner{{.v}}.SectorOnChainInfo) SectorO InitialPledge: v{{.v}}.InitialPledge, ExpectedDayReward: v{{.v}}.ExpectedDayReward, ExpectedStoragePledge: v{{.v}}.ExpectedStoragePledge, + {{if (ge .v 7)}} + SectorKeyCID: v{{.v}}.SectorKeyCID, + {{end}} } -{{else}} - return (SectorOnChainInfo)(v0) -{{end}} + return info } func fromV{{.v}}SectorPreCommitOnChainInfo(v{{.v}} miner{{.v}}.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { diff --git a/chain/actors/builtin/miner/v0.go b/chain/actors/builtin/miner/v0.go index 564bcbbc2..8bde8bf73 100644 --- a/chain/actors/builtin/miner/v0.go +++ b/chain/actors/builtin/miner/v0.go @@ -140,6 +140,7 @@ func (s *state0) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, e // 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 *miner0.Deadline) error { @@ -505,9 +506,20 @@ func (p *partition0) UnprovenSectors() (bitfield.BitField, error) { } func fromV0SectorOnChainInfo(v0 miner0.SectorOnChainInfo) SectorOnChainInfo { - - return (SectorOnChainInfo)(v0) - + info := SectorOnChainInfo{ + SectorNumber: v0.SectorNumber, + SealProof: v0.SealProof, + SealedCID: v0.SealedCID, + DealIDs: v0.DealIDs, + Activation: v0.Activation, + Expiration: v0.Expiration, + DealWeight: v0.DealWeight, + VerifiedDealWeight: v0.VerifiedDealWeight, + InitialPledge: v0.InitialPledge, + ExpectedDayReward: v0.ExpectedDayReward, + ExpectedStoragePledge: v0.ExpectedStoragePledge, + } + return info } func fromV0SectorPreCommitOnChainInfo(v0 miner0.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { diff --git a/chain/actors/builtin/miner/v2.go b/chain/actors/builtin/miner/v2.go index fe0863111..bbfdd403e 100644 --- a/chain/actors/builtin/miner/v2.go +++ b/chain/actors/builtin/miner/v2.go @@ -138,6 +138,7 @@ func (s *state2) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, e // 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 *miner2.Deadline) error { @@ -535,8 +536,7 @@ func (p *partition2) UnprovenSectors() (bitfield.BitField, error) { } func fromV2SectorOnChainInfo(v2 miner2.SectorOnChainInfo) SectorOnChainInfo { - - return SectorOnChainInfo{ + info := SectorOnChainInfo{ SectorNumber: v2.SectorNumber, SealProof: v2.SealProof, SealedCID: v2.SealedCID, @@ -549,7 +549,7 @@ func fromV2SectorOnChainInfo(v2 miner2.SectorOnChainInfo) SectorOnChainInfo { ExpectedDayReward: v2.ExpectedDayReward, ExpectedStoragePledge: v2.ExpectedStoragePledge, } - + return info } func fromV2SectorPreCommitOnChainInfo(v2 miner2.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { diff --git a/chain/actors/builtin/miner/v3.go b/chain/actors/builtin/miner/v3.go index b0d5429ea..68505918a 100644 --- a/chain/actors/builtin/miner/v3.go +++ b/chain/actors/builtin/miner/v3.go @@ -140,6 +140,7 @@ func (s *state3) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, e // epoch (i.e., the first element in the partition's expiration queue. // 2. If it's faulty, it will expire early within the first 14 entries // of the expiration queue. + stopErr := errors.New("stop") out := SectorExpiration{} err = dls.ForEach(s.store, func(dlIdx uint64, dl *miner3.Deadline) error { @@ -536,8 +537,7 @@ func (p *partition3) UnprovenSectors() (bitfield.BitField, error) { } func fromV3SectorOnChainInfo(v3 miner3.SectorOnChainInfo) SectorOnChainInfo { - - return SectorOnChainInfo{ + info := SectorOnChainInfo{ SectorNumber: v3.SectorNumber, SealProof: v3.SealProof, SealedCID: v3.SealedCID, @@ -550,7 +550,7 @@ func fromV3SectorOnChainInfo(v3 miner3.SectorOnChainInfo) SectorOnChainInfo { ExpectedDayReward: v3.ExpectedDayReward, ExpectedStoragePledge: v3.ExpectedStoragePledge, } - + return info } func fromV3SectorPreCommitOnChainInfo(v3 miner3.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { diff --git a/chain/actors/builtin/miner/v4.go b/chain/actors/builtin/miner/v4.go index 7e5a9761a..5c40d4189 100644 --- a/chain/actors/builtin/miner/v4.go +++ b/chain/actors/builtin/miner/v4.go @@ -140,6 +140,7 @@ func (s *state4) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, e // 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 { @@ -536,8 +537,7 @@ func (p *partition4) UnprovenSectors() (bitfield.BitField, error) { } func fromV4SectorOnChainInfo(v4 miner4.SectorOnChainInfo) SectorOnChainInfo { - - return SectorOnChainInfo{ + info := SectorOnChainInfo{ SectorNumber: v4.SectorNumber, SealProof: v4.SealProof, SealedCID: v4.SealedCID, @@ -550,7 +550,7 @@ func fromV4SectorOnChainInfo(v4 miner4.SectorOnChainInfo) SectorOnChainInfo { ExpectedDayReward: v4.ExpectedDayReward, ExpectedStoragePledge: v4.ExpectedStoragePledge, } - + return info } func fromV4SectorPreCommitOnChainInfo(v4 miner4.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { diff --git a/chain/actors/builtin/miner/v5.go b/chain/actors/builtin/miner/v5.go index 7f4aaf168..f717934f4 100644 --- a/chain/actors/builtin/miner/v5.go +++ b/chain/actors/builtin/miner/v5.go @@ -140,6 +140,7 @@ func (s *state5) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, e // 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 *miner5.Deadline) error { @@ -536,8 +537,7 @@ func (p *partition5) UnprovenSectors() (bitfield.BitField, error) { } func fromV5SectorOnChainInfo(v5 miner5.SectorOnChainInfo) SectorOnChainInfo { - - return SectorOnChainInfo{ + info := SectorOnChainInfo{ SectorNumber: v5.SectorNumber, SealProof: v5.SealProof, SealedCID: v5.SealedCID, @@ -550,7 +550,7 @@ func fromV5SectorOnChainInfo(v5 miner5.SectorOnChainInfo) SectorOnChainInfo { ExpectedDayReward: v5.ExpectedDayReward, ExpectedStoragePledge: v5.ExpectedStoragePledge, } - + return info } func fromV5SectorPreCommitOnChainInfo(v5 miner5.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { diff --git a/chain/actors/builtin/miner/v6.go b/chain/actors/builtin/miner/v6.go index de5a22a10..7a9dfb0df 100644 --- a/chain/actors/builtin/miner/v6.go +++ b/chain/actors/builtin/miner/v6.go @@ -138,8 +138,9 @@ func (s *state6) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, e // 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 + // 2. If it's faulty, it will expire early within the first 42 entries // of the expiration queue. + stopErr := errors.New("stop") out := SectorExpiration{} err = dls.ForEach(s.store, func(dlIdx uint64, dl *miner6.Deadline) error { @@ -536,8 +537,7 @@ func (p *partition6) UnprovenSectors() (bitfield.BitField, error) { } func fromV6SectorOnChainInfo(v6 miner6.SectorOnChainInfo) SectorOnChainInfo { - - return SectorOnChainInfo{ + info := SectorOnChainInfo{ SectorNumber: v6.SectorNumber, SealProof: v6.SealProof, SealedCID: v6.SealedCID, @@ -550,7 +550,7 @@ func fromV6SectorOnChainInfo(v6 miner6.SectorOnChainInfo) SectorOnChainInfo { ExpectedDayReward: v6.ExpectedDayReward, ExpectedStoragePledge: v6.ExpectedStoragePledge, } - + return info } func fromV6SectorPreCommitOnChainInfo(v6 miner6.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { diff --git a/chain/actors/builtin/miner/v7.go b/chain/actors/builtin/miner/v7.go index c7096a781..e1b2520e4 100644 --- a/chain/actors/builtin/miner/v7.go +++ b/chain/actors/builtin/miner/v7.go @@ -135,11 +135,11 @@ func (s *state7) GetSectorExpiration(num abi.SectorNumber) (*SectorExpiration, e 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 + // 1. If the sector is non-faulty, it will expire on-time (can be + // learned from the sector info). + // 2. If it's faulty, it will expire early within the first 42 entries // of the expiration queue. + stopErr := errors.New("stop") out := SectorExpiration{} err = dls.ForEach(s.store, func(dlIdx uint64, dl *miner7.Deadline) error { @@ -536,8 +536,7 @@ func (p *partition7) UnprovenSectors() (bitfield.BitField, error) { } func fromV7SectorOnChainInfo(v7 miner7.SectorOnChainInfo) SectorOnChainInfo { - - return SectorOnChainInfo{ + info := SectorOnChainInfo{ SectorNumber: v7.SectorNumber, SealProof: v7.SealProof, SealedCID: v7.SealedCID, @@ -549,8 +548,10 @@ func fromV7SectorOnChainInfo(v7 miner7.SectorOnChainInfo) SectorOnChainInfo { InitialPledge: v7.InitialPledge, ExpectedDayReward: v7.ExpectedDayReward, ExpectedStoragePledge: v7.ExpectedStoragePledge, - } + SectorKeyCID: v7.SectorKeyCID, + } + return info } func fromV7SectorPreCommitOnChainInfo(v7 miner7.SectorPreCommitOnChainInfo) SectorPreCommitOnChainInfo { diff --git a/chain/vm/runtime.go b/chain/vm/runtime.go index 583c99593..0dbe98224 100644 --- a/chain/vm/runtime.go +++ b/chain/vm/runtime.go @@ -16,7 +16,11 @@ import ( "github.com/filecoin-project/go-state-types/network" rtt "github.com/filecoin-project/go-state-types/rt" rt0 "github.com/filecoin-project/specs-actors/actors/runtime" + rt2 "github.com/filecoin-project/specs-actors/v2/actors/runtime" + rt3 "github.com/filecoin-project/specs-actors/v3/actors/runtime" + rt4 "github.com/filecoin-project/specs-actors/v4/actors/runtime" rt5 "github.com/filecoin-project/specs-actors/v5/actors/runtime" + rt6 "github.com/filecoin-project/specs-actors/v6/actors/runtime" rt7 "github.com/filecoin-project/specs-actors/v7/actors/runtime" "github.com/ipfs/go-cid" ipldcbor "github.com/ipfs/go-ipld-cbor" @@ -142,6 +146,11 @@ func (rt *Runtime) StorePut(x cbor.Marshaler) cid.Cid { var _ rt0.Runtime = (*Runtime)(nil) var _ rt5.Runtime = (*Runtime)(nil) +var _ rt2.Runtime = (*Runtime)(nil) +var _ rt3.Runtime = (*Runtime)(nil) +var _ rt4.Runtime = (*Runtime)(nil) +var _ rt5.Runtime = (*Runtime)(nil) +var _ rt6.Runtime = (*Runtime)(nil) var _ rt7.Runtime = (*Runtime)(nil) func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) { diff --git a/documentation/en/api-v0-methods.md b/documentation/en/api-v0-methods.md index 42bb945d0..09c3d1c34 100644 --- a/documentation/en/api-v0-methods.md +++ b/documentation/en/api-v0-methods.md @@ -5016,7 +5016,8 @@ Response: "VerifiedDealWeight": "0", "InitialPledge": "0", "ExpectedDayReward": "0", - "ExpectedStoragePledge": "0" + "ExpectedStoragePledge": "0", + "SectorKeyCID": null } ``` diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 3578a4492..91baffdc6 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -5223,7 +5223,8 @@ Response: "VerifiedDealWeight": "0", "InitialPledge": "0", "ExpectedDayReward": "0", - "ExpectedStoragePledge": "0" + "ExpectedStoragePledge": "0", + "SectorKeyCID": null } ``` diff --git a/itests/wdpost_test.go b/itests/wdpost_test.go index b1420e6a3..d87059bb4 100644 --- a/itests/wdpost_test.go +++ b/itests/wdpost_test.go @@ -23,7 +23,7 @@ import ( ) func TestWindowedPost(t *testing.T) { - //kit.Expensive(t) + kit.Expensive(t) kit.QuietMiningLogs() From 7d2b3f05db38cee481c4b91e628b53bb460bdadc Mon Sep 17 00:00:00 2001 From: zenground0 Date: Wed, 10 Nov 2021 13:53:00 -0500 Subject: [PATCH 07/12] WIP sector storage and integration test --- api/api_storage.go | 25 +-- api/api_worker.go | 3 + api/proxy_gen.go | 78 +++++++++ build/openrpc/full.json.gz | Bin 25465 -> 25466 bytes build/openrpc/miner.json.gz | Bin 10467 -> 10672 bytes build/openrpc/worker.json.gz | Bin 2713 -> 2940 bytes documentation/en/api-v0-methods-miner.md | 85 +++++++++ documentation/en/api-v0-methods-worker.md | 118 +++++++++++++ extern/filecoin-ffi | 2 +- .../sector-storage/ffiwrapper/sealer_cgo.go | 83 +++++++++ .../sector-storage/ffiwrapper/verifier_cgo.go | 3 +- extern/sector-storage/manager.go | 161 ++++++++++++++++++ extern/sector-storage/manager_calltracker.go | 1 - extern/sector-storage/manager_test.go | 139 ++++++++++++++- extern/sector-storage/mock/mock.go | 32 ++++ extern/sector-storage/sched_test.go | 12 ++ extern/sector-storage/sealtasks/task.go | 27 ++- extern/sector-storage/storiface/filetype.go | 42 +++-- extern/sector-storage/storiface/worker.go | 6 + extern/sector-storage/teststorage_test.go | 16 ++ extern/sector-storage/testworker_test.go | 28 +++ extern/sector-storage/worker_local.go | 85 ++++++--- extern/sector-storage/worker_tracked.go | 19 ++- go.mod | 4 +- go.sum | 10 +- 25 files changed, 911 insertions(+), 68 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index 8cca2aa5b..bf7520d09 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -118,17 +118,20 @@ type StorageMiner interface { WorkerJobs(context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) //perm:admin //storiface.WorkerReturn - ReturnAddPiece(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err *storiface.CallError) error //perm:admin retry:true - ReturnSealPreCommit1(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err *storiface.CallError) error //perm:admin retry:true - ReturnSealPreCommit2(ctx context.Context, callID storiface.CallID, sealed storage.SectorCids, err *storiface.CallError) error //perm:admin retry:true - ReturnSealCommit1(ctx context.Context, callID storiface.CallID, out storage.Commit1Out, err *storiface.CallError) error //perm:admin retry:true - ReturnSealCommit2(ctx context.Context, callID storiface.CallID, proof storage.Proof, err *storiface.CallError) error //perm:admin retry:true - ReturnFinalizeSector(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true - ReturnReleaseUnsealed(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true - ReturnMoveStorage(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true - ReturnUnsealPiece(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true - ReturnReadPiece(ctx context.Context, callID storiface.CallID, ok bool, err *storiface.CallError) error //perm:admin retry:true - ReturnFetch(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true + ReturnAddPiece(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err *storiface.CallError) error //perm:admin retry:true + ReturnSealPreCommit1(ctx context.Context, callID storiface.CallID, p1o storage.PreCommit1Out, err *storiface.CallError) error //perm:admin retry:true + ReturnSealPreCommit2(ctx context.Context, callID storiface.CallID, sealed storage.SectorCids, err *storiface.CallError) error //perm:admin retry:true + ReturnSealCommit1(ctx context.Context, callID storiface.CallID, out storage.Commit1Out, err *storiface.CallError) error //perm:admin retry:true + ReturnSealCommit2(ctx context.Context, callID storiface.CallID, proof storage.Proof, err *storiface.CallError) error //perm:admin retry:true + ReturnFinalizeSector(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true + ReturnReplicaUpdate(ctx context.Context, callID storiface.CallID, out storage.ReplicaUpdateOut, err *storiface.CallError) error //perm:admin retry:true + ReturnProveReplicaUpdate1(ctx context.Context, callID storiface.CallID, vanillaProofs storage.ReplicaVanillaProofs, err *storiface.CallError) error //perm:admin retry:true + ReturnProveReplicaUpdate2(ctx context.Context, callID storiface.CallID, proof storage.ReplicaUpdateProof, err *storiface.CallError) error //perm:admin retry:true + ReturnReleaseUnsealed(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true + ReturnMoveStorage(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true + ReturnUnsealPiece(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true + ReturnReadPiece(ctx context.Context, callID storiface.CallID, ok bool, err *storiface.CallError) error //perm:admin retry:true + ReturnFetch(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true // SealingSchedDiag dumps internal sealing scheduler state SealingSchedDiag(ctx context.Context, doSched bool) (interface{}, error) //perm:admin diff --git a/api/api_worker.go b/api/api_worker.go index 4553c30e0..5e0b4f8c6 100644 --- a/api/api_worker.go +++ b/api/api_worker.go @@ -39,6 +39,9 @@ type Worker interface { SealCommit1(ctx context.Context, sector storage.SectorRef, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage.SectorCids) (storiface.CallID, error) //perm:admin SealCommit2(ctx context.Context, sector storage.SectorRef, c1o storage.Commit1Out) (storiface.CallID, error) //perm:admin FinalizeSector(ctx context.Context, sector storage.SectorRef, keepUnsealed []storage.Range) (storiface.CallID, error) //perm:admin + ReplicaUpdate(ctx context.Context, sector storage.SectorRef, pieces []abi.PieceInfo) (storiface.CallID, error) //perm:admin + ProveReplicaUpdate1(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid) (storiface.CallID, error) //perm:admin + ProveReplicaUpdate2(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid, vanillaProofs storage.ReplicaVanillaProofs) (storiface.CallID, error) //perm:admin ReleaseUnsealed(ctx context.Context, sector storage.SectorRef, safeToFree []storage.Range) (storiface.CallID, error) //perm:admin MoveStorage(ctx context.Context, sector storage.SectorRef, types storiface.SectorFileType) (storiface.CallID, error) //perm:admin UnsealPiece(context.Context, storage.SectorRef, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (storiface.CallID, error) //perm:admin diff --git a/api/proxy_gen.go b/api/proxy_gen.go index b36f19a7e..b78b40959 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -709,10 +709,16 @@ type StorageMinerStruct struct { ReturnMoveStorage func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnProveReplicaUpdate1 func(p0 context.Context, p1 storiface.CallID, p2 storage.ReplicaVanillaProofs, p3 *storiface.CallError) error `perm:"admin"` + + ReturnProveReplicaUpdate2 func(p0 context.Context, p1 storiface.CallID, p2 storage.ReplicaUpdateProof, p3 *storiface.CallError) error `perm:"admin"` + ReturnReadPiece func(p0 context.Context, p1 storiface.CallID, p2 bool, p3 *storiface.CallError) error `perm:"admin"` ReturnReleaseUnsealed func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnReplicaUpdate func(p0 context.Context, p1 storiface.CallID, p2 storage.ReplicaUpdateOut, p3 *storiface.CallError) error `perm:"admin"` + ReturnSealCommit1 func(p0 context.Context, p1 storiface.CallID, p2 storage.Commit1Out, p3 *storiface.CallError) error `perm:"admin"` ReturnSealCommit2 func(p0 context.Context, p1 storiface.CallID, p2 storage.Proof, p3 *storiface.CallError) error `perm:"admin"` @@ -852,10 +858,16 @@ type WorkerStruct struct { ProcessSession func(p0 context.Context) (uuid.UUID, error) `perm:"admin"` + ProveReplicaUpdate1 func(p0 context.Context, p1 storage.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid) (storiface.CallID, error) `perm:"admin"` + + ProveReplicaUpdate2 func(p0 context.Context, p1 storage.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid, p5 storage.ReplicaVanillaProofs) (storiface.CallID, error) `perm:"admin"` + ReleaseUnsealed func(p0 context.Context, p1 storage.SectorRef, p2 []storage.Range) (storiface.CallID, error) `perm:"admin"` Remove func(p0 context.Context, p1 abi.SectorID) error `perm:"admin"` + ReplicaUpdate func(p0 context.Context, p1 storage.SectorRef, p2 []abi.PieceInfo) (storiface.CallID, error) `perm:"admin"` + SealCommit1 func(p0 context.Context, p1 storage.SectorRef, p2 abi.SealRandomness, p3 abi.InteractiveSealRandomness, p4 []abi.PieceInfo, p5 storage.SectorCids) (storiface.CallID, error) `perm:"admin"` SealCommit2 func(p0 context.Context, p1 storage.SectorRef, p2 storage.Commit1Out) (storiface.CallID, error) `perm:"admin"` @@ -4165,6 +4177,28 @@ func (s *StorageMinerStub) ReturnMoveStorage(p0 context.Context, p1 storiface.Ca return ErrNotSupported } +func (s *StorageMinerStruct) ReturnProveReplicaUpdate1(p0 context.Context, p1 storiface.CallID, p2 storage.ReplicaVanillaProofs, p3 *storiface.CallError) error { + if s.Internal.ReturnProveReplicaUpdate1 == nil { + return ErrNotSupported + } + return s.Internal.ReturnProveReplicaUpdate1(p0, p1, p2, p3) +} + +func (s *StorageMinerStub) ReturnProveReplicaUpdate1(p0 context.Context, p1 storiface.CallID, p2 storage.ReplicaVanillaProofs, p3 *storiface.CallError) error { + return ErrNotSupported +} + +func (s *StorageMinerStruct) ReturnProveReplicaUpdate2(p0 context.Context, p1 storiface.CallID, p2 storage.ReplicaUpdateProof, p3 *storiface.CallError) error { + if s.Internal.ReturnProveReplicaUpdate2 == nil { + return ErrNotSupported + } + return s.Internal.ReturnProveReplicaUpdate2(p0, p1, p2, p3) +} + +func (s *StorageMinerStub) ReturnProveReplicaUpdate2(p0 context.Context, p1 storiface.CallID, p2 storage.ReplicaUpdateProof, p3 *storiface.CallError) error { + return ErrNotSupported +} + func (s *StorageMinerStruct) ReturnReadPiece(p0 context.Context, p1 storiface.CallID, p2 bool, p3 *storiface.CallError) error { if s.Internal.ReturnReadPiece == nil { return ErrNotSupported @@ -4187,6 +4221,17 @@ func (s *StorageMinerStub) ReturnReleaseUnsealed(p0 context.Context, p1 storifac return ErrNotSupported } +func (s *StorageMinerStruct) ReturnReplicaUpdate(p0 context.Context, p1 storiface.CallID, p2 storage.ReplicaUpdateOut, p3 *storiface.CallError) error { + if s.Internal.ReturnReplicaUpdate == nil { + return ErrNotSupported + } + return s.Internal.ReturnReplicaUpdate(p0, p1, p2, p3) +} + +func (s *StorageMinerStub) ReturnReplicaUpdate(p0 context.Context, p1 storiface.CallID, p2 storage.ReplicaUpdateOut, p3 *storiface.CallError) error { + return ErrNotSupported +} + func (s *StorageMinerStruct) ReturnSealCommit1(p0 context.Context, p1 storiface.CallID, p2 storage.Commit1Out, p3 *storiface.CallError) error { if s.Internal.ReturnSealCommit1 == nil { return ErrNotSupported @@ -4858,6 +4903,28 @@ func (s *WorkerStub) ProcessSession(p0 context.Context) (uuid.UUID, error) { return *new(uuid.UUID), ErrNotSupported } +func (s *WorkerStruct) ProveReplicaUpdate1(p0 context.Context, p1 storage.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid) (storiface.CallID, error) { + if s.Internal.ProveReplicaUpdate1 == nil { + return *new(storiface.CallID), ErrNotSupported + } + return s.Internal.ProveReplicaUpdate1(p0, p1, p2, p3, p4) +} + +func (s *WorkerStub) ProveReplicaUpdate1(p0 context.Context, p1 storage.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid) (storiface.CallID, error) { + return *new(storiface.CallID), ErrNotSupported +} + +func (s *WorkerStruct) ProveReplicaUpdate2(p0 context.Context, p1 storage.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid, p5 storage.ReplicaVanillaProofs) (storiface.CallID, error) { + if s.Internal.ProveReplicaUpdate2 == nil { + return *new(storiface.CallID), ErrNotSupported + } + return s.Internal.ProveReplicaUpdate2(p0, p1, p2, p3, p4, p5) +} + +func (s *WorkerStub) ProveReplicaUpdate2(p0 context.Context, p1 storage.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid, p5 storage.ReplicaVanillaProofs) (storiface.CallID, error) { + return *new(storiface.CallID), ErrNotSupported +} + func (s *WorkerStruct) ReleaseUnsealed(p0 context.Context, p1 storage.SectorRef, p2 []storage.Range) (storiface.CallID, error) { if s.Internal.ReleaseUnsealed == nil { return *new(storiface.CallID), ErrNotSupported @@ -4880,6 +4947,17 @@ func (s *WorkerStub) Remove(p0 context.Context, p1 abi.SectorID) error { return ErrNotSupported } +func (s *WorkerStruct) ReplicaUpdate(p0 context.Context, p1 storage.SectorRef, p2 []abi.PieceInfo) (storiface.CallID, error) { + if s.Internal.ReplicaUpdate == nil { + return *new(storiface.CallID), ErrNotSupported + } + return s.Internal.ReplicaUpdate(p0, p1, p2) +} + +func (s *WorkerStub) ReplicaUpdate(p0 context.Context, p1 storage.SectorRef, p2 []abi.PieceInfo) (storiface.CallID, error) { + return *new(storiface.CallID), ErrNotSupported +} + func (s *WorkerStruct) SealCommit1(p0 context.Context, p1 storage.SectorRef, p2 abi.SealRandomness, p3 abi.InteractiveSealRandomness, p4 []abi.PieceInfo, p5 storage.SectorCids) (storiface.CallID, error) { if s.Internal.SealCommit1 == nil { return *new(storiface.CallID), ErrNotSupported diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 8719b71713e8587d8e7ec8ea03f23b0d6486fd6c..a5816ef4f3d57f10df36cc9e5a911257fb47e0e6 100644 GIT binary patch delta 25088 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 WJUo1P`2PU_0RR7TD+|HU^Z@`4(25@b delta 10388 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 literal 2713 zcmV;K3TE{miwFP!00000|Lk4eZ{s!+|5pg!OHwHQ&X<8c>?Lh4!0tAebgvJa;6h7d zn~g-OB$dPs{J$S4$(CeEw&>VB#}O9rMihsfA?M@A5h=Z5?gJCPjr+LW=rm5Sg((|y z+<(Q2Di?4cf95KX=;rzYeY(EF7JdRDDQ6)?yW8j-Iq-z17WP1mxg&A^`zvO|)1*IB z7i>;hZ_=Uhlhs|zhlFI+2}x`AAaZJ5yY($fvpbFjO@T~A)7M= zFRF17{cj<^jilm&jG%D~w&LOjh8FTW==(hx(8f3B6UTw5fm`|)Sjg|9vOB$bTbD$U zLv)}o>5$maxFD{3b!j0Gf{R1+ddKb*9U|GdVhRK!?p!+bz@{1gJnT^aF$E zTyuvO`bmhdT-^q~&xHa<(@gbGOjgkTf#1?%Yaz8Tn(f0oHoapH4-eSFGVnYiCb*B2 z-lFl;eabtAE$kCPyl8j>p{HmtIr6!r;dI2eGgIidb90s(^-SOT!XAT1v<|@w@q8De z7OyUK(HF`<;C{Q+YFYSe;0^TE`P9PKg7e{T6CZH@YuJK`>blc;2_O6cw!&GV3>x@8YvF!sVF7;zRDgr~ zN(7)M!xvx^rAtELrdBdro!o4dSVN^bV}a}5TbL?{l_DoWwy$Wc5S56a1tGuBXzumg z&dP`oWMVF5H`lYFjO)me8kcsf)4MN_%utM8scC5^RL!c&Ek!d>iKBa6Nd~UcZO6PV z`l~`t7b;Zo0g=yG>IbwjZ7OI^j4 zBORYwDcN_=Q?2cK@@3jmqQG^@?Shg1g{pBdKmt6j0J)SsVhabt#eF&LXHfRoP?16!Gc=nx+NfOjuK`5}XOo-PM2+L(UaI($9S-{!?tmev4O!h5 zqMeOHH8@-2)(?nV%k+MGpl$<*E)Pue7FtQ`ums{#Ho_^Uq!MAtW?*K{KUCw(<4>?Q zQ#I18k>0c1fg&|JJ5SymIX5}}8jf}&7rsu82|3&#`K%fQyJ7J`| z000*Bc)f&`!O;FX97<5t#x~3@tvN7jroZagS;x*ji=Ah!lj7KU#fIE4Vrr7&{LJFR z5M6Uw1l0E{#l56Cqu3X7x|Q@z5pzqNLZ(s`$M7#M)x0YW{LvF}1MQoyMvM!%0m%bl z&(hBpP8Gc3FW_B|Cz9I4#rfCTZRbyOEzTz`|%U%!NZY3DvQ^d7_0HO- z#ct{ge}dZxqZoRt6y;{JfrcnQ)&I62epbX9-|rNV*adw5eiD2&^sb@zzQwf8S#eCe zCTc7VqghB(48Eg9Jjg~I3Ut+FfhlZiNk}Sc&nPU-c-;#8F5<2vuaT>?-Q>mvVYd*Y z#T>-dH#JMecO$Qm!=#_NP27<8qPxEX9gQm`Q#P0)*;QNXo|o8~;5JBk3sOePWn^?2 z;$rIy0_rrreOrzNvkfh=y?JY92Div(vE@aCI=BeJ9PT0A5#mGi97>I3L~o%HFc5l% zLB6tWv<<%4WOOA$UK`?6_5IW;fsh zk?@U4Am)327O4NuXE6(1Z)>HNm#|)~?G*Ohh1FX9G^Sn>)=R>@UJ{Blr| zYNE1eNd`3b`&XBTQ3NawfVz?5xMvdIVpeq5#UX8$3vHrb)mWp*4aK;$oE5FT#Kz6c zcDoi}sP9F-@@wGc_Zi29sf6Dg&ARS8H?Gr8v2p2D`33hps`A>i+`>|nW}q}uO5)yx z>n8?M&X2~0HbZPhpCDJG7ayz(kJm&GQT^kEE-t7e4MA>7jBNqj>_{!{Io4v-KzAo1 z>Mj7?ymjp1QMpn(f7i0+H##qPtgWwF!k#YTjA=Y5p+ja0T{*xM9n!QWCkfO4!x|py2miFrvz1BR<(tpKG?J&u3(i!|kY#`ld>5NY%UD7>KgRXo8&;NtJ{OJc1?)iTV zydg}6-QJLPgULw{K(F)Ei`D>}Y|qeDCY_tjXL=Y+C^reR>IG@NAbro6`K;s+XM*SQ z;kznk?wIep(WNnr{54Q(!`#mHVQ#0+;qIDk?gF&UEAjh-dv%#doSaJ=5KIqCmz0S)!ydFM=Z7XU+{Horg2P)EKx^6gvXYnL1&UvFdm z+jrD&Yb*V#J@lXHBP^T?u+Sh-Xui3g#e1z%JLa_&I8=sj6|8s5f0*6!=be&6&9|V| zdr4+OSOyaZoV!bQ`y~y$b;nw&o}c)88B)Jamo1FvEiYLbuV~(A!JL+)*brtl(9vDcYIOlcFD`iVLU@G~xfxkq zze>VwW>;EEXQtJE4Y$1dMCn1f&g7dKKdekp?Ro0xtmIfuw0(D-Z&sx!*L}6u>_ayH zoG7?r4!o@RbXDPYjbmg}r*T0Y!zV5&{-*@V@x@VjC z#M9n>scO&m&*Trl#NKoD%oJ{N$+mSt9VB%35}4AWNN|ToQJn#0qbN!+g^1$_kP;k3 z=dCr+mC^$+UkX0#{L6-#zk){Rqyy z7Zt8X2y+lYUv#Z8k>f^IaW-?", t) } @@ -104,9 +116,11 @@ func (t SectorFileType) All() [FileTypes]bool { type SectorPaths struct { ID abi.SectorID - Unsealed string - Sealed string - Cache string + Unsealed string + Sealed string + Cache string + Update string + UpdateCache string } func ParseSectorID(baseName string) (abi.SectorID, error) { @@ -139,6 +153,10 @@ func PathByType(sps SectorPaths, fileType SectorFileType) string { return sps.Sealed case FTCache: return sps.Cache + case FTUpdate: + return sps.Update + case FTUpdateCache: + return sps.UpdateCache } panic("requested unknown path type") @@ -152,5 +170,9 @@ func SetPathByType(sps *SectorPaths, fileType SectorFileType, p string) { sps.Sealed = p case FTCache: sps.Cache = p + case FTUpdate: + sps.Update = p + case FTUpdateCache: + sps.UpdateCache = p } } diff --git a/extern/sector-storage/storiface/worker.go b/extern/sector-storage/storiface/worker.go index e3374d6cf..970e0ec33 100644 --- a/extern/sector-storage/storiface/worker.go +++ b/extern/sector-storage/storiface/worker.go @@ -92,6 +92,9 @@ type WorkerCalls interface { SealCommit2(ctx context.Context, sector storage.SectorRef, c1o storage.Commit1Out) (CallID, error) FinalizeSector(ctx context.Context, sector storage.SectorRef, keepUnsealed []storage.Range) (CallID, error) ReleaseUnsealed(ctx context.Context, sector storage.SectorRef, safeToFree []storage.Range) (CallID, error) + ReplicaUpdate(ctx context.Context, sector storage.SectorRef, pieces []abi.PieceInfo) (CallID, error) + ProveReplicaUpdate1(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid) (CallID, error) + ProveReplicaUpdate2(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid, vanillaProofs storage.ReplicaVanillaProofs) (CallID, error) MoveStorage(ctx context.Context, sector storage.SectorRef, types SectorFileType) (CallID, error) UnsealPiece(context.Context, storage.SectorRef, UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (CallID, error) Fetch(context.Context, storage.SectorRef, SectorFileType, PathType, AcquireMode) (CallID, error) @@ -145,6 +148,9 @@ type WorkerReturn interface { ReturnSealCommit2(ctx context.Context, callID CallID, proof storage.Proof, err *CallError) error ReturnFinalizeSector(ctx context.Context, callID CallID, err *CallError) error ReturnReleaseUnsealed(ctx context.Context, callID CallID, err *CallError) error + ReturnReplicaUpdate(ctx context.Context, callID CallID, out storage.ReplicaUpdateOut, err *CallError) error + ReturnProveReplicaUpdate1(ctx context.Context, callID CallID, proofs storage.ReplicaVanillaProofs, err *CallError) error + ReturnProveReplicaUpdate2(ctx context.Context, callID CallID, proof storage.ReplicaUpdateProof, err *CallError) error ReturnMoveStorage(ctx context.Context, callID CallID, err *CallError) error ReturnUnsealPiece(ctx context.Context, callID CallID, err *CallError) error ReturnReadPiece(ctx context.Context, callID CallID, ok bool, err *CallError) error diff --git a/extern/sector-storage/teststorage_test.go b/extern/sector-storage/teststorage_test.go index 72b27b154..4061b48d9 100644 --- a/extern/sector-storage/teststorage_test.go +++ b/extern/sector-storage/teststorage_test.go @@ -55,10 +55,26 @@ func (t *testExec) ReleaseUnsealed(ctx context.Context, sector storage.SectorRef panic("implement me") } +func (t *testExec) ReleaseSealed(ctx context.Context, sector storage.SectorRef) error { + panic("implement me") +} + func (t *testExec) Remove(ctx context.Context, sector storage.SectorRef) error { panic("implement me") } +func (t *testExec) ReplicaUpdate(ctx context.Context, sector storage.SectorRef, pieces []abi.PieceInfo) (storage.ReplicaUpdateOut, error) { + panic("implement me") +} + +func (t *testExec) ProveReplicaUpdate1(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid) (storage.ReplicaVanillaProofs, error) { + panic("implement me") +} + +func (t *testExec) ProveReplicaUpdate2(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid, vanillaProofs storage.ReplicaVanillaProofs) (storage.ReplicaUpdateProof, error) { + panic("implement me") +} + func (t *testExec) NewSector(ctx context.Context, sector storage.SectorRef) error { panic("implement me") } diff --git a/extern/sector-storage/testworker_test.go b/extern/sector-storage/testworker_test.go index 2fe99f3d4..a5c678415 100644 --- a/extern/sector-storage/testworker_test.go +++ b/extern/sector-storage/testworker_test.go @@ -7,6 +7,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/specs-storage/storage" "github.com/google/uuid" + cid "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/extern/sector-storage/mock" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" @@ -67,6 +68,33 @@ func (t *testWorker) AddPiece(ctx context.Context, sector storage.SectorRef, pie }) } +func (t *testWorker) ReplicaUpdate(ctx context.Context, sector storage.SectorRef, pieces []abi.PieceInfo) (storiface.CallID, error) { + return t.asyncCall(sector, func(ci storiface.CallID) { + out, err := t.mockSeal.ReplicaUpdate(ctx, sector, pieces) + if err := t.ret.ReturnReplicaUpdate(ctx, ci, out, toCallError(err)); err != nil { + log.Error(err) + } + }) +} + +func (t *testWorker) ProveReplicaUpdate1(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid) (storiface.CallID, error) { + return t.asyncCall(sector, func(ci storiface.CallID) { + vanillaProofs, err := t.mockSeal.ProveReplicaUpdate1(ctx, sector, sectorKey, newSealed, newUnsealed) + if err := t.ret.ReturnProveReplicaUpdate1(ctx, ci, vanillaProofs, toCallError(err)); err != nil { + log.Error(err) + } + }) +} + +func (t *testWorker) ProveReplicaUpdate2(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid, vanillaProofs storage.ReplicaVanillaProofs) (storiface.CallID, error) { + return t.asyncCall(sector, func(ci storiface.CallID) { + proof, err := t.mockSeal.ProveReplicaUpdate2(ctx, sector, sectorKey, newSealed, newUnsealed, vanillaProofs) + if err := t.ret.ReturnProveReplicaUpdate2(ctx, ci, proof, toCallError(err)); err != nil { + log.Error(err) + } + }) +} + func (t *testWorker) SealPreCommit1(ctx context.Context, sector storage.SectorRef, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) { return t.asyncCall(sector, func(ci storiface.CallID) { t.pc1s++ diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index d45d140f8..cc41e916e 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -28,7 +28,7 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) -var pathTypes = []storiface.SectorFileType{storiface.FTUnsealed, storiface.FTSealed, storiface.FTCache} +var pathTypes = []storiface.SectorFileType{storiface.FTUnsealed, storiface.FTSealed, storiface.FTCache, storiface.FTUpdate, storiface.FTUpdateCache} type WorkerConfig struct { TaskTypes []sealtasks.TaskType @@ -145,7 +145,6 @@ func (l *localWorkerPathProvider) AcquireSector(ctx context.Context, sector stor } sid := storiface.PathByType(storageIDs, fileType) - if err := l.w.sindex.StorageDeclareSector(ctx, stores.ID(sid), sector.ID, fileType, l.op == storiface.AcquireMove); err != nil { log.Errorf("declare sector error: %+v", err) } @@ -160,16 +159,19 @@ func (l *LocalWorker) ffiExec() (ffiwrapper.Storage, error) { type ReturnType string const ( - AddPiece ReturnType = "AddPiece" - SealPreCommit1 ReturnType = "SealPreCommit1" - SealPreCommit2 ReturnType = "SealPreCommit2" - SealCommit1 ReturnType = "SealCommit1" - SealCommit2 ReturnType = "SealCommit2" - FinalizeSector ReturnType = "FinalizeSector" - ReleaseUnsealed ReturnType = "ReleaseUnsealed" - MoveStorage ReturnType = "MoveStorage" - UnsealPiece ReturnType = "UnsealPiece" - Fetch ReturnType = "Fetch" + AddPiece ReturnType = "AddPiece" + SealPreCommit1 ReturnType = "SealPreCommit1" + SealPreCommit2 ReturnType = "SealPreCommit2" + SealCommit1 ReturnType = "SealCommit1" + SealCommit2 ReturnType = "SealCommit2" + FinalizeSector ReturnType = "FinalizeSector" + ReplicaUpdate ReturnType = "ReplicaUpdate" + ProveReplicaUpdate1 ReturnType = "ProveReplicaUpdate1" + ProveReplicaUpdate2 ReturnType = "ProveReplicaUpdate2" + ReleaseUnsealed ReturnType = "ReleaseUnsealed" + MoveStorage ReturnType = "MoveStorage" + UnsealPiece ReturnType = "UnsealPiece" + Fetch ReturnType = "Fetch" ) // in: func(WorkerReturn, context.Context, CallID, err string) @@ -207,16 +209,19 @@ func rfunc(in interface{}) func(context.Context, storiface.CallID, storiface.Wor } var returnFunc = map[ReturnType]func(context.Context, storiface.CallID, storiface.WorkerReturn, interface{}, *storiface.CallError) error{ - AddPiece: rfunc(storiface.WorkerReturn.ReturnAddPiece), - SealPreCommit1: rfunc(storiface.WorkerReturn.ReturnSealPreCommit1), - SealPreCommit2: rfunc(storiface.WorkerReturn.ReturnSealPreCommit2), - SealCommit1: rfunc(storiface.WorkerReturn.ReturnSealCommit1), - SealCommit2: rfunc(storiface.WorkerReturn.ReturnSealCommit2), - FinalizeSector: rfunc(storiface.WorkerReturn.ReturnFinalizeSector), - ReleaseUnsealed: rfunc(storiface.WorkerReturn.ReturnReleaseUnsealed), - MoveStorage: rfunc(storiface.WorkerReturn.ReturnMoveStorage), - UnsealPiece: rfunc(storiface.WorkerReturn.ReturnUnsealPiece), - Fetch: rfunc(storiface.WorkerReturn.ReturnFetch), + AddPiece: rfunc(storiface.WorkerReturn.ReturnAddPiece), + SealPreCommit1: rfunc(storiface.WorkerReturn.ReturnSealPreCommit1), + SealPreCommit2: rfunc(storiface.WorkerReturn.ReturnSealPreCommit2), + SealCommit1: rfunc(storiface.WorkerReturn.ReturnSealCommit1), + SealCommit2: rfunc(storiface.WorkerReturn.ReturnSealCommit2), + FinalizeSector: rfunc(storiface.WorkerReturn.ReturnFinalizeSector), + ReleaseUnsealed: rfunc(storiface.WorkerReturn.ReturnReleaseUnsealed), + ReplicaUpdate: rfunc(storiface.WorkerReturn.ReturnReplicaUpdate), + ProveReplicaUpdate1: rfunc(storiface.WorkerReturn.ReturnProveReplicaUpdate1), + ProveReplicaUpdate2: rfunc(storiface.WorkerReturn.ReturnProveReplicaUpdate2), + MoveStorage: rfunc(storiface.WorkerReturn.ReturnMoveStorage), + UnsealPiece: rfunc(storiface.WorkerReturn.ReturnUnsealPiece), + Fetch: rfunc(storiface.WorkerReturn.ReturnFetch), } func (l *LocalWorker) asyncCall(ctx context.Context, sector storage.SectorRef, rt ReturnType, work func(ctx context.Context, ci storiface.CallID) (interface{}, error)) (storiface.CallID, error) { @@ -240,7 +245,6 @@ func (l *LocalWorker) asyncCall(ctx context.Context, sector storage.SectorRef, r } res, err := work(ctx, ci) - if err != nil { rb, err := json.Marshal(res) if err != nil { @@ -258,7 +262,6 @@ func (l *LocalWorker) asyncCall(ctx context.Context, sector storage.SectorRef, r } } }() - return ci, nil } @@ -382,6 +385,40 @@ func (l *LocalWorker) SealCommit2(ctx context.Context, sector storage.SectorRef, }) } +func (l *LocalWorker) ReplicaUpdate(ctx context.Context, sector storage.SectorRef, pieces []abi.PieceInfo) (storiface.CallID, error) { + sb, err := l.executor() + if err != nil { + return storiface.UndefCall, err + } + + return l.asyncCall(ctx, sector, ReplicaUpdate, func(ctx context.Context, ci storiface.CallID) (interface{}, error) { + sealerOut, err := sb.ReplicaUpdate(ctx, sector, pieces) + return sealerOut, err + }) +} + +func (l *LocalWorker) ProveReplicaUpdate1(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid) (storiface.CallID, error) { + sb, err := l.executor() + if err != nil { + return storiface.UndefCall, err + } + + return l.asyncCall(ctx, sector, ProveReplicaUpdate1, func(ctx context.Context, ci storiface.CallID) (interface{}, error) { + return sb.ProveReplicaUpdate1(ctx, sector, sectorKey, newSealed, newUnsealed) + }) +} + +func (l *LocalWorker) ProveReplicaUpdate2(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid, vanillaProofs storage.ReplicaVanillaProofs) (storiface.CallID, error) { + sb, err := l.executor() + if err != nil { + return storiface.UndefCall, err + } + + return l.asyncCall(ctx, sector, ProveReplicaUpdate2, func(ctx context.Context, ci storiface.CallID) (interface{}, error) { + return sb.ProveReplicaUpdate2(ctx, sector, sectorKey, newSealed, newUnsealed, vanillaProofs) + }) +} + func (l *LocalWorker) FinalizeSector(ctx context.Context, sector storage.SectorRef, keepUnsealed []storage.Range) (storiface.CallID, error) { sb, err := l.executor() if err != nil { diff --git a/extern/sector-storage/worker_tracked.go b/extern/sector-storage/worker_tracked.go index 5702426c3..b87abed06 100644 --- a/extern/sector-storage/worker_tracked.go +++ b/extern/sector-storage/worker_tracked.go @@ -98,7 +98,6 @@ func (wt *workTracker) track(ctx context.Context, ready chan struct{}, wid Worke wt.lk.Lock() delete(wt.prepared, prepID) } - callID, err := cb() if err != nil { return callID, err @@ -198,4 +197,22 @@ func (t *trackedWorker) UnsealPiece(ctx context.Context, id storage.SectorRef, i return t.tracker.track(ctx, t.execute, t.wid, t.workerInfo, id, sealtasks.TTUnseal, func() (storiface.CallID, error) { return t.Worker.UnsealPiece(ctx, id, index, size, randomness, cid) }) } +func (t *trackedWorker) ReplicaUpdate(ctx context.Context, sector storage.SectorRef, pieces []abi.PieceInfo) (storiface.CallID, error) { + return t.tracker.track(ctx, t.execute, t.wid, t.workerInfo, sector, sealtasks.TTReplicaUpdate, func() (storiface.CallID, error) { + return t.Worker.ReplicaUpdate(ctx, sector, pieces) + }) +} + +func (t *trackedWorker) ProveReplicaUpdate1(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid) (storiface.CallID, error) { + return t.tracker.track(ctx, t.execute, t.wid, t.workerInfo, sector, sealtasks.TTProveReplicaUpdate1, func() (storiface.CallID, error) { + return t.Worker.ProveReplicaUpdate1(ctx, sector, sectorKey, newSealed, newUnsealed) + }) +} + +func (t *trackedWorker) ProveReplicaUpdate2(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid, vanillaProofs storage.ReplicaVanillaProofs) (storiface.CallID, error) { + return t.tracker.track(ctx, t.execute, t.wid, t.workerInfo, sector, sealtasks.TTProveReplicaUpdate2, func() (storiface.CallID, error) { + return t.Worker.ProveReplicaUpdate2(ctx, sector, sectorKey, newSealed, newUnsealed, vanillaProofs) + }) +} + var _ Worker = &trackedWorker{} diff --git a/go.mod b/go.mod index ce52b7975..e0823094d 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/filecoin-project/specs-actors/v5 v5.0.4 github.com/filecoin-project/specs-actors/v6 v6.0.1 github.com/filecoin-project/specs-actors/v7 v7.0.0-20211118013026-3dce48197cec - github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 + github.com/filecoin-project/specs-storage v0.1.1-0.20211123153428-712cb8da07a3 github.com/filecoin-project/test-vectors/schema v0.0.5 github.com/gbrlsnchs/jwt/v3 v3.0.1 github.com/gdamore/tcell/v2 v2.2.0 @@ -156,7 +156,7 @@ require ( golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac - golang.org/x/tools v0.1.5 + golang.org/x/tools v0.1.7 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 gopkg.in/cheggaaa/pb.v1 v1.0.28 gotest.tools v2.2.0+incompatible diff --git a/go.sum b/go.sum index 06341ce01..e404ca72e 100644 --- a/go.sum +++ b/go.sum @@ -396,8 +396,8 @@ github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVi github.com/filecoin-project/specs-actors/v7 v7.0.0-20211117170924-fd07a4c7dff9/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-actors/v7 v7.0.0-20211118013026-3dce48197cec h1:KV9vE+Sl2Y3qKsrpba4HcE7wHwK7v6O5U/S0xHbje6A= github.com/filecoin-project/specs-actors/v7 v7.0.0-20211118013026-3dce48197cec/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= -github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506 h1:Ur/l2+6qN+lQiqjozWWc5p9UDaAMDZKTlDS98oRnlIw= -github.com/filecoin-project/specs-storage v0.1.1-0.20201105051918-5188d9774506/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= +github.com/filecoin-project/specs-storage v0.1.1-0.20211123153428-712cb8da07a3 h1:FLPxD2ksWwGc/sbnFLWep2p8ViP93VCAwFaVxrtVCyo= +github.com/filecoin-project/specs-storage v0.1.1-0.20211123153428-712cb8da07a3/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -1872,6 +1872,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.12.1 h1:hYRcyznPRJp+5mzF2sazTLP2nGvGjYDD2VzhHhFomLU= @@ -2104,6 +2105,7 @@ golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf h1:R150MpwJIv1MpS0N/pc+NhTM8ajzvlmxlY5OYsrevXQ= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -2227,6 +2229,7 @@ golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 h1:J27LZFQBFoihqXoegpscI10HpjZ7B5WQLLKL2FZXQKw= golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2318,8 +2321,9 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1-0.20210225150353-54dc8c5edb56/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From e16e9ad34393c5c97f18d895749ffc3a1c70a8c8 Mon Sep 17 00:00:00 2001 From: c r Date: Mon, 29 Nov 2021 17:26:47 -0500 Subject: [PATCH 08/12] reorder `transfer` checks so as to ensure sending more money than you have to yourself fails with an error (fixing issue 7596) PR #7637, also adds tests to make sure behavior is correct across versions. --- .circleci/config.yml | 5 ++ chain/vm/runtime.go | 2 +- chain/vm/vm.go | 93 ++++++++++++++++++++++---------- itests/self_sent_txn_test.go | 102 +++++++++++++++++++++++++++++++++++ 4 files changed, 174 insertions(+), 28 deletions(-) create mode 100644 itests/self_sent_txn_test.go diff --git a/.circleci/config.yml b/.circleci/config.yml index 30f2d5c01..d747e2cab 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -890,6 +890,11 @@ workflows: suite: itest-sector_terminate target: "./itests/sector_terminate_test.go" + - test: + name: test-itest-self_sent_txn + suite: itest-self_sent_txn + target: "./itests/self_sent_txn_test.go" + - test: name: test-itest-tape suite: itest-tape diff --git a/chain/vm/runtime.go b/chain/vm/runtime.go index 0dbe98224..548b09028 100644 --- a/chain/vm/runtime.go +++ b/chain/vm/runtime.go @@ -332,7 +332,7 @@ func (rt *Runtime) DeleteActor(beneficiary address.Address) { } // Transfer the executing actor's balance to the beneficiary - if err := rt.vm.transfer(rt.Receiver(), beneficiary, act.Balance); err != nil { + if err := rt.vm.transfer(rt.Receiver(), beneficiary, act.Balance, rt.NetworkVersion()); err != nil { panic(aerrors.Fatalf("failed to transfer balance to beneficiary actor: %s", err)) } } diff --git a/chain/vm/vm.go b/chain/vm/vm.go index 36308fe03..16ad5e2a4 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -339,7 +339,7 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime, defer rt.chargeGasSafe(newGasCharge("OnMethodInvocationDone", 0, 0)) if types.BigCmp(msg.Value, types.NewInt(0)) != 0 { - if err := vm.transfer(msg.From, msg.To, msg.Value); err != nil { + if err := vm.transfer(msg.From, msg.To, msg.Value, vm.ntwkVersion(ctx, vm.blockHeight)); err != nil { return nil, aerrors.Wrap(err, "failed to transfer funds") } } @@ -869,32 +869,71 @@ func (vm *VM) incrementNonce(addr address.Address) error { }) } -func (vm *VM) transfer(from, to address.Address, amt types.BigInt) aerrors.ActorError { - if from == to { - return nil - } +func (vm *VM) transfer(from, to address.Address, amt types.BigInt, networkVersion network.Version) aerrors.ActorError { + var f *types.Actor + var fromID, toID address.Address + var err error + // switching the order around so that transactions for more than the balance sent to self fail + if networkVersion >= network.Version15 { + if amt.LessThan(types.NewInt(0)) { + return aerrors.Newf(exitcode.SysErrForbidden, "attempted to transfer negative value: %s", amt) + } - fromID, err := vm.cstate.LookupID(from) - if err != nil { - return aerrors.Fatalf("transfer failed when resolving sender address: %s", err) - } + fromID, err = vm.cstate.LookupID(from) + if err != nil { + return aerrors.Fatalf("transfer failed when resolving sender address: %s", err) + } - toID, err := vm.cstate.LookupID(to) - if err != nil { - return aerrors.Fatalf("transfer failed when resolving receiver address: %s", err) - } + f, err = vm.cstate.GetActor(fromID) + if err != nil { + return aerrors.Fatalf("transfer failed when retrieving sender actor: %s", err) + } - if fromID == toID { - return nil - } + if f.Balance.LessThan(amt) { + return aerrors.Newf(exitcode.SysErrInsufficientFunds, "transfer failed, insufficient balance in sender actor: %v", f.Balance) + } - if amt.LessThan(types.NewInt(0)) { - return aerrors.Newf(exitcode.SysErrForbidden, "attempted to transfer negative value: %s", amt) - } + if from == to { + log.Infow("sending to same address: noop", "from/to addr", from) + return nil + } - f, err := vm.cstate.GetActor(fromID) - if err != nil { - return aerrors.Fatalf("transfer failed when retrieving sender actor: %s", err) + toID, err = vm.cstate.LookupID(to) + if err != nil { + return aerrors.Fatalf("transfer failed when resolving receiver address: %s", err) + } + + if fromID == toID { + log.Infow("sending to same actor ID: noop", "from/to actor", fromID) + return nil + } + } else { + if from == to { + return nil + } + + fromID, err = vm.cstate.LookupID(from) + if err != nil { + return aerrors.Fatalf("transfer failed when resolving sender address: %s", err) + } + + toID, err = vm.cstate.LookupID(to) + if err != nil { + return aerrors.Fatalf("transfer failed when resolving receiver address: %s", err) + } + + if fromID == toID { + return nil + } + + if amt.LessThan(types.NewInt(0)) { + return aerrors.Newf(exitcode.SysErrForbidden, "attempted to transfer negative value: %s", amt) + } + + f, err = vm.cstate.GetActor(fromID) + if err != nil { + return aerrors.Fatalf("transfer failed when retrieving sender actor: %s", err) + } } t, err := vm.cstate.GetActor(toID) @@ -902,17 +941,17 @@ func (vm *VM) transfer(from, to address.Address, amt types.BigInt) aerrors.Actor return aerrors.Fatalf("transfer failed when retrieving receiver actor: %s", err) } - if err := deductFunds(f, amt); err != nil { + if err = deductFunds(f, amt); err != nil { return aerrors.Newf(exitcode.SysErrInsufficientFunds, "transfer failed when deducting funds (%s): %s", types.FIL(amt), err) } depositFunds(t, amt) - if err := vm.cstate.SetActor(fromID, f); err != nil { - return aerrors.Fatalf("transfer failed when setting receiver actor: %s", err) + if err = vm.cstate.SetActor(fromID, f); err != nil { + return aerrors.Fatalf("transfer failed when setting sender actor: %s", err) } - if err := vm.cstate.SetActor(toID, t); err != nil { - return aerrors.Fatalf("transfer failed when setting sender actor: %s", err) + if err = vm.cstate.SetActor(toID, t); err != nil { + return aerrors.Fatalf("transfer failed when setting receiver actor: %s", err) } return nil diff --git a/itests/self_sent_txn_test.go b/itests/self_sent_txn_test.go new file mode 100644 index 000000000..846bcff05 --- /dev/null +++ b/itests/self_sent_txn_test.go @@ -0,0 +1,102 @@ +package itests + +import ( + "context" + "testing" + "time" + + "github.com/filecoin-project/go-state-types/network" + + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/go-state-types/exitcode" + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/itests/kit" + "github.com/stretchr/testify/require" +) + + +// these tests check that the versioned code in vm.transfer is functioning correctly across versions! +// we reordered the checks to make sure that a transaction with too much money in it sent to yourself will fail instead of succeeding as a noop +// more info in this PR! https://github.com/filecoin-project/lotus/pull/7637 +func TestSelfSentTxnV15(t *testing.T) { + ctx := context.Background() + + kit.QuietMiningLogs() + + client15, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.GenesisNetworkVersion(network.Version15)) + ens.InterconnectAll().BeginMining(10 * time.Millisecond) + + bal, err := client15.WalletBalance(ctx, client15.DefaultKey.Address) + require.NoError(t, err) + + // send self half of account balance + msgHalfBal := &types.Message{ + From: client15.DefaultKey.Address, + To: client15.DefaultKey.Address, + Value: big.Div(bal, big.NewInt(2)), + } + smHalfBal, err := client15.MpoolPushMessage(ctx, msgHalfBal, nil) + require.NoError(t, err) + mLookup, err := client15.StateWaitMsg(ctx, smHalfBal.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) + + msgOverBal := &types.Message{ + From: client15.DefaultKey.Address, + To: client15.DefaultKey.Address, + Value: big.Mul(big.NewInt(2), bal), + GasLimit: 10000000000, + GasPremium: big.NewInt(10000000000), + GasFeeCap: big.NewInt(100000000000), + Nonce: 1, + } + smOverBal, err := client15.WalletSignMessage(ctx, client15.DefaultKey.Address, msgOverBal) + require.NoError(t, err) + smcid, err := client15.MpoolPush(ctx, smOverBal) + require.NoError(t, err) + mLookup, err = client15.StateWaitMsg(ctx, smcid, 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, exitcode.SysErrInsufficientFunds, mLookup.Receipt.ExitCode) +} + +func TestSelfSentTxnV14(t *testing.T) { + ctx := context.Background() + + kit.QuietMiningLogs() + + client14, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.GenesisNetworkVersion(network.Version14)) + ens.InterconnectAll().BeginMining(10 * time.Millisecond) + + bal, err := client14.WalletBalance(ctx, client14.DefaultKey.Address) + require.NoError(t, err) + + // send self half of account balance + msgHalfBal := &types.Message{ + From: client14.DefaultKey.Address, + To: client14.DefaultKey.Address, + Value: big.Div(bal, big.NewInt(2)), + } + smHalfBal, err := client14.MpoolPushMessage(ctx, msgHalfBal, nil) + require.NoError(t, err) + mLookup, err := client14.StateWaitMsg(ctx, smHalfBal.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) + + msgOverBal := &types.Message{ + From: client14.DefaultKey.Address, + To: client14.DefaultKey.Address, + Value: big.Mul(big.NewInt(2), bal), + GasLimit: 10000000000, + GasPremium: big.NewInt(10000000000), + GasFeeCap: big.NewInt(100000000000), + Nonce: 1, + } + smOverBal, err := client14.WalletSignMessage(ctx, client14.DefaultKey.Address, msgOverBal) + require.NoError(t, err) + smcid, err := client14.MpoolPush(ctx, smOverBal) + require.NoError(t, err) + mLookup, err = client14.StateWaitMsg(ctx, smcid, 3, api.LookbackNoLimit, true) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) +} From f88fcdbcfc5c238f8bc6545a39c78c2e9a1df7d4 Mon Sep 17 00:00:00 2001 From: zenground0 Date: Tue, 30 Nov 2021 12:40:14 -0500 Subject: [PATCH 09/12] WIP --- extern/sector-storage/ffiwrapper/sealer_cgo.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extern/sector-storage/ffiwrapper/sealer_cgo.go b/extern/sector-storage/ffiwrapper/sealer_cgo.go index 81dbfb426..b9fad3a04 100644 --- a/extern/sector-storage/ffiwrapper/sealer_cgo.go +++ b/extern/sector-storage/ffiwrapper/sealer_cgo.go @@ -628,9 +628,9 @@ func (sb *Sealer) ReplicaUpdate(ctx context.Context, sector storage.SectorRef, p } // XXX: we want to keep the stuff at the end - if err := os.Truncate(paths.Unsealed, sealedSize); err != nil { - return empty, xerrors.Errorf("failed to truncate unsealed data file: %w", err) - } + // if err := os.Truncate(paths.Unsealed, sealedSize); err != nil { + // return empty, xerrors.Errorf("failed to truncate unsealed data file: %w", err) + // } sealed, unsealed, err := ffi.SectorUpdate.EncodeInto(updateProofType, paths.Update, paths.UpdateCache, paths.Sealed, paths.Cache, paths.Unsealed, pieces) if err != nil { From 40d16a8f880395c7ce2b8cc62a2e4605e95e2c5d Mon Sep 17 00:00:00 2001 From: zenground0 Date: Tue, 30 Nov 2021 13:53:37 -0500 Subject: [PATCH 10/12] Review Response --- extern/filecoin-ffi | 2 +- extern/sector-storage/ffiwrapper/sealer_cgo.go | 6 +++--- extern/sector-storage/manager_test.go | 15 ++++++++++----- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index b1a66cfd1..ce7083b3d 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit b1a66cfd12686a8af6030fccace49916849b1954 +Subproject commit ce7083b3d187ec3bc41a68ab66567bd4f3be6dfc diff --git a/extern/sector-storage/ffiwrapper/sealer_cgo.go b/extern/sector-storage/ffiwrapper/sealer_cgo.go index b9fad3a04..81dbfb426 100644 --- a/extern/sector-storage/ffiwrapper/sealer_cgo.go +++ b/extern/sector-storage/ffiwrapper/sealer_cgo.go @@ -628,9 +628,9 @@ func (sb *Sealer) ReplicaUpdate(ctx context.Context, sector storage.SectorRef, p } // XXX: we want to keep the stuff at the end - // if err := os.Truncate(paths.Unsealed, sealedSize); err != nil { - // return empty, xerrors.Errorf("failed to truncate unsealed data file: %w", err) - // } + if err := os.Truncate(paths.Unsealed, sealedSize); err != nil { + return empty, xerrors.Errorf("failed to truncate unsealed data file: %w", err) + } sealed, unsealed, err := ffi.SectorUpdate.EncodeInto(updateProofType, paths.Update, paths.UpdateCache, paths.Sealed, paths.Cache, paths.Unsealed, pieces) if err != nil { diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index e4ca35560..77e185b93 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -68,11 +68,16 @@ func newTestStorage(t *testing.T) *testStorage { } func (t testStorage) cleanup() { - // for _, path := range t.StoragePaths { - // if err := os.RemoveAll(path.Path); err != nil { - // fmt.Println("Cleanup error:", err) - // } - // } + noCleanup := os.Getenv("LOTUS_TEST_NO_CLEANUP") != "" + for _, path := range t.StoragePaths { + if noCleanup { + fmt.Printf("Not cleaning up test storage at %s\n", path) + continue + } + if err := os.RemoveAll(path.Path); err != nil { + fmt.Println("Cleanup error:", err) + } + } } func (t testStorage) GetStorage() (stores.StorageConfig, error) { From a5be80828a28908b665b9f5b5a647b084c2bc6ba Mon Sep 17 00:00:00 2001 From: zenground0 Date: Wed, 1 Dec 2021 14:01:55 -0500 Subject: [PATCH 11/12] RemoveData and Decode - Unsealing replica update with sector key works and tested - Sector key generation added and tested --- api/api_storage.go | 1 + api/api_worker.go | 1 + api/proxy_gen.go | 26 +++++++ build/openrpc/full.json.gz | Bin 25466 -> 25465 bytes build/openrpc/miner.json.gz | Bin 10672 -> 10724 bytes build/openrpc/worker.json.gz | Bin 2940 -> 3000 bytes documentation/en/api-v0-methods-miner.md | 25 ++++++ documentation/en/api-v0-methods-worker.md | 37 +++++++++ extern/filecoin-ffi | 2 +- .../sector-storage/ffiwrapper/sealer_cgo.go | 60 ++++++++++++-- extern/sector-storage/manager.go | 73 +++++++++++++++++- extern/sector-storage/manager_test.go | 36 ++++++--- extern/sector-storage/mock/mock.go | 8 ++ extern/sector-storage/sched_test.go | 4 + extern/sector-storage/sealtasks/task.go | 5 +- extern/sector-storage/storiface/worker.go | 2 + extern/sector-storage/teststorage_test.go | 4 + extern/sector-storage/worker_local.go | 13 ++++ go.mod | 2 +- go.sum | 4 +- itests/self_sent_txn_test.go | 3 +- 21 files changed, 281 insertions(+), 25 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index bf7520d09..92117d2fb 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -127,6 +127,7 @@ type StorageMiner interface { ReturnReplicaUpdate(ctx context.Context, callID storiface.CallID, out storage.ReplicaUpdateOut, err *storiface.CallError) error //perm:admin retry:true ReturnProveReplicaUpdate1(ctx context.Context, callID storiface.CallID, vanillaProofs storage.ReplicaVanillaProofs, err *storiface.CallError) error //perm:admin retry:true ReturnProveReplicaUpdate2(ctx context.Context, callID storiface.CallID, proof storage.ReplicaUpdateProof, err *storiface.CallError) error //perm:admin retry:true + ReturnGenerateSectorKeyFromData(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true ReturnReleaseUnsealed(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true ReturnMoveStorage(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true ReturnUnsealPiece(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true diff --git a/api/api_worker.go b/api/api_worker.go index 5e0b4f8c6..68d8e7baf 100644 --- a/api/api_worker.go +++ b/api/api_worker.go @@ -42,6 +42,7 @@ type Worker interface { ReplicaUpdate(ctx context.Context, sector storage.SectorRef, pieces []abi.PieceInfo) (storiface.CallID, error) //perm:admin ProveReplicaUpdate1(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid) (storiface.CallID, error) //perm:admin ProveReplicaUpdate2(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid, vanillaProofs storage.ReplicaVanillaProofs) (storiface.CallID, error) //perm:admin + GenerateSectorKeyFromData(ctx context.Context, sector storage.SectorRef, commD cid.Cid) (storiface.CallID, error) //perm:admin ReleaseUnsealed(ctx context.Context, sector storage.SectorRef, safeToFree []storage.Range) (storiface.CallID, error) //perm:admin MoveStorage(ctx context.Context, sector storage.SectorRef, types storiface.SectorFileType) (storiface.CallID, error) //perm:admin UnsealPiece(context.Context, storage.SectorRef, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (storiface.CallID, error) //perm:admin diff --git a/api/proxy_gen.go b/api/proxy_gen.go index b78b40959..5733c3cc8 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -707,6 +707,8 @@ type StorageMinerStruct struct { ReturnFinalizeSector func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnGenerateSectorKeyFromData func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnMoveStorage func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` ReturnProveReplicaUpdate1 func(p0 context.Context, p1 storiface.CallID, p2 storage.ReplicaVanillaProofs, p3 *storiface.CallError) error `perm:"admin"` @@ -850,6 +852,8 @@ type WorkerStruct struct { FinalizeSector func(p0 context.Context, p1 storage.SectorRef, p2 []storage.Range) (storiface.CallID, error) `perm:"admin"` + GenerateSectorKeyFromData func(p0 context.Context, p1 storage.SectorRef, p2 cid.Cid) (storiface.CallID, error) `perm:"admin"` + Info func(p0 context.Context) (storiface.WorkerInfo, error) `perm:"admin"` MoveStorage func(p0 context.Context, p1 storage.SectorRef, p2 storiface.SectorFileType) (storiface.CallID, error) `perm:"admin"` @@ -4166,6 +4170,17 @@ func (s *StorageMinerStub) ReturnFinalizeSector(p0 context.Context, p1 storiface return ErrNotSupported } +func (s *StorageMinerStruct) ReturnGenerateSectorKeyFromData(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error { + if s.Internal.ReturnGenerateSectorKeyFromData == nil { + return ErrNotSupported + } + return s.Internal.ReturnGenerateSectorKeyFromData(p0, p1, p2) +} + +func (s *StorageMinerStub) ReturnGenerateSectorKeyFromData(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error { + return ErrNotSupported +} + func (s *StorageMinerStruct) ReturnMoveStorage(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error { if s.Internal.ReturnMoveStorage == nil { return ErrNotSupported @@ -4859,6 +4874,17 @@ func (s *WorkerStub) FinalizeSector(p0 context.Context, p1 storage.SectorRef, p2 return *new(storiface.CallID), ErrNotSupported } +func (s *WorkerStruct) GenerateSectorKeyFromData(p0 context.Context, p1 storage.SectorRef, p2 cid.Cid) (storiface.CallID, error) { + if s.Internal.GenerateSectorKeyFromData == nil { + return *new(storiface.CallID), ErrNotSupported + } + return s.Internal.GenerateSectorKeyFromData(p0, p1, p2) +} + +func (s *WorkerStub) GenerateSectorKeyFromData(p0 context.Context, p1 storage.SectorRef, p2 cid.Cid) (storiface.CallID, error) { + return *new(storiface.CallID), ErrNotSupported +} + func (s *WorkerStruct) Info(p0 context.Context) (storiface.WorkerInfo, error) { if s.Internal.Info == nil { return *new(storiface.WorkerInfo), ErrNotSupported diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index a5816ef4f3d57f10df36cc9e5a911257fb47e0e6..839e95e61f36b78820c1705ba99bb12de914ce52 100644 GIT binary patch delta 24891 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 diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 0c176bbef0d3f369e719e67fffeed4443dd180b3..f0eaa49ec9bd976dc3f27084730e55661bfeaf14 100644 GIT binary patch delta 10012 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 delta 9959 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 literal 2940 zcmV-?3xo6@iwFP!00000|Lk3FZ`-!k|0)EZH_f2fj_stWfxYOHZo2{6E;m`W7fo^5$&wt=v3ebc7|_KO4|xuG{``1EQjeI2z(nZc0X}MVTPN7T zl#MtZJYq$a4|sq-aurE*d2xo`Uz}qH--D2pvzX$j*Xka6aF1sW4nR$~C-LCRBW5Jf zq`y)hTuxc*z2{v}Z~;5m1L+DHs-%gpU%!s|4I4$wMQPdgm z)(4`<0eYi<(h+f?bw+&u{DXr)2rdrL;|;q}bcAH~9Y%Qb~Mzeiz!)7<^>({T?!7>U0 zBBpqNm%Sz9sr!^S3_Ca^f&|I%MnX@~aC#VWN#p5AALphpJSxmtVbpVd>mTj}0-|*Y zzL6mGA!+gagD(0+83;T$>U25|{u~8E{p;P#!54z_(I3+g@ZfZI>tNz}Fh1bQ+;0WMLxBo=PwEN81*n5_zHs5NIS^8H%}Qw6C~6eP&^m5ddl5)rf_ zyDQ~O(s+7}}3Uz!y;xpFz0d35<^EUbKu;icle|RG=kt*|JE!BO}I|St0dD7s~ ziGu^mGQZNwiH^^ljO@GTsWx^!#WHOvN#Odx-I9_1jjBmBL;?b?0Qr>NVFyRT#{)c3 zDwKnEdmLA3xjbl(QV4Mv3a=R6zo_YeuotdM-FM}x^eZTLVyH+ljTxF`OUqBz;rH+#08lt5nA^{EJJq=t={BbWi+9`{wg8 z;{q;0@<_Pz^s|FA1&{a>1Q(O3q%QICpxv)9U(wYmOS73D2N96{xP8Yectx1r~ zjCE7})01wwoBG7>;VQu>hTbYext(mFAh^rrJmdc+dUZH?VKXRA&G4Ewh{{lLm)JmpoF-5YgwszXDurVfhx7#*$ z5~J?IsxH;&rx$Ut(J+P1Jz$ECXo-hAqaG5vdkIWwHz&a#9VT^#l#LSuWC{__6Cfpc zh%Q=dp>w63!$e>gKXxnq+%dzRdJ z*Ey++go^>(6bW~?ii8~$9xo``9xxh)akMxtfMeO;i;v$&jXg|NO&2 z5&_Etpl+l*?wQ25loj1|c}Sb@{cWS))da-Wu7=9WS<~7pY~0Ljo3#K#eJ}HspCi9` zuSQy!S-38CZ}|QTH?CgAtr@ulsj-b^Xg9eNF1{HmKCoj7Ofwxf2TSwPSx~wQw!dSb zG^fRlgVMOCvvdRKx};iR|EGnh7NS~+`s^rrTyeR?6%hZ72LV;4TNyKyW)U=jcErDo zcil3Oa&e(*9KwjJ=sgr_^jAY~?hS9!#ToTX-|J??Xeu7(N6Nm(wUK#EWG-6A9$v6o zY3DCm*5V6B3$vd40&wZqYkIB4%ZkBvUTBQ=vXCvRfMZR|x zx3X<^9ozHoVQcCFwx@1h`$+F#>X>b<&L%E zPN(9IwJT7YeOhrzSOpV@ocn9`%r6^w?!NgPD{J=7FFOo~xRXdtU~UyeB1oRK=ho3e zpSeP6Li9gWA_+=SHojp2nIc8*01-5T2PDDe%#%oQq}@9i69xK*BJvJtb@w8Fi#zpy z%r_nFR``#{oui7|Skgln?>#TROV!kH^3>IfEJ4|Lo&Dt7dA1Q1*s8Xqt*waSoKU^b z>Se!LvCS)^UY%BVD^4H(LFCoV9aXwtI+O##R0wf zoS1$DU_n>D1P(~}r8x1oGNyir`T3)j>exiA!1#?!CazmKcK!-O`r_%$JTzCKM zh42$n6lUb<`gIa+bGy=7IybGsW4z@xBuWp;MK0ge`sv98)n2ELjyoq6$8wVGyYV|s zL+i;g;cK#Qk>faFsWvG%1x>BXAOnxoMo}2s1_Ft}k%dUn#ckd*Mn4&&X6A*xi0K}5F mbP|b(vH0EIGd1?rC8OT;@N9NF`)>dM0RR8#PS8G&m;eBTe!1}g diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index c037a0af6..a498cddff 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -94,6 +94,7 @@ * [ReturnAddPiece](#ReturnAddPiece) * [ReturnFetch](#ReturnFetch) * [ReturnFinalizeSector](#ReturnFinalizeSector) + * [ReturnGenerateSectorKeyFromData](#ReturnGenerateSectorKeyFromData) * [ReturnMoveStorage](#ReturnMoveStorage) * [ReturnProveReplicaUpdate1](#ReturnProveReplicaUpdate1) * [ReturnProveReplicaUpdate2](#ReturnProveReplicaUpdate2) @@ -1443,6 +1444,30 @@ Response: `{}` ### ReturnFinalizeSector +Perms: admin + +Inputs: +```json +[ + { + "Sector": { + "Miner": 1000, + "Number": 9 + }, + "ID": "07070707-0707-0707-0707-070707070707" + }, + { + "Code": 0, + "Message": "string value" + } +] +``` + +Response: `{}` + +### ReturnGenerateSectorKeyFromData + + Perms: admin Inputs: diff --git a/documentation/en/api-v0-methods-worker.md b/documentation/en/api-v0-methods-worker.md index 7aee91d52..5d4b33a52 100644 --- a/documentation/en/api-v0-methods-worker.md +++ b/documentation/en/api-v0-methods-worker.md @@ -11,6 +11,8 @@ * [AddPiece](#AddPiece) * [Finalize](#Finalize) * [FinalizeSector](#FinalizeSector) +* [Generate](#Generate) + * [GenerateSectorKeyFromData](#GenerateSectorKeyFromData) * [Move](#Move) * [MoveStorage](#MoveStorage) * [Process](#Process) @@ -220,6 +222,41 @@ Response: } ``` +## Generate + + +### GenerateSectorKeyFromData + + +Perms: admin + +Inputs: +```json +[ + { + "ID": { + "Miner": 1000, + "Number": 9 + }, + "ProofType": 8 + }, + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + } +] +``` + +Response: +```json +{ + "Sector": { + "Miner": 1000, + "Number": 9 + }, + "ID": "07070707-0707-0707-0707-070707070707" +} +``` + ## Move diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index ce7083b3d..428503c87 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit ce7083b3d187ec3bc41a68ab66567bd4f3be6dfc +Subproject commit 428503c87d917cc5e3e637983b43b4c260863bf0 diff --git a/extern/sector-storage/ffiwrapper/sealer_cgo.go b/extern/sector-storage/ffiwrapper/sealer_cgo.go index 81dbfb426..65c6762fa 100644 --- a/extern/sector-storage/ffiwrapper/sealer_cgo.go +++ b/extern/sector-storage/ffiwrapper/sealer_cgo.go @@ -251,6 +251,23 @@ func (sb *Sealer) pieceCid(spt abi.RegisteredSealProof, in []byte) (cid.Cid, err return pieceCID, werr() } +func (sb *Sealer) tryDecodeUpdatedReplica(ctx context.Context, sector storage.SectorRef, commD cid.Cid, unsealedPath string) (bool, error) { + paths, done, err := sb.sectors.AcquireSector(ctx, sector, storiface.FTUpdate|storiface.FTSealed|storiface.FTCache, storiface.FTNone, storiface.PathStorage) + if xerrors.Is(err, storiface.ErrSectorNotFound) { + return false, nil + } else if err != nil { + return false, xerrors.Errorf("reading updated replica: %w", err) + } + defer done() + + // Sector data stored in replica update + updateProof, err := sector.ProofType.RegisteredUpdateProof() + if err != nil { + return false, err + } + return true, ffi.SectorUpdate.DecodeFrom(updateProof, unsealedPath, paths.Update, paths.Sealed, paths.Cache, commD) +} + func (sb *Sealer) UnsealPiece(ctx context.Context, sector storage.SectorRef, offset storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, commd cid.Cid) error { ssize, err := sector.ProofType.SectorSize() if err != nil { @@ -301,6 +318,16 @@ func (sb *Sealer) UnsealPiece(ctx context.Context, sector storage.SectorRef, off return nil } + // If piece data stored in updated replica decode whole sector + decoded, err := sb.tryDecodeUpdatedReplica(ctx, sector, commd, unsealedPath.Unsealed) + if err != nil { + return xerrors.Errorf("decoding sector from replica: %w", err) + } + if decoded { + return pf.MarkAllocated(0, maxPieceSize) + } + + // Piece data sealed in sector srcPaths, srcDone, err := sb.sectors.AcquireSector(ctx, sector, storiface.FTCache|storiface.FTSealed, storiface.FTNone, storiface.PathStorage) if err != nil { return xerrors.Errorf("acquire sealed sector paths: %w", err) @@ -626,12 +653,6 @@ func (sb *Sealer) ReplicaUpdate(ctx context.Context, sector storage.SectorRef, p return empty, err } } - - // XXX: we want to keep the stuff at the end - if err := os.Truncate(paths.Unsealed, sealedSize); err != nil { - return empty, xerrors.Errorf("failed to truncate unsealed data file: %w", err) - } - sealed, unsealed, err := ffi.SectorUpdate.EncodeInto(updateProofType, paths.Update, paths.UpdateCache, paths.Sealed, paths.Cache, paths.Unsealed, pieces) if err != nil { return empty, xerrors.Errorf("failed to update replica %d with new deal data: %w", sector.ID.Number, err) @@ -661,6 +682,33 @@ func (sb *Sealer) ProveReplicaUpdate2(ctx context.Context, sector storage.Sector return ffi.SectorUpdate.GenerateUpdateProofWithVanilla(updateProofType, sectorKey, newSealed, newUnsealed, vanillaProofs) } +func (sb *Sealer) GenerateSectorKeyFromData(ctx context.Context, sector storage.SectorRef, commD cid.Cid) error { + paths, done, err := sb.sectors.AcquireSector(ctx, sector, storiface.FTUnsealed|storiface.FTCache|storiface.FTUpdate|storiface.FTUpdateCache, storiface.FTSealed, storiface.PathSealing) + defer done() + if err != nil { + return xerrors.Errorf("failed to acquire sector paths: %w", err) + } + + s, err := os.Stat(paths.Update) + if err != nil { + return xerrors.Errorf("measuring update file size: %w", err) + } + sealedSize := s.Size() + e, err := os.OpenFile(paths.Sealed, os.O_RDWR|os.O_CREATE, 0644) // nolint:gosec + if err != nil { + return xerrors.Errorf("ensuring sector key file exists: %w", err) + } + if err := fallocate.Fallocate(e, 0, sealedSize); err != nil { + return xerrors.Errorf("allocating space for sector key file: %w", err) + } + if err := e.Close(); err != nil { + return err + } + + updateProofType := abi.SealProofInfos[sector.ProofType].UpdateProof + return ffi.SectorUpdate.RemoveData(updateProofType, paths.Sealed, paths.Cache, paths.Update, paths.UpdateCache, paths.Unsealed, commD) +} + func (sb *Sealer) ReleaseSealed(ctx context.Context, sector storage.SectorRef) error { return xerrors.Errorf("not supported at this layer") } diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index e0abf1773..3deff4d6b 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -578,15 +578,72 @@ func (m *Manager) ReleaseUnsealed(ctx context.Context, sector storage.SectorRef, return nil } -func (m *Manager) ReleaseSealed(ctx context.Context, sector storage.SectorRef) error { - return nil +func (m *Manager) ReleaseSectorKey(ctx context.Context, sector storage.SectorRef) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + if err := m.index.StorageLock(ctx, sector.ID, storiface.FTNone, storiface.FTSealed); err != nil { + return xerrors.Errorf("acquiring sector lock: %w", err) + } + + return m.storage.Remove(ctx, sector.ID, storiface.FTSealed, true, nil) +} + +func (m *Manager) GenerateSectorKeyFromData(ctx context.Context, sector storage.SectorRef, commD cid.Cid) error { + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + wk, wait, cancel, err := m.getWork(ctx, sealtasks.TTRegenSectorKey, sector, commD) + if err != nil { + return xerrors.Errorf("getWork: %w", err) + } + defer cancel() + + var waitErr error + waitRes := func() { + _, werr := m.waitWork(ctx, wk) + if werr != nil { + waitErr = werr + return + } + } + + if wait { // already in progress + waitRes() + return waitErr + } + + if err := m.index.StorageLock(ctx, sector.ID, storiface.FTUnsealed|storiface.FTUpdate|storiface.FTUpdateCache, storiface.FTSealed|storiface.FTCache); err != nil { + return xerrors.Errorf("acquiring sector lock: %w", err) + } + + // NOTE: We set allowFetch to false in so that we always execute on a worker + // with direct access to the data. We want to do that because this step is + // generally very cheap / fast, and transferring data is not worth the effort + selector := newExistingSelector(m.index, sector.ID, storiface.FTUnsealed|storiface.FTUpdate|storiface.FTUpdateCache|storiface.FTCache, true) + + err = m.sched.Schedule(ctx, sector, sealtasks.TTRegenSectorKey, selector, m.schedFetch(sector, storiface.FTUpdate|storiface.FTUnsealed, storiface.PathSealing, storiface.AcquireMove), func(ctx context.Context, w Worker) error { + err := m.startWork(ctx, w, wk)(w.GenerateSectorKeyFromData(ctx, sector, commD)) + if err != nil { + return err + } + + waitRes() + return nil + }) + if err != nil { + return err + } + + return waitErr } func (m *Manager) Remove(ctx context.Context, sector storage.SectorRef) error { ctx, cancel := context.WithCancel(ctx) defer cancel() - if err := m.index.StorageLock(ctx, sector.ID, storiface.FTNone, storiface.FTSealed|storiface.FTUnsealed|storiface.FTCache); err != nil { + if err := m.index.StorageLock(ctx, sector.ID, storiface.FTNone, storiface.FTSealed|storiface.FTUnsealed|storiface.FTCache|storiface.FTUpdate|storiface.FTUpdateCache); err != nil { return xerrors.Errorf("acquiring sector lock: %w", err) } @@ -601,6 +658,12 @@ func (m *Manager) Remove(ctx context.Context, sector storage.SectorRef) error { if rerr := m.storage.Remove(ctx, sector.ID, storiface.FTUnsealed, true, nil); rerr != nil { err = multierror.Append(err, xerrors.Errorf("removing sector (unsealed): %w", rerr)) } + if rerr := m.storage.Remove(ctx, sector.ID, storiface.FTUpdate, true, nil); rerr != nil { + err = multierror.Append(err, xerrors.Errorf("removing sector (unsealed): %w", rerr)) + } + if rerr := m.storage.Remove(ctx, sector.ID, storiface.FTUpdateCache, true, nil); rerr != nil { + err = multierror.Append(err, xerrors.Errorf("removing sector (unsealed): %w", rerr)) + } return err } @@ -790,6 +853,10 @@ func (m *Manager) ReturnProveReplicaUpdate2(ctx context.Context, callID storifac return m.returnResult(ctx, callID, proof, err) } +func (m *Manager) ReturnGenerateSectorKeyFromData(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error { + return m.returnResult(ctx, callID, nil, err) +} + func (m *Manager) ReturnMoveStorage(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error { return m.returnResult(ctx, callID, nil, err) } diff --git a/extern/sector-storage/manager_test.go b/extern/sector-storage/manager_test.go index 77e185b93..cf54ccbf2 100644 --- a/extern/sector-storage/manager_test.go +++ b/extern/sector-storage/manager_test.go @@ -199,7 +199,8 @@ func TestSnapDeals(t *testing.T) { localTasks := []sealtasks.TaskType{ sealtasks.TTAddPiece, sealtasks.TTPreCommit1, sealtasks.TTPreCommit2, sealtasks.TTCommit1, sealtasks.TTCommit2, sealtasks.TTFinalize, - sealtasks.TTFetch, sealtasks.TTReplicaUpdate, sealtasks.TTProveReplicaUpdate1, sealtasks.TTProveReplicaUpdate2, + sealtasks.TTFetch, sealtasks.TTReplicaUpdate, sealtasks.TTProveReplicaUpdate1, sealtasks.TTProveReplicaUpdate2, sealtasks.TTUnseal, + sealtasks.TTRegenSectorKey, } wds := datastore.NewMapDatastore() @@ -245,14 +246,6 @@ func TestSnapDeals(t *testing.T) { require.NoError(t, err) fmt.Printf("PC2\n") pc2Out, err := m.SealPreCommit2(ctx, sid, pc1Out) - - require.NoError(t, err) - seed := abi.InteractiveSealRandomness{1, 1, 1, 1, 1, 1, 1} - fmt.Printf("C1\n") - c1Out, err := m.SealCommit1(ctx, sid, ticket, seed, nil, pc2Out) - require.NoError(t, err) - fmt.Printf("C2\n") - _, err = m.SealCommit2(ctx, sid, c1Out) require.NoError(t, err) // Now do a snap deals replica update @@ -270,19 +263,26 @@ func TestSnapDeals(t *testing.T) { pieces := []abi.PieceInfo{p1, p2} fmt.Printf("RU\n") + startRU := time.Now() out, err := m.ReplicaUpdate(ctx, sid, pieces) require.NoError(t, err) + fmt.Printf("RU duration (%s): %s\n", ss.ShortString(), time.Since(startRU)) + updateProofType, err := sid.ProofType.RegisteredUpdateProof() require.NoError(t, err) require.NotNil(t, out) fmt.Printf("PR1\n") + startPR1 := time.Now() vanillaProofs, err := m.ProveReplicaUpdate1(ctx, sid, sectorKey, out.NewSealed, out.NewUnsealed) require.NoError(t, err) require.NotNil(t, vanillaProofs) + fmt.Printf("PR1 duration (%s): %s\n", ss.ShortString(), time.Since(startPR1)) fmt.Printf("PR2\n") + startPR2 := time.Now() proof, err := m.ProveReplicaUpdate2(ctx, sid, sectorKey, out.NewSealed, out.NewUnsealed, vanillaProofs) require.NoError(t, err) require.NotNil(t, proof) + fmt.Printf("PR2 duration (%s): %s\n", ss.ShortString(), time.Since(startPR2)) vInfo := proof7.ReplicaUpdateInfo{ Proof: proof, @@ -294,6 +294,24 @@ func TestSnapDeals(t *testing.T) { pass, err := ffiwrapper.ProofVerifier.VerifyReplicaUpdate(vInfo) require.NoError(t, err) assert.True(t, pass) + + fmt.Printf("Decode\n") + // Remove unsealed data and decode for retrieval + require.NoError(t, m.FinalizeSector(ctx, sid, nil)) + startDecode := time.Now() + require.NoError(t, m.SectorsUnsealPiece(ctx, sid, 0, p1.Size.Unpadded(), ticket, &out.NewUnsealed)) + fmt.Printf("Decode duration (%s): %s\n", ss.ShortString(), time.Since(startDecode)) + + // Remove just the first piece and decode for retrieval + require.NoError(t, m.FinalizeSector(ctx, sid, []storage.Range{{Offset: p1.Size.Unpadded(), Size: p2.Size.Unpadded()}})) + require.NoError(t, m.SectorsUnsealPiece(ctx, sid, 0, p1.Size.Unpadded(), ticket, &out.NewUnsealed)) + + fmt.Printf("GSK\n") + require.NoError(t, m.ReleaseSectorKey(ctx, sid)) + startGSK := time.Now() + require.NoError(t, m.GenerateSectorKeyFromData(ctx, sid, out.NewUnsealed)) + fmt.Printf("GSK duration (%s): %s\n", ss.ShortString(), time.Since(startGSK)) + } func TestRedoPC1(t *testing.T) { diff --git a/extern/sector-storage/mock/mock.go b/extern/sector-storage/mock/mock.go index 023904984..95b11c004 100644 --- a/extern/sector-storage/mock/mock.go +++ b/extern/sector-storage/mock/mock.go @@ -277,6 +277,10 @@ func (mgr *SectorMgr) ProveReplicaUpdate2(ctx context.Context, sector storage.Se return make([]byte, 0), nil } +func (mgr *SectorMgr) GenerateSectorKeyFromData(ctx context.Context, sector storage.SectorRef, commD cid.Cid) error { + return nil +} + func (mgr *SectorMgr) ReleaseSealed(ctx context.Context, sid storage.SectorRef) error { return nil } @@ -534,6 +538,10 @@ func (mgr *SectorMgr) ReturnProveReplicaUpdate2(ctx context.Context, callID stor panic("not supported") } +func (mgr *SectorMgr) ReturnGenerateSectorKeyFromData(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error { + panic("not supported") +} + func (m mockVerifProver) VerifySeal(svi proof5.SealVerifyInfo) (bool, error) { plen, err := svi.SealProof.ProofSize() if err != nil { diff --git a/extern/sector-storage/sched_test.go b/extern/sector-storage/sched_test.go index fd3c90295..a41e7c855 100644 --- a/extern/sector-storage/sched_test.go +++ b/extern/sector-storage/sched_test.go @@ -112,6 +112,10 @@ func (s *schedTestWorker) ProveReplicaUpdate2(ctx context.Context, sector storag panic("implement me") } +func (s *schedTestWorker) GenerateSectorKeyFromData(ctx context.Context, sector storage.SectorRef, commD cid.Cid) (storiface.CallID, error) { + panic("implement me") +} + func (s *schedTestWorker) MoveStorage(ctx context.Context, sector storage.SectorRef, types storiface.SectorFileType) (storiface.CallID, error) { panic("implement me") } diff --git a/extern/sector-storage/sealtasks/task.go b/extern/sector-storage/sealtasks/task.go index 3f2a9701f..f6104878b 100644 --- a/extern/sector-storage/sealtasks/task.go +++ b/extern/sector-storage/sealtasks/task.go @@ -17,10 +17,12 @@ const ( TTReplicaUpdate TaskType = "seal/v0/replicaupdate" TTProveReplicaUpdate1 TaskType = "seal/v0/provereplicaupdate/1" TTProveReplicaUpdate2 TaskType = "seal/v0/provereplicaupdate/2" + TTRegenSectorKey TaskType = "seal/v0/regensectorkey" ) var order = map[TaskType]int{ - TTAddPiece: 9, // least priority + TTRegenSectorKey: 10, // least priority + TTAddPiece: 9, TTReplicaUpdate: 8, TTProveReplicaUpdate2: 7, TTProveReplicaUpdate1: 6, @@ -49,6 +51,7 @@ var shortNames = map[TaskType]string{ TTReplicaUpdate: "RU", TTProveReplicaUpdate1: "PR1", TTProveReplicaUpdate2: "PR2", + TTRegenSectorKey: "GSK", } func (a TaskType) MuchLess(b TaskType) (bool, bool) { diff --git a/extern/sector-storage/storiface/worker.go b/extern/sector-storage/storiface/worker.go index 970e0ec33..ab8c484e6 100644 --- a/extern/sector-storage/storiface/worker.go +++ b/extern/sector-storage/storiface/worker.go @@ -95,6 +95,7 @@ type WorkerCalls interface { ReplicaUpdate(ctx context.Context, sector storage.SectorRef, pieces []abi.PieceInfo) (CallID, error) ProveReplicaUpdate1(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid) (CallID, error) ProveReplicaUpdate2(ctx context.Context, sector storage.SectorRef, sectorKey, newSealed, newUnsealed cid.Cid, vanillaProofs storage.ReplicaVanillaProofs) (CallID, error) + GenerateSectorKeyFromData(ctx context.Context, sector storage.SectorRef, commD cid.Cid) (CallID, error) MoveStorage(ctx context.Context, sector storage.SectorRef, types SectorFileType) (CallID, error) UnsealPiece(context.Context, storage.SectorRef, UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (CallID, error) Fetch(context.Context, storage.SectorRef, SectorFileType, PathType, AcquireMode) (CallID, error) @@ -151,6 +152,7 @@ type WorkerReturn interface { ReturnReplicaUpdate(ctx context.Context, callID CallID, out storage.ReplicaUpdateOut, err *CallError) error ReturnProveReplicaUpdate1(ctx context.Context, callID CallID, proofs storage.ReplicaVanillaProofs, err *CallError) error ReturnProveReplicaUpdate2(ctx context.Context, callID CallID, proof storage.ReplicaUpdateProof, err *CallError) error + ReturnGenerateSectorKeyFromData(ctx context.Context, callID CallID, err *CallError) error ReturnMoveStorage(ctx context.Context, callID CallID, err *CallError) error ReturnUnsealPiece(ctx context.Context, callID CallID, err *CallError) error ReturnReadPiece(ctx context.Context, callID CallID, ok bool, err *CallError) error diff --git a/extern/sector-storage/teststorage_test.go b/extern/sector-storage/teststorage_test.go index 4061b48d9..9fdb3a913 100644 --- a/extern/sector-storage/teststorage_test.go +++ b/extern/sector-storage/teststorage_test.go @@ -75,6 +75,10 @@ func (t *testExec) ProveReplicaUpdate2(ctx context.Context, sector storage.Secto panic("implement me") } +func (t *testExec) GenerateSectorKeyFromData(ctx context.Context, sector storage.SectorRef, commD cid.Cid) error { + panic("implement me") +} + func (t *testExec) NewSector(ctx context.Context, sector storage.SectorRef) error { panic("implement me") } diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index cc41e916e..387a47f8f 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -168,6 +168,7 @@ const ( ReplicaUpdate ReturnType = "ReplicaUpdate" ProveReplicaUpdate1 ReturnType = "ProveReplicaUpdate1" ProveReplicaUpdate2 ReturnType = "ProveReplicaUpdate2" + GenerateSectorKey ReturnType = "GenerateSectorKey" ReleaseUnsealed ReturnType = "ReleaseUnsealed" MoveStorage ReturnType = "MoveStorage" UnsealPiece ReturnType = "UnsealPiece" @@ -219,6 +220,7 @@ var returnFunc = map[ReturnType]func(context.Context, storiface.CallID, storifac ReplicaUpdate: rfunc(storiface.WorkerReturn.ReturnReplicaUpdate), ProveReplicaUpdate1: rfunc(storiface.WorkerReturn.ReturnProveReplicaUpdate1), ProveReplicaUpdate2: rfunc(storiface.WorkerReturn.ReturnProveReplicaUpdate2), + GenerateSectorKey: rfunc(storiface.WorkerReturn.ReturnGenerateSectorKeyFromData), MoveStorage: rfunc(storiface.WorkerReturn.ReturnMoveStorage), UnsealPiece: rfunc(storiface.WorkerReturn.ReturnUnsealPiece), Fetch: rfunc(storiface.WorkerReturn.ReturnFetch), @@ -419,6 +421,17 @@ func (l *LocalWorker) ProveReplicaUpdate2(ctx context.Context, sector storage.Se }) } +func (l *LocalWorker) GenerateSectorKeyFromData(ctx context.Context, sector storage.SectorRef, commD cid.Cid) (storiface.CallID, error) { + sb, err := l.executor() + if err != nil { + return storiface.UndefCall, err + } + + return l.asyncCall(ctx, sector, GenerateSectorKey, func(ctx context.Context, ci storiface.CallID) (interface{}, error) { + return nil, sb.GenerateSectorKeyFromData(ctx, sector, commD) + }) +} + func (l *LocalWorker) FinalizeSector(ctx context.Context, sector storage.SectorRef, keepUnsealed []storage.Range) (storiface.CallID, error) { sb, err := l.executor() if err != nil { diff --git a/go.mod b/go.mod index e0823094d..95618417b 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/filecoin-project/specs-actors/v5 v5.0.4 github.com/filecoin-project/specs-actors/v6 v6.0.1 github.com/filecoin-project/specs-actors/v7 v7.0.0-20211118013026-3dce48197cec - github.com/filecoin-project/specs-storage v0.1.1-0.20211123153428-712cb8da07a3 + github.com/filecoin-project/specs-storage v0.1.1-0.20211202151826-2e51da61d454 github.com/filecoin-project/test-vectors/schema v0.0.5 github.com/gbrlsnchs/jwt/v3 v3.0.1 github.com/gdamore/tcell/v2 v2.2.0 diff --git a/go.sum b/go.sum index e404ca72e..38f772025 100644 --- a/go.sum +++ b/go.sum @@ -396,8 +396,8 @@ github.com/filecoin-project/specs-actors/v6 v6.0.1/go.mod h1:V1AYfi5GkHXipx1mnVi github.com/filecoin-project/specs-actors/v7 v7.0.0-20211117170924-fd07a4c7dff9/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= github.com/filecoin-project/specs-actors/v7 v7.0.0-20211118013026-3dce48197cec h1:KV9vE+Sl2Y3qKsrpba4HcE7wHwK7v6O5U/S0xHbje6A= github.com/filecoin-project/specs-actors/v7 v7.0.0-20211118013026-3dce48197cec/go.mod h1:p6LIOFezA1rgRLMewbvdi3Pp6SAu+q9FtJ9CAleSjrE= -github.com/filecoin-project/specs-storage v0.1.1-0.20211123153428-712cb8da07a3 h1:FLPxD2ksWwGc/sbnFLWep2p8ViP93VCAwFaVxrtVCyo= -github.com/filecoin-project/specs-storage v0.1.1-0.20211123153428-712cb8da07a3/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= +github.com/filecoin-project/specs-storage v0.1.1-0.20211202151826-2e51da61d454 h1:9II9Xf+jq5xAPQiS4rVoKIiALINa3loMC+ghyFYIrqQ= +github.com/filecoin-project/specs-storage v0.1.1-0.20211202151826-2e51da61d454/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g= github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg= github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= diff --git a/itests/self_sent_txn_test.go b/itests/self_sent_txn_test.go index 846bcff05..b5ec2c0dc 100644 --- a/itests/self_sent_txn_test.go +++ b/itests/self_sent_txn_test.go @@ -15,8 +15,7 @@ import ( "github.com/stretchr/testify/require" ) - -// these tests check that the versioned code in vm.transfer is functioning correctly across versions! +// these tests check that the versioned code in vm.transfer is functioning correctly across versions! // we reordered the checks to make sure that a transaction with too much money in it sent to yourself will fail instead of succeeding as a noop // more info in this PR! https://github.com/filecoin-project/lotus/pull/7637 func TestSelfSentTxnV15(t *testing.T) { From 3e288f1066f290f59316696f506b2ae2b02a2cd3 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Mon, 13 Dec 2021 15:47:17 -0500 Subject: [PATCH 12/12] Update FFI --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 428503c87..52d80081b 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 428503c87d917cc5e3e637983b43b4c260863bf0 +Subproject commit 52d80081bfdd8a30bc44bcfe44cb0f299615b9f3