Merge pull request #1025 from filecoin-project/fix/faults-counting
Fix faults handling
This commit is contained in:
commit
d213bd1fee
@ -467,14 +467,21 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM
|
|||||||
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
|
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
|
||||||
}
|
}
|
||||||
|
|
||||||
faults, nerr := self.FaultSet.AllMap()
|
ss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.Sectors)
|
||||||
|
if lerr != nil {
|
||||||
|
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
|
||||||
|
}
|
||||||
|
|
||||||
|
faults, nerr := self.FaultSet.AllMap(2 * ss.Count)
|
||||||
if nerr != nil {
|
if nerr != nil {
|
||||||
return nil, aerrors.Absorb(err, 5, "RLE+ invalid")
|
return nil, aerrors.Absorb(err, 5, "RLE+ invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
activeFaults := uint64(0)
|
||||||
var sectorInfos []ffi.PublicSectorInfo
|
var sectorInfos []ffi.PublicSectorInfo
|
||||||
if err := pss.ForEach(func(id uint64, v *cbg.Deferred) error {
|
if err := pss.ForEach(func(id uint64, v *cbg.Deferred) error {
|
||||||
if faults[id] {
|
if faults[id] {
|
||||||
|
activeFaults++
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,7 +519,7 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ok, lerr := sectorbuilder.VerifyFallbackPost(vmctx.Context(), mi.SectorSize,
|
if ok, lerr := sectorbuilder.VerifyFallbackPost(vmctx.Context(), mi.SectorSize,
|
||||||
sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), seed[:], params.Proof, candidates, proverID, len(faults)); !ok || lerr != nil {
|
sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), seed[:], params.Proof, candidates, proverID, activeFaults); !ok || lerr != nil {
|
||||||
if lerr != nil {
|
if lerr != nil {
|
||||||
// TODO: study PoST errors
|
// TODO: study PoST errors
|
||||||
return nil, aerrors.Absorb(lerr, 4, "PoST error")
|
return nil, aerrors.Absorb(lerr, 4, "PoST error")
|
||||||
@ -523,7 +530,7 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Post submission is successful!
|
// Post submission is successful!
|
||||||
if err := onSuccessfulPoSt(self, vmctx); err != nil {
|
if err := onSuccessfulPoSt(self, vmctx, activeFaults); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -834,6 +841,20 @@ func (sma StorageMinerActor) DeclareFaults(act *types.Actor, vmctx types.VMConte
|
|||||||
return nil, aerrors.Absorb(err, 1, "failed to merge bitfields")
|
return nil, aerrors.Absorb(err, 1, "failed to merge bitfields")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ss, nerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.Sectors)
|
||||||
|
if nerr != nil {
|
||||||
|
return nil, aerrors.HandleExternalError(nerr, "failed to load sector set")
|
||||||
|
}
|
||||||
|
|
||||||
|
cf, nerr := nfaults.Count()
|
||||||
|
if nerr != nil {
|
||||||
|
return nil, aerrors.Absorb(nerr, 2, "could not decode RLE+")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cf > 2*ss.Count {
|
||||||
|
return nil, aerrors.Newf(3, "too many declared faults: %d > %d", cf, 2*ss.Count)
|
||||||
|
}
|
||||||
|
|
||||||
self.FaultSet = nfaults
|
self.FaultSet = nfaults
|
||||||
|
|
||||||
self.LastFaultSubmission = vmctx.BlockHeight()
|
self.LastFaultSubmission = vmctx.BlockHeight()
|
||||||
@ -909,7 +930,41 @@ func (sma StorageMinerActor) SubmitElectionPoSt(act *types.Actor, vmctx types.VM
|
|||||||
return nil, aerrors.New(1, "slashed miners can't perform election PoSt")
|
return nil, aerrors.New(1, "slashed miners can't perform election PoSt")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := onSuccessfulPoSt(self, vmctx); err != nil {
|
pss, nerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
|
||||||
|
if nerr != nil {
|
||||||
|
return nil, aerrors.HandleExternalError(nerr, "failed to load proving set")
|
||||||
|
}
|
||||||
|
|
||||||
|
ss, nerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.Sectors)
|
||||||
|
if nerr != nil {
|
||||||
|
return nil, aerrors.HandleExternalError(nerr, "failed to load proving set")
|
||||||
|
}
|
||||||
|
|
||||||
|
faults, nerr := self.FaultSet.AllMap(2 * ss.Count)
|
||||||
|
if nerr != nil {
|
||||||
|
return nil, aerrors.Absorb(nerr, 1, "invalid bitfield (fatal?)")
|
||||||
|
}
|
||||||
|
|
||||||
|
activeFaults := uint64(0)
|
||||||
|
for f := range faults {
|
||||||
|
if f > amt.MaxIndex {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var comms [][]byte
|
||||||
|
err := pss.Get(f, &comms)
|
||||||
|
if err != nil {
|
||||||
|
var notfound *amt.ErrNotFound
|
||||||
|
if !xerrors.As(err, ¬found) {
|
||||||
|
return nil, aerrors.HandleExternalError(err, "failed to find sector in sector set")
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
activeFaults++
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := onSuccessfulPoSt(self, vmctx, activeFaults); err != nil { // TODO
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -924,7 +979,7 @@ func (sma StorageMinerActor) SubmitElectionPoSt(act *types.Actor, vmctx types.VM
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func onSuccessfulPoSt(self *StorageMinerActorState, vmctx types.VMContext) aerrors.ActorError {
|
func onSuccessfulPoSt(self *StorageMinerActorState, vmctx types.VMContext, activeFaults uint64) aerrors.ActorError {
|
||||||
// TODO: some sector upkeep stuff that is very haphazard and unclear in the spec
|
// TODO: some sector upkeep stuff that is very haphazard and unclear in the spec
|
||||||
|
|
||||||
var mi MinerInfo
|
var mi MinerInfo
|
||||||
@ -937,7 +992,12 @@ func onSuccessfulPoSt(self *StorageMinerActorState, vmctx types.VMContext) aerro
|
|||||||
return aerrors.HandleExternalError(nerr, "failed to load proving set")
|
return aerrors.HandleExternalError(nerr, "failed to load proving set")
|
||||||
}
|
}
|
||||||
|
|
||||||
faults, nerr := self.FaultSet.All()
|
ss, nerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.Sectors)
|
||||||
|
if nerr != nil {
|
||||||
|
return aerrors.HandleExternalError(nerr, "failed to load sector set")
|
||||||
|
}
|
||||||
|
|
||||||
|
faults, nerr := self.FaultSet.All(2 * ss.Count)
|
||||||
if nerr != nil {
|
if nerr != nil {
|
||||||
return aerrors.Absorb(nerr, 1, "invalid bitfield (fatal?)")
|
return aerrors.Absorb(nerr, 1, "invalid bitfield (fatal?)")
|
||||||
}
|
}
|
||||||
@ -945,7 +1005,7 @@ func onSuccessfulPoSt(self *StorageMinerActorState, vmctx types.VMContext) aerro
|
|||||||
self.FaultSet = types.NewBitField()
|
self.FaultSet = types.NewBitField()
|
||||||
|
|
||||||
oldPower := self.Power
|
oldPower := self.Power
|
||||||
newPower := types.BigMul(types.NewInt(pss.Count-uint64(len(faults))), types.NewInt(mi.SectorSize))
|
newPower := types.BigMul(types.NewInt(pss.Count-activeFaults), types.NewInt(mi.SectorSize))
|
||||||
|
|
||||||
// If below the minimum size requirement, miners have zero power
|
// If below the minimum size requirement, miners have zero power
|
||||||
if newPower.LessThan(types.NewInt(build.MinimumMinerPower)) {
|
if newPower.LessThan(types.NewInt(build.MinimumMinerPower)) {
|
||||||
|
@ -3,18 +3,22 @@ package actors_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-sectorbuilder"
|
"github.com/filecoin-project/go-sectorbuilder"
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/lib/rlepluslazy"
|
||||||
hamt "github.com/ipfs/go-hamt-ipld"
|
hamt "github.com/ipfs/go-hamt-ipld"
|
||||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,23 +54,37 @@ func TestMinerCommitSectors(t *testing.T) {
|
|||||||
addSectorToMiner(h, t, minerAddr, worker, client, 1)
|
addSectorToMiner(h, t, minerAddr, worker, client, 1)
|
||||||
|
|
||||||
assertSectorIDs(h, t, minerAddr, []uint64{1})
|
assertSectorIDs(h, t, minerAddr, []uint64{1})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type badRuns struct {
|
||||||
|
done bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (br *badRuns) HasNext() bool {
|
||||||
|
return !br.done
|
||||||
|
}
|
||||||
|
|
||||||
|
func (br *badRuns) NextRun() (rlepluslazy.Run, error) {
|
||||||
|
br.done = true
|
||||||
|
return rlepluslazy.Run{true, math.MaxInt64}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ rlepluslazy.RunIterator = (*badRuns)(nil)
|
||||||
|
|
||||||
func TestMinerSubmitBadFault(t *testing.T) {
|
func TestMinerSubmitBadFault(t *testing.T) {
|
||||||
|
oldSS, oldMin := build.SectorSizes, build.MinimumMinerPower
|
||||||
|
build.SectorSizes, build.MinimumMinerPower = []uint64{1024}, 1024
|
||||||
|
defer func() {
|
||||||
|
build.SectorSizes, build.MinimumMinerPower = oldSS, oldMin
|
||||||
|
}()
|
||||||
|
|
||||||
var worker, client address.Address
|
var worker, client address.Address
|
||||||
var minerAddr address.Address
|
var minerAddr address.Address
|
||||||
opts := []HarnessOpt{
|
opts := []HarnessOpt{
|
||||||
HarnessAddr(&worker, 1000000),
|
HarnessAddr(&worker, 1000000),
|
||||||
HarnessAddr(&client, 1000000),
|
HarnessAddr(&client, 1000000),
|
||||||
HarnessActor(&minerAddr, &worker, actors.StorageMinerCodeCid,
|
HarnessAddMiner(&minerAddr, &worker),
|
||||||
func() cbg.CBORMarshaler {
|
|
||||||
return &actors.StorageMinerConstructorParams{
|
|
||||||
Owner: worker,
|
|
||||||
Worker: worker,
|
|
||||||
SectorSize: 1024,
|
|
||||||
PeerID: "fakepeerid",
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h := NewHarness(t, opts...)
|
h := NewHarness(t, opts...)
|
||||||
@ -92,18 +110,52 @@ func TestMinerSubmitBadFault(t *testing.T) {
|
|||||||
|
|
||||||
ret, _ = h.Invoke(t, actors.NetworkAddress, minerAddr, actors.MAMethods.SubmitElectionPoSt, nil)
|
ret, _ = h.Invoke(t, actors.NetworkAddress, minerAddr, actors.MAMethods.SubmitElectionPoSt, nil)
|
||||||
ApplyOK(t, ret)
|
ApplyOK(t, ret)
|
||||||
|
|
||||||
assertSectorIDs(h, t, minerAddr, []uint64{1})
|
assertSectorIDs(h, t, minerAddr, []uint64{1})
|
||||||
|
|
||||||
|
st, err := getMinerState(context.TODO(), h.vm.StateTree(), h.bs, minerAddr)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
expectedPower := st.Power
|
||||||
|
if types.BigCmp(expectedPower, types.NewInt(1024)) != 0 {
|
||||||
|
t.Errorf("Expected power of 1024, got %s", expectedPower)
|
||||||
|
}
|
||||||
|
|
||||||
badnum := uint64(0)
|
badnum := uint64(0)
|
||||||
badnum--
|
badnum--
|
||||||
bf = types.NewBitField()
|
bf = types.NewBitField()
|
||||||
bf.Set(badnum)
|
bf.Set(badnum)
|
||||||
|
bf.Set(badnum - 1)
|
||||||
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
|
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
|
||||||
ApplyOK(t, ret)
|
ApplyOK(t, ret)
|
||||||
|
|
||||||
ret, _ = h.Invoke(t, actors.NetworkAddress, minerAddr, actors.MAMethods.SubmitElectionPoSt, nil)
|
ret, _ = h.Invoke(t, actors.NetworkAddress, minerAddr, actors.MAMethods.SubmitElectionPoSt, nil)
|
||||||
|
|
||||||
ApplyOK(t, ret)
|
ApplyOK(t, ret)
|
||||||
|
assertSectorIDs(h, t, minerAddr, []uint64{1})
|
||||||
|
|
||||||
|
st, err = getMinerState(context.TODO(), h.vm.StateTree(), h.bs, minerAddr)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
currentPower := st.Power
|
||||||
|
if types.BigCmp(expectedPower, currentPower) != 0 {
|
||||||
|
t.Errorf("power changed and shouldn't have: %s != %s", expectedPower, currentPower)
|
||||||
|
}
|
||||||
|
|
||||||
|
bf.Set(badnum - 2)
|
||||||
|
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
|
||||||
|
if ret.ExitCode != 3 {
|
||||||
|
t.Errorf("expected exit code 3, got %d: %+v", ret.ExitCode, ret.ActorErr)
|
||||||
|
}
|
||||||
|
assertSectorIDs(h, t, minerAddr, []uint64{1})
|
||||||
|
|
||||||
|
rle, err := rlepluslazy.EncodeRuns(&badRuns{}, []byte{})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
bf, err = types.NewBitFieldFromBytes(rle)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
|
||||||
|
if ret.ExitCode != 3 {
|
||||||
|
t.Errorf("expected exit code 3, got %d: %+v", ret.ExitCode, ret.ActorErr)
|
||||||
|
}
|
||||||
|
assertSectorIDs(h, t, minerAddr, []uint64{1})
|
||||||
|
|
||||||
bf = types.NewBitField()
|
bf = types.NewBitField()
|
||||||
bf.Set(1)
|
bf.Set(1)
|
||||||
@ -175,7 +227,7 @@ func assertSectorIDs(h *Harness, t *testing.T, maddr address.Address, ids []uint
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMinerSectorSet(ctx context.Context, st types.StateTree, bs blockstore.Blockstore, maddr address.Address) ([]*api.ChainSectorInfo, error) {
|
func getMinerState(ctx context.Context, st types.StateTree, bs blockstore.Blockstore, maddr address.Address) (*actors.StorageMinerActorState, error) {
|
||||||
mact, err := st.GetActor(maddr)
|
mact, err := st.GetActor(maddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -187,6 +239,14 @@ func getMinerSectorSet(ctx context.Context, st types.StateTree, bs blockstore.Bl
|
|||||||
if err := cst.Get(ctx, mact.Head, &mstate); err != nil {
|
if err := cst.Get(ctx, mact.Head, &mstate); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return &mstate, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMinerSectorSet(ctx context.Context, st types.StateTree, bs blockstore.Blockstore, maddr address.Address) ([]*api.ChainSectorInfo, error) {
|
||||||
|
mstate, err := getMinerState(ctx, st, bs, maddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return stmgr.LoadSectorsFromSet(ctx, bs, mstate.Sectors)
|
return stmgr.LoadSectorsFromSet(ctx, bs, mstate.Sectors)
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ type CreateStorageMinerParams struct {
|
|||||||
|
|
||||||
func (spa StoragePowerActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) ([]byte, ActorError) {
|
func (spa StoragePowerActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) ([]byte, ActorError) {
|
||||||
if !build.SupportedSectorSize(params.SectorSize) {
|
if !build.SupportedSectorSize(params.SectorSize) {
|
||||||
return nil, aerrors.New(1, "Unsupported sector size")
|
return nil, aerrors.Newf(1, "Unsupported sector size: %d", params.SectorSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
var self StoragePowerState
|
var self StoragePowerState
|
||||||
|
@ -115,6 +115,32 @@ func HarnessActor(actor *address.Address, creator *address.Address, code cid.Cid
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HarnessAddMiner(addr *address.Address, creator *address.Address) HarnessOpt {
|
||||||
|
return func(t testing.TB, h *Harness) error {
|
||||||
|
if h.Stage != HarnessPostInit {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if !addr.Empty() {
|
||||||
|
return xerrors.New("actor address should be empty")
|
||||||
|
}
|
||||||
|
ret, _ := h.InvokeWithValue(t, *creator, actors.StoragePowerAddress,
|
||||||
|
actors.SPAMethods.CreateStorageMiner, types.NewInt(3000), &actors.StorageMinerConstructorParams{
|
||||||
|
Owner: *creator,
|
||||||
|
Worker: *creator,
|
||||||
|
SectorSize: 1024,
|
||||||
|
PeerID: "fakepeerid",
|
||||||
|
})
|
||||||
|
|
||||||
|
if ret.ExitCode != 0 {
|
||||||
|
return xerrors.Errorf("creating actor: %w", ret.ActorErr)
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
*addr, err = address.NewFromBytes(ret.Return)
|
||||||
|
return err
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func HarnessCtx(ctx context.Context) HarnessOpt {
|
func HarnessCtx(ctx context.Context) HarnessOpt {
|
||||||
return func(t testing.TB, h *Harness) error {
|
return func(t testing.TB, h *Harness) error {
|
||||||
h.ctx = ctx
|
h.ctx = ctx
|
||||||
@ -177,7 +203,7 @@ func NewHarness(t *testing.T, options ...HarnessOpt) *Harness {
|
|||||||
for _, opt := range options {
|
for _, opt := range options {
|
||||||
err := opt(t, h)
|
err := opt(t, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Applying options: %v", err)
|
t.Fatalf("Applying options: %+v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
@ -9,6 +10,8 @@ import (
|
|||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ErrBitFieldTooMany = errors.New("to many items in RLE")
|
||||||
|
|
||||||
type BitField struct {
|
type BitField struct {
|
||||||
rle rlepluslazy.RLE
|
rle rlepluslazy.RLE
|
||||||
|
|
||||||
@ -16,14 +19,23 @@ type BitField struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewBitField() BitField {
|
func NewBitField() BitField {
|
||||||
rle, err := rlepluslazy.FromBuf([]byte{})
|
bf, err := NewBitFieldFromBytes([]byte{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(fmt.Sprintf("creating empty rle: %+v", err))
|
||||||
}
|
}
|
||||||
return BitField{
|
return bf
|
||||||
rle: rle,
|
}
|
||||||
bits: make(map[uint64]struct{}),
|
|
||||||
|
func NewBitFieldFromBytes(rle []byte) (BitField, error) {
|
||||||
|
bf := BitField{}
|
||||||
|
rlep, err := rlepluslazy.FromBuf(rle)
|
||||||
|
if err != nil {
|
||||||
|
return BitField{}, xerrors.Errorf("could not decode rle+: %w", err)
|
||||||
}
|
}
|
||||||
|
bf.rle = rlep
|
||||||
|
bf.bits = make(map[uint64]struct{})
|
||||||
|
return bf, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BitFieldFromSet(setBits []uint64) BitField {
|
func BitFieldFromSet(setBits []uint64) BitField {
|
||||||
@ -106,7 +118,14 @@ func (bf BitField) Count() (uint64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// All returns all set bits
|
// All returns all set bits
|
||||||
func (bf BitField) All() ([]uint64, error) {
|
func (bf BitField) All(max uint64) ([]uint64, error) {
|
||||||
|
c, err := bf.Count()
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("count errror: %w", err)
|
||||||
|
}
|
||||||
|
if c > max {
|
||||||
|
return nil, xerrors.Errorf("expected %d, got %d: %w", max, c, ErrBitFieldTooMany)
|
||||||
|
}
|
||||||
|
|
||||||
runs, err := bf.sum()
|
runs, err := bf.sum()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -121,7 +140,14 @@ func (bf BitField) All() ([]uint64, error) {
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bf BitField) AllMap() (map[uint64]bool, error) {
|
func (bf BitField) AllMap(max uint64) (map[uint64]bool, error) {
|
||||||
|
c, err := bf.Count()
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("count errror: %w", err)
|
||||||
|
}
|
||||||
|
if c > max {
|
||||||
|
return nil, xerrors.Errorf("expected %d, got %d: %w", max, c, ErrBitFieldTooMany)
|
||||||
|
}
|
||||||
|
|
||||||
runs, err := bf.sum()
|
runs, err := bf.sum()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -216,7 +216,7 @@ func IsTicketWinner(partialTicket []byte, ssizeI uint64, snum uint64, totpow Big
|
|||||||
return lhs.Cmp(rhs) < 0
|
return lhs.Cmp(rhs) < 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func ElectionPostChallengeCount(sectors uint64, faults int) uint64 {
|
func ElectionPostChallengeCount(sectors uint64, faults uint64) uint64 {
|
||||||
return sectorbuilder.ElectionPostChallengeCount(sectors, faults)
|
return sectorbuilder.ElectionPostChallengeCount(sectors, faults)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
go.mod
2
go.mod
@ -16,7 +16,7 @@ require (
|
|||||||
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2
|
github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2
|
||||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
|
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
|
||||||
github.com/filecoin-project/go-paramfetch v0.0.0-20200102181131-b20d579f2878
|
github.com/filecoin-project/go-paramfetch v0.0.0-20200102181131-b20d579f2878
|
||||||
github.com/filecoin-project/go-sectorbuilder v0.0.0-20200107152336-0cbb2c483013
|
github.com/filecoin-project/go-sectorbuilder v0.0.0-20200107220006-3361d30ea5ab
|
||||||
github.com/filecoin-project/go-statestore v0.0.0-20200102200712-1f63c701c1e5
|
github.com/filecoin-project/go-statestore v0.0.0-20200102200712-1f63c701c1e5
|
||||||
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
|
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
|
||||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||||
|
4
go.sum
4
go.sum
@ -93,8 +93,8 @@ github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMX
|
|||||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ=
|
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ=
|
||||||
github.com/filecoin-project/go-paramfetch v0.0.0-20200102181131-b20d579f2878 h1:YicJT9xhPzZ1SBGiJFNUCkfwqK/G9vFyY1ytKBSjNJA=
|
github.com/filecoin-project/go-paramfetch v0.0.0-20200102181131-b20d579f2878 h1:YicJT9xhPzZ1SBGiJFNUCkfwqK/G9vFyY1ytKBSjNJA=
|
||||||
github.com/filecoin-project/go-paramfetch v0.0.0-20200102181131-b20d579f2878/go.mod h1:40kI2Gv16mwcRsHptI3OAV4nlOEU7wVDc4RgMylNFjU=
|
github.com/filecoin-project/go-paramfetch v0.0.0-20200102181131-b20d579f2878/go.mod h1:40kI2Gv16mwcRsHptI3OAV4nlOEU7wVDc4RgMylNFjU=
|
||||||
github.com/filecoin-project/go-sectorbuilder v0.0.0-20200107152336-0cbb2c483013 h1:OGpRq3HRxyrxZJtbNKCOsb5YTmc+RBLLwdAgwZfkRnY=
|
github.com/filecoin-project/go-sectorbuilder v0.0.0-20200107220006-3361d30ea5ab h1:bsrBNO1LwnhOLxPEXlSPal/WuY61mLJUCHYyD0NayHg=
|
||||||
github.com/filecoin-project/go-sectorbuilder v0.0.0-20200107152336-0cbb2c483013/go.mod h1:3OZ4E3B2OuwhJjtxR4r7hPU9bCfB+A+hm4alLEsaeDc=
|
github.com/filecoin-project/go-sectorbuilder v0.0.0-20200107220006-3361d30ea5ab/go.mod h1:3OZ4E3B2OuwhJjtxR4r7hPU9bCfB+A+hm4alLEsaeDc=
|
||||||
github.com/filecoin-project/go-statestore v0.0.0-20200102200712-1f63c701c1e5 h1:NZXq90YlfakSmB2/84dGr0AVmKYFA97+yyViBIgTFbk=
|
github.com/filecoin-project/go-statestore v0.0.0-20200102200712-1f63c701c1e5 h1:NZXq90YlfakSmB2/84dGr0AVmKYFA97+yyViBIgTFbk=
|
||||||
github.com/filecoin-project/go-statestore v0.0.0-20200102200712-1f63c701c1e5/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI=
|
github.com/filecoin-project/go-statestore v0.0.0-20200102200712-1f63c701c1e5/go.mod h1:LFc9hD+fRxPqiHiaqUEZOinUJB4WARkRfNl10O7kTnI=
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
|
Loading…
Reference in New Issue
Block a user