From f5a2d998bfbdc3727288f734881237f308c229a8 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Tue, 17 Sep 2019 16:20:08 +0200 Subject: [PATCH] Add BitField with RLE License: MIT Signed-off-by: Jakub Sztandera --- chain/actors/actor_miner.go | 16 ++++++-- chain/actors/cbor_gen.go | 46 ++++++++++++++++++++- chain/types/bitfield.go | 82 +++++++++++++++++++++++++++++++++++++ chain/types/cbor_gen.go | 2 +- go.sum | 2 - 5 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 chain/types/bitfield.go diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index bde5b815d..6a3dd3ec8 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -39,10 +39,20 @@ type StorageMinerActorState struct { ProvingSet cid.Cid ProvingSetSize uint64 - // Sectors reported during the last PoSt submission as being 'done'. The collateral - // for them is still being held until the next PoSt submission in case early sector + // Faulty sectors reported since last SubmitPost, + // up to the current proving period's challenge time. + CurrentFaultSet types.BitField + + // Faults submitted after the current proving period's challenge time, + // but before the PoSt for that period is submitted. + // These become the currentFaultSet when a PoSt is submitted. + NextFaultSet types.BitField + + // Sectors reported during the last PoSt submission as being 'done'. + // The collateral for them is still being held until + // the next PoSt submission in case early sector // removal penalization is needed. - //NextDoneSet BitField + NextDoneSet types.BitField // Deals this miner has been slashed for since the last post submission. //TODO: unsupported map key type "Cid" (if you want to use struct keys, your atlas needs a transform to string) diff --git a/chain/actors/cbor_gen.go b/chain/actors/cbor_gen.go index f971b6108..381f22b7b 100644 --- a/chain/actors/cbor_gen.go +++ b/chain/actors/cbor_gen.go @@ -197,7 +197,7 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write([]byte{139}); err != nil { + if _, err := w.Write([]byte{142}); err != nil { return err } @@ -239,6 +239,21 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error { return err } + // t.t.CurrentFaultSet (types.BitField) + if err := t.CurrentFaultSet.MarshalCBOR(w); err != nil { + return err + } + + // t.t.NextFaultSet (types.BitField) + if err := t.NextFaultSet.MarshalCBOR(w); err != nil { + return err + } + + // t.t.NextDoneSet (types.BitField) + if err := t.NextDoneSet.MarshalCBOR(w); err != nil { + return err + } + // t.t.Power (types.BigInt) if err := t.Power.MarshalCBOR(w); err != nil { return err @@ -272,7 +287,7 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input should be of type array") } - if extra != 11 { + if extra != 14 { return fmt.Errorf("cbor input had wrong number of fields") } @@ -350,6 +365,33 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("wrong type for uint64 field") } t.ProvingSetSize = extra + // t.t.CurrentFaultSet (types.BitField) + + { + + if err := t.CurrentFaultSet.UnmarshalCBOR(br); err != nil { + return err + } + + } + // t.t.NextFaultSet (types.BitField) + + { + + if err := t.NextFaultSet.UnmarshalCBOR(br); err != nil { + return err + } + + } + // t.t.NextDoneSet (types.BitField) + + { + + if err := t.NextDoneSet.UnmarshalCBOR(br); err != nil { + return err + } + + } // t.t.Power (types.BigInt) { diff --git a/chain/types/bitfield.go b/chain/types/bitfield.go new file mode 100644 index 000000000..f708c2733 --- /dev/null +++ b/chain/types/bitfield.go @@ -0,0 +1,82 @@ +package types + +import ( + "fmt" + "io" + + "github.com/filecoin-project/go-lotus/extern/rleplus" + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" +) + +type BitField struct { + bits map[uint64]struct{} +} + +// Set ...s bit in the BitField +func (bf BitField) Set(bit uint64) { + bf.bits[bit] = struct{}{} +} + +// Clear ...s bit in the BitField +func (bf BitField) Clear(bit uint64) { + delete(bf.bits, bit) +} + +// Has checkes if bit is set in the BitField +func (bf BitField) Has(bit uint64) bool { + _, ok := bf.bits[bit] + return ok +} + +func (bf BitField) MarshalCBOR(w io.Writer) error { + ints := make([]uint64, 0, len(bf.bits)) + for i := range bf.bits { + ints = append(ints, i) + } + + rle, _, err := rleplus.Encode(ints) // Encode sorts internally + if err != nil { + return err + } + + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(rle)))); err != nil { + return err + } + if _, err = w.Write(rle); err != nil { + return xerrors.Errorf("writing rle: %w", err) + } + return nil +} + +func (bf *BitField) UnmarshalCBOR(r io.Reader) error { + br := cbg.GetPeeker(r) + + maj, extra, err := cbg.CborReadHeader(br) + if err != nil { + return err + } + if extra > 8192 { + return fmt.Errorf("array too large") + } + + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + rle := make([]byte, extra) + if _, err := io.ReadFull(br, rle); err != nil { + return err + } + + ints, err := rleplus.Decode(rle) + if err != nil { + return xerrors.Errorf("could not decode rle+: %w", err) + } + bf.bits = make(map[uint64]struct{}) + for _, i := range ints { + bf.bits[i] = struct{}{} + } + + return nil +} diff --git a/chain/types/cbor_gen.go b/chain/types/cbor_gen.go index ab6f616dc..81a23081c 100644 --- a/chain/types/cbor_gen.go +++ b/chain/types/cbor_gen.go @@ -5,7 +5,7 @@ import ( "io" "math" - cid "github.com/ipfs/go-cid" + "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" ) diff --git a/go.sum b/go.sum index f644c281b..1059a4470 100644 --- a/go.sum +++ b/go.sum @@ -601,9 +601,7 @@ github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboa github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba h1:X4n8JG2e2biEZZXdBKt9HX7DN3bYGFUqljqqy0DqgnY= github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba/go.mod h1:CHQnYnQUEPydYCwuy8lmTHfGmdw9TKrhWV0xLx8l0oM= -github.com/whyrusleeping/cbor-gen v0.0.0-20190910031516-c1cbffdb01bb h1:8yBVx6dgk1GfkiWOQ+RbeDDBLCOZxOtmZ949O2uj5H4= github.com/whyrusleeping/cbor-gen v0.0.0-20190910031516-c1cbffdb01bb/go.mod h1:xdlJQaiqipF0HW+Mzpg7XRM3fWbGvfgFlcppuvlkIvY= -github.com/whyrusleeping/cbor-gen v0.0.0-20190917003517-d78d67427694 h1:Bjfm012LwDvjZvjPDU/oHwm7uX5U/yRHZaQt6gtbGlI= github.com/whyrusleeping/cbor-gen v0.0.0-20190917003517-d78d67427694/go.mod h1:xdlJQaiqipF0HW+Mzpg7XRM3fWbGvfgFlcppuvlkIvY= github.com/whyrusleeping/cbor-gen v0.0.0-20190917010546-c55df54645cb h1:Lc5MOczpVOeI/KwFoib6BMBQ1PfFxMzm/yOUfEeQP+o= github.com/whyrusleeping/cbor-gen v0.0.0-20190917010546-c55df54645cb/go.mod h1:xdlJQaiqipF0HW+Mzpg7XRM3fWbGvfgFlcppuvlkIvY=