diff --git a/builtin/v16/miner/cbor_gen.go b/builtin/v16/miner/cbor_gen.go index b47aa51a..80c5c76d 100644 --- a/builtin/v16/miner/cbor_gen.go +++ b/builtin/v16/miner/cbor_gen.go @@ -886,7 +886,7 @@ func (t *Deadlines) UnmarshalCBOR(r io.Reader) (err error) { return nil } -var lengthBufDeadline = []byte{139} +var lengthBufDeadline = []byte{141} func (t *Deadline) MarshalCBOR(w io.Writer) error { if t == nil { @@ -963,6 +963,15 @@ func (t *Deadline) MarshalCBOR(w io.Writer) error { return xerrors.Errorf("failed to write cid field t.OptimisticPoStSubmissionsSnapshot: %w", err) } + // t.LivePower (miner.PowerPair) (struct) + if err := t.LivePower.MarshalCBOR(cw); err != nil { + return err + } + + // t.DailyFee (big.Int) (struct) + if err := t.DailyFee.MarshalCBOR(cw); err != nil { + return err + } return nil } @@ -985,7 +994,7 @@ func (t *Deadline) UnmarshalCBOR(r io.Reader) (err error) { return fmt.Errorf("cbor input should be of type array") } - if extra != 11 { + if extra != 13 { return fmt.Errorf("cbor input had wrong number of fields") } @@ -1115,6 +1124,24 @@ func (t *Deadline) UnmarshalCBOR(r io.Reader) (err error) { t.OptimisticPoStSubmissionsSnapshot = c + } + // t.LivePower (miner.PowerPair) (struct) + + { + + if err := t.LivePower.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.LivePower: %w", err) + } + + } + // t.DailyFee (big.Int) (struct) + + { + + if err := t.DailyFee.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.DailyFee: %w", err) + } + } return nil } @@ -1323,7 +1350,7 @@ func (t *Partition) UnmarshalCBOR(r io.Reader) (err error) { return nil } -var lengthBufExpirationSet = []byte{133} +var lengthBufExpirationSet = []byte{134} func (t *ExpirationSet) MarshalCBOR(w io.Writer) error { if t == nil { @@ -1361,6 +1388,11 @@ func (t *ExpirationSet) MarshalCBOR(w io.Writer) error { if err := t.FaultyPower.MarshalCBOR(cw); err != nil { return err } + + // t.FeeDeduction (big.Int) (struct) + if err := t.FeeDeduction.MarshalCBOR(cw); err != nil { + return err + } return nil } @@ -1383,10 +1415,16 @@ func (t *ExpirationSet) UnmarshalCBOR(r io.Reader) (err error) { return fmt.Errorf("cbor input should be of type array") } - if extra != 5 { - return fmt.Errorf("cbor input had wrong number of fields") + if extra > 6 { + return fmt.Errorf("cbor input has too many fields %d > 6", extra) } + if extra < 5 { + return fmt.Errorf("cbor input has too few fields %d < 5", extra) + } + + fieldCount := extra + // t.OnTimeSectors (bitfield.BitField) (struct) { @@ -1431,6 +1469,18 @@ func (t *ExpirationSet) UnmarshalCBOR(r io.Reader) (err error) { return xerrors.Errorf("unmarshaling t.FaultyPower: %w", err) } + } + // t.FeeDeduction (big.Int) (struct) + if fieldCount < 6 { + return nil + } + + { + + if err := t.FeeDeduction.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.FeeDeduction: %w", err) + } + } return nil } @@ -1894,7 +1944,7 @@ func (t *SectorPreCommitInfo) UnmarshalCBOR(r io.Reader) (err error) { return nil } -var lengthBufSectorOnChainInfo = []byte{143} +var lengthBufSectorOnChainInfo = []byte{144} func (t *SectorOnChainInfo) MarshalCBOR(w io.Writer) error { if t == nil { @@ -1931,15 +1981,15 @@ func (t *SectorOnChainInfo) MarshalCBOR(w io.Writer) error { return xerrors.Errorf("failed to write cid field t.SealedCID: %w", err) } - // t.DealIDs ([]abi.DealID) (slice) - if len(t.DealIDs) > 8192 { - return xerrors.Errorf("Slice value in field t.DealIDs was too long") + // t.DeprecatedDealIDs ([]abi.DealID) (slice) + if len(t.DeprecatedDealIDs) > 8192 { + return xerrors.Errorf("Slice value in field t.DeprecatedDealIDs was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.DealIDs))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.DeprecatedDealIDs))); err != nil { return err } - for _, v := range t.DealIDs { + for _, v := range t.DeprecatedDealIDs { if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(v)); err != nil { return err @@ -2028,6 +2078,10 @@ func (t *SectorOnChainInfo) MarshalCBOR(w io.Writer) error { return err } + // t.DailyFee (big.Int) (struct) + if err := t.DailyFee.MarshalCBOR(cw); err != nil { + return err + } return nil } @@ -2050,10 +2104,16 @@ func (t *SectorOnChainInfo) UnmarshalCBOR(r io.Reader) (err error) { return fmt.Errorf("cbor input should be of type array") } - if extra != 15 { - return fmt.Errorf("cbor input had wrong number of fields") + if extra > 16 { + return fmt.Errorf("cbor input has too many fields %d > 16", extra) + } + + if extra < 15 { + return fmt.Errorf("cbor input has too few fields %d < 15", extra) } + fieldCount := extra + // t.SectorNumber (abi.SectorNumber) (uint64) { @@ -2105,7 +2165,7 @@ func (t *SectorOnChainInfo) UnmarshalCBOR(r io.Reader) (err error) { t.SealedCID = c } - // t.DealIDs ([]abi.DealID) (slice) + // t.DeprecatedDealIDs ([]abi.DealID) (slice) maj, extra, err = cr.ReadHeader() if err != nil { @@ -2113,7 +2173,7 @@ func (t *SectorOnChainInfo) UnmarshalCBOR(r io.Reader) (err error) { } if extra > 8192 { - return fmt.Errorf("t.DealIDs: array too large (%d)", extra) + return fmt.Errorf("t.DeprecatedDealIDs: array too large (%d)", extra) } if maj != cbg.MajArray { @@ -2121,7 +2181,7 @@ func (t *SectorOnChainInfo) UnmarshalCBOR(r io.Reader) (err error) { } if extra > 0 { - t.DealIDs = make([]abi.DealID, extra) + t.DeprecatedDealIDs = make([]abi.DealID, extra) } for i := 0; i < int(extra); i++ { @@ -2142,7 +2202,7 @@ func (t *SectorOnChainInfo) UnmarshalCBOR(r io.Reader) (err error) { if maj != cbg.MajUnsignedInt { return fmt.Errorf("wrong type for uint64 field") } - t.DealIDs[i] = abi.DealID(extra) + t.DeprecatedDealIDs[i] = abi.DealID(extra) } @@ -2312,6 +2372,18 @@ func (t *SectorOnChainInfo) UnmarshalCBOR(r io.Reader) (err error) { } t.Flags = SectorOnChainInfoFlags(extra) + } + // t.DailyFee (big.Int) (struct) + if fieldCount < 16 { + return nil + } + + { + + if err := t.DailyFee.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.DailyFee: %w", err) + } + } return nil } diff --git a/builtin/v16/miner/deadline_state.go b/builtin/v16/miner/deadline_state.go index 7789913a..d177b8dd 100644 --- a/builtin/v16/miner/deadline_state.go +++ b/builtin/v16/miner/deadline_state.go @@ -5,6 +5,7 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/go-bitfield" + abi "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/builtin/v16/util/adt" xc "github.com/filecoin-project/go-state-types/exitcode" @@ -76,6 +77,14 @@ type Deadline struct { // These proofs may be disputed via DisputeWindowedPoSt. Successfully // disputed window PoSts are removed from the snapshot. OptimisticPoStSubmissionsSnapshot cid.Cid + + // Memoized sum of all non-terminated power in partitions, including active, faulty, and + // unproven. Used to cap the daily fee as a proportion of expected block reward. + LivePower PowerPair + + // Memoized sum of daily fee payable to the network for the active sectors + // in this deadline. + DailyFee abi.TokenAmount } type WindowedPoSt struct { diff --git a/builtin/v16/miner/invariants.go b/builtin/v16/miner/invariants.go index 091e469e..d2f0332a 100644 --- a/builtin/v16/miner/invariants.go +++ b/builtin/v16/miner/invariants.go @@ -97,7 +97,7 @@ func CheckStateInvariants(st *State, store adt.Store, balance abi.TokenAmount) ( acc.Require(allocated, "on chain sector's sector number has not been allocated %d", sno) - for _, dealID := range sector.DealIDs { + for _, dealID := range sector.DeprecatedDealIDs { minerSummary.Deals[dealID] = DealSummary{ SectorStart: sector.Activation, SectorExpiration: sector.Expiration, diff --git a/builtin/v16/miner/miner_state.go b/builtin/v16/miner/miner_state.go index 57cd5c58..05dc7963 100644 --- a/builtin/v16/miner/miner_state.go +++ b/builtin/v16/miner/miner_state.go @@ -169,7 +169,7 @@ type SectorOnChainInfo struct { SectorNumber abi.SectorNumber SealProof abi.RegisteredSealProof // The seal proof type implies the PoSt proof/s SealedCID cid.Cid // CommR - DealIDs []abi.DealID + DeprecatedDealIDs []abi.DealID Activation abi.ChainEpoch // Epoch during which the sector proof was accepted Expiration abi.ChainEpoch // Epoch during which the sector expires DealWeight abi.DealWeight // Integral of active deals over sector lifetime @@ -181,6 +181,19 @@ type SectorOnChainInfo struct { ReplacedDayReward abi.TokenAmount // Day reward of this sector before its power was most recently updated SectorKeyCID *cid.Cid // The original SealedSectorCID, only gets set on the first ReplicaUpdate Flags SectorOnChainInfoFlags // Additional flags + // The total fee payable per day for this sector. The value of this field is set at the time of + // sector activation, extension and whenever a sector's QAP is changed. This fee is payable for + // the lifetime of the sector and is aggregated in the deadline's `daily_fee` field. + // + // This field is not included in the serialised form of the struct prior to the activation of + // FIP-0100, and is added as the 16th element of the array after that point only for new sectors + // or sectors that are updated after that point. For old sectors, the value of this field will + // always be zero. + // + // This field is OPTIONAL, meaning that it may present as a nil BigInt (not a nil pointer). + // If FeeDeduction.Nil() then it should be treated the same as if it were zero (but cannot be + // used in place of a zero value). + DailyFee abi.TokenAmount `cborgen:"optional"` } func (st *State) GetInfo(store adt.Store) (*MinerInfo, error) { diff --git a/builtin/v16/miner/miner_types.go b/builtin/v16/miner/miner_types.go index 7368a3c2..095a4503 100644 --- a/builtin/v16/miner/miner_types.go +++ b/builtin/v16/miner/miner_types.go @@ -252,6 +252,13 @@ type ExpirationSet struct { OnTimePledge abi.TokenAmount // Pledge total for the on-time sectors ActivePower PowerPair // Power that is currently active (not faulty) FaultyPower PowerPair // Power that is currently faulty + // Adjustment to the daily fee recorded for the deadline associated with this expiration set + // to account for expiring sectors. + // + // This field is OPTIONAL, meaning that it may present as a nil BigInt (not a nil pointer). + // If FeeDeduction.Nil() then it should be treated the same as if it were zero (but cannot be + // used in place of a zero value). + FeeDeduction abi.TokenAmount `cborgen:"optional"` } // A queue of expiration sets by epoch, representing the on-time or early termination epoch for a collection of sectors. diff --git a/builtin/v16/miner/miner_types_test.go b/builtin/v16/miner/miner_types_test.go index 1e49a6e1..061a5e3a 100644 --- a/builtin/v16/miner/miner_types_test.go +++ b/builtin/v16/miner/miner_types_test.go @@ -5,12 +5,19 @@ import ( "encoding/hex" "testing" + "github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/go-state-types/builtin" cid "github.com/ipfs/go-cid" "github.com/stretchr/testify/require" ) -// Test to match with Rust fil_actor_miner::serialization +// Tests to match with Rust fil_actor_miner::serialization + +// defaultCid as a Rust Default::default() value +var defaultCid = cid.MustParse("baeaaaaa") + func TestSerializationProveCommitSectorsNIParams(t *testing.T) { testCases := []struct { params ProveCommitSectorsNIParams @@ -91,3 +98,273 @@ func TestSerializationProveCommitSectorsNIParams(t *testing.T) { }) } } + +func TestSectorOnChainInfo(t *testing.T) { + sectorKey := cid.MustParse("baga6ea4seaaqc") + zero := big.Zero() + + testCases := []struct { + sector SectorOnChainInfo + readHex string + writeHex string + }{ + { + sector: SectorOnChainInfo{ + SealProof: -1, + SealedCID: defaultCid, + DealWeight: zero, + VerifiedDealWeight: zero, + InitialPledge: zero, + ExpectedDayReward: zero, + ExpectedStoragePledge: zero, + ReplacedDayReward: zero, + DailyFee: zero, + }, + // [0,-1,{"/":"baeaaaaa"},[],0,0,[],[],[],[],[],0,[],null,0,[]] + readHex: "900020d82a45000100000080000040404040400040f60040", + // same on write as read + writeHex: "900020d82a45000100000080000040404040400040f60040", + }, + { + sector: SectorOnChainInfo{ + SectorNumber: 1, + SealProof: abi.RegisteredSealProof_StackedDrg32GiBV1_1, + SealedCID: cid.MustParse("bagboea4seaaqa"), + DeprecatedDealIDs: nil, + Activation: 2, + Expiration: 3, + DealWeight: big.NewInt(4), + VerifiedDealWeight: big.NewInt(5), + InitialPledge: filWhole(6), + ExpectedDayReward: filWhole(7), + ExpectedStoragePledge: filWhole(8), + PowerBaseEpoch: 9, + ReplacedDayReward: filWhole(10), + SectorKeyCID: nil, + Flags: 0, + DailyFee: filWhole(11), + }, + // '[1,8,{"/":"bagboea4seaaqa"},[],2,3,[AAQ],[AAU],[AFNESDXsWAAA],[AGEk/umTvAAA],[AG8FtZ07IAAA],9,[AIrHIwSJ6AAA],null,0,[AJin2bgxTAAA]]' + readHex: "900108d82a49000182e20392200100800203420004420005490053444835ec58000049006124fee993bc000049006f05b59d3b2000000949008ac7230489e80000f600490098a7d9b8314c0000", + // same on write as read + writeHex: "900108d82a49000182e20392200100800203420004420005490053444835ec58000049006124fee993bc000049006f05b59d3b2000000949008ac7230489e80000f600490098a7d9b8314c0000", + }, + { + sector: SectorOnChainInfo{ + SectorNumber: 1, + SealProof: abi.RegisteredSealProof_StackedDrg32GiBV1_1, + SealedCID: cid.MustParse("bagboea4seaaqa"), + DeprecatedDealIDs: nil, + Activation: 2, + Expiration: 3, + DealWeight: big.NewInt(4), + VerifiedDealWeight: big.NewInt(5), + InitialPledge: filWhole(6), + ExpectedDayReward: filWhole(7), + ExpectedStoragePledge: filWhole(8), + PowerBaseEpoch: 9, + ReplacedDayReward: filWhole(10), + SectorKeyCID: §orKey, + Flags: SIMPLE_QA_POWER, + DailyFee: filWhole(11), + }, + // [1,8,{"/":"bagboea4seaaqa"},[],2,3,[AAQ],[AAU],[AFNESDXsWAAA],[AGEk/umTvAAA],[AG8FtZ07IAAA],9,[AIrHIwSJ6AAA],{"/":"baga6ea4seaaqc"},1,[AJin2bgxTAAA]] + readHex: "900108d82a49000182e20392200100800203420004420005490053444835ec58000049006124fee993bc000049006f05b59d3b2000000949008ac7230489e80000d82a49000181e2039220010101490098a7d9b8314c0000", + // same on write as read + writeHex: "900108d82a49000182e20392200100800203420004420005490053444835ec58000049006124fee993bc000049006f05b59d3b2000000949008ac7230489e80000d82a49000181e2039220010101490098a7d9b8314c0000", + }, + { + // old format stored on chain but materialised as the new format with a default value at the end + sector: SectorOnChainInfo{ + SectorNumber: 1, + SealProof: abi.RegisteredSealProof_StackedDrg64GiBV1_1, + SealedCID: cid.MustParse("bagboea4seaaqa"), + DeprecatedDealIDs: nil, + Activation: 2, + Expiration: 3, + DealWeight: big.NewInt(4), + VerifiedDealWeight: big.NewInt(5), + InitialPledge: filWhole(6), + ExpectedDayReward: filWhole(7), + ExpectedStoragePledge: filWhole(8), + PowerBaseEpoch: 9, + ReplacedDayReward: filWhole(10), + SectorKeyCID: nil, + Flags: SIMPLE_QA_POWER, + DailyFee: big.Int{}, // default, not present in the binary + }, + // [1,9,{"/":"bagboea4seaaqa"},[],2,3,[AAQ],[AAU],[AFNESDXsWAAA],[AGEk/umTvAAA],[AG8FtZ07IAAA],9,[AIrHIwSJ6AAA],null,1] + readHex: "8f0109d82a49000182e20392200100800203420004420005490053444835ec58000049006124fee993bc000049006f05b59d3b2000000949008ac7230489e80000f601", + // extra field at the end on write, zero BigInt (bytes) for daily_fee + // [1,9,{"/":"bagboea4seaaqa"},[],2,3,[AAQ],[AAU],[AFNESDXsWAAA],[AGEk/umTvAAA],[AG8FtZ07IAAA],9,[AIrHIwSJ6AAA],null,1,[]] + writeHex: "900109d82a49000182e20392200100800203420004420005490053444835ec58000049006124fee993bc000049006f05b59d3b2000000949008ac7230489e80000f60140", + }, + } + + for _, tc := range testCases { + t.Run("", func(t *testing.T) { + req := require.New(t) + + // write + var buf bytes.Buffer + req.NoError(tc.sector.MarshalCBOR(&buf)) + req.Equal(tc.writeHex, hex.EncodeToString(buf.Bytes())) + + // read + byts, err := hex.DecodeString(tc.readHex) + req.NoError(err) + var rt SectorOnChainInfo + req.NoError(rt.UnmarshalCBOR(bytes.NewReader(byts))) + req.Equal(tc.sector, rt) + }) + } +} + +func TestExpirationSet(t *testing.T) { + zero := big.Zero() + + testCases := []struct { + set ExpirationSet + readHex string + writeHex string + }{ + { + set: ExpirationSet{ + OnTimeSectors: bitfield.New(), + EarlySectors: bitfield.New(), + OnTimePledge: zero, + ActivePower: NewPowerPairZero(), + FaultyPower: NewPowerPairZero(), + FeeDeduction: zero, + }, + // [[],[],[],[[],[]],[[],[]],[]] + readHex: "8640404082404082404040", + // same on write as read + writeHex: "8640404082404082404040", + }, + { + set: ExpirationSet{ + OnTimeSectors: bfrt(0), + EarlySectors: bfrt(1), + OnTimePledge: filWhole(2), + ActivePower: NewPowerPair(big.NewInt(3), big.NewInt(4)), + FaultyPower: NewPowerPair(big.NewInt(5), big.NewInt(6)), + FeeDeduction: filWhole(7), + }, + // [[DA],[GA],[ABvBbWdOyAAA],[[AAM],[AAQ]],[[AAU],[AAY]],[AGEk/umTvAAA]] + readHex: "86410c411849001bc16d674ec80000824200034200048242000542000649006124fee993bc0000", + // same on write as read + writeHex: "86410c411849001bc16d674ec80000824200034200048242000542000649006124fee993bc0000", + }, + { + set: ExpirationSet{ + OnTimeSectors: bfrt(0), + EarlySectors: bfrt(1), + OnTimePledge: filWhole(2), + ActivePower: NewPowerPair(big.NewInt(3), big.NewInt(4)), + FaultyPower: NewPowerPair(big.NewInt(5), big.NewInt(6)), + FeeDeduction: big.Int{}, + }, + // [[DA],[GA],[ABvBbWdOyAAA],[[AAM],[AAQ]],[[AAU],[AAY]]] + readHex: "85410c411849001bc16d674ec800008242000342000482420005420006", + // [[DA],[GA],[ABvBbWdOyAAA],[[AAM],[AAQ]],[[AAU],[AAY]],[]] + writeHex: "86410c411849001bc16d674ec80000824200034200048242000542000640", + }, + } + + for _, tc := range testCases { + t.Run("", func(t *testing.T) { + req := require.New(t) + + // write + var buf bytes.Buffer + req.NoError(tc.set.MarshalCBOR(&buf)) + req.Equal(tc.writeHex, hex.EncodeToString(buf.Bytes())) + + // read + byts, err := hex.DecodeString(tc.readHex) + req.NoError(err) + var rt ExpirationSet + req.NoError(rt.UnmarshalCBOR(bytes.NewReader(byts))) + req.Equal(tc.set, rt) + }) + } +} + +func TestDeadline(t *testing.T) { + zero := big.Zero() + + testCases := []struct { + deadline Deadline + hex string + }{ + { + deadline: Deadline{ + Partitions: defaultCid, + ExpirationsEpochs: defaultCid, + PartitionsPoSted: bfrt(), + EarlyTerminations: bfrt(), + FaultyPower: NewPowerPairZero(), + OptimisticPoStSubmissions: defaultCid, + SectorsSnapshot: defaultCid, + PartitionsSnapshot: defaultCid, + OptimisticPoStSubmissionsSnapshot: defaultCid, + LivePower: NewPowerPairZero(), + DailyFee: zero, + }, + // [baeaaaaa,baeaaaaa,[],[],0,0,[[],[]],baeaaaaa,baeaaaaa,baeaaaaa,baeaaaaa,[[],[]],[]] + hex: "8dd82a450001000000d82a45000100000040400000824040d82a450001000000d82a450001000000d82a450001000000d82a45000100000082404040", + }, + { + deadline: Deadline{ + Partitions: cid.MustParse("bagboea4seaaqa"), + ExpirationsEpochs: cid.MustParse("bagboea4seaaqc"), + PartitionsPoSted: bfrt(0), + EarlyTerminations: bfrt(1), + LiveSectors: 2, + TotalSectors: 3, + FaultyPower: NewPowerPair(big.NewInt(4), big.NewInt(5)), + OptimisticPoStSubmissions: cid.MustParse("bagboea4seaaqe"), + SectorsSnapshot: cid.MustParse("bagboea4seaaqg"), + PartitionsSnapshot: cid.MustParse("bagboea4seaaqi"), + OptimisticPoStSubmissionsSnapshot: cid.MustParse("bagboea4seaaqk"), + LivePower: NewPowerPair(big.NewInt(6), big.NewInt(7)), + DailyFee: filWhole(8), + }, + // [bagboea4seaaqa,bagboea4seaaqc,[DA],[GA],2,3,[[AAQ],[AAU]],bagboea4seaaqe,bagboea4seaaqg,bagboea4seaaqi,bagboea4seaaqk,[[AAY],[AAc]],[AG8FtZ07IAAA]] + hex: "8dd82a49000182e20392200100d82a49000182e20392200101410c4118020382420004420005d82a49000182e20392200102d82a49000182e20392200103d82a49000182e20392200104d82a49000182e203922001058242000642000749006f05b59d3b200000", + }, + } + + for _, tc := range testCases { + t.Run("", func(t *testing.T) { + req := require.New(t) + + var buf bytes.Buffer + req.NoError(tc.deadline.MarshalCBOR(&buf)) + req.Equal(tc.hex, hex.EncodeToString(buf.Bytes())) + var rt Deadline + req.NoError(rt.UnmarshalCBOR(&buf)) + req.Equal(tc.deadline, rt) + }) + } +} + +func filWhole(i int64) abi.TokenAmount { + return big.Mul(big.NewInt(i), builtin.TokenPrecision) +} + +// bfrt makes a bitfield from a list of integers and round-trips it through encoding +// so that the internal representation is set properly for a deep equals() test +func bfrt(b ...uint64) bitfield.BitField { + bf := bitfield.NewFromSet(b) + var buf bytes.Buffer + if err := bf.MarshalCBOR(&buf); err != nil { + panic(err) + } + var rt bitfield.BitField + if err := rt.UnmarshalCBOR(&buf); err != nil { + panic(err) + } + return rt +} diff --git a/go.mod b/go.mod index 0b396433..35f02784 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/multiformats/go-multihash v0.2.3 github.com/multiformats/go-varint v0.0.7 github.com/stretchr/testify v1.10.0 - github.com/whyrusleeping/cbor-gen v0.3.0 + github.com/whyrusleeping/cbor-gen v0.3.1 golang.org/x/crypto v0.35.0 golang.org/x/sync v0.11.0 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da diff --git a/go.sum b/go.sum index 6d4b5822..6309125a 100644 --- a/go.sum +++ b/go.sum @@ -103,8 +103,8 @@ github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60Nt github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/cbor-gen v0.0.0-20200414195334-429a0b5e922e/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= -github.com/whyrusleeping/cbor-gen v0.3.0 h1:BR7/2RPYdqzGyHsJvC/lm+g8qTlm4SD9GHA8++CJT8o= -github.com/whyrusleeping/cbor-gen v0.3.0/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so= +github.com/whyrusleeping/cbor-gen v0.3.1 h1:82ioxmhEYut7LBVGhGq8xoRkXPLElVuh5mV67AFfdv0= +github.com/whyrusleeping/cbor-gen v0.3.1/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so= gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b h1:CzigHMRySiX3drau9C6Q5CAbNIApmLdat5jPMqChvDA= gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8= gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q=