diff --git a/builtin/network.go b/builtin/network.go index 13923b60..615b93eb 100644 --- a/builtin/network.go +++ b/builtin/network.go @@ -51,6 +51,7 @@ var TotalFilecoin = big.Mul(big.NewIntUnsigned(2_000_000_000), TokenPrecision) var QualityBaseMultiplier = big.NewInt(10) // Quality multiplier for unverified deals in a sector +// DEPRECATED: This is no longer used, but is kept here for reference. var DealWeightMultiplier = big.NewInt(10) // Quality multiplier for verified deals in a sector diff --git a/builtin/v15/miner/policy.go b/builtin/v15/miner/policy.go index ccbf7667..e90bad27 100644 --- a/builtin/v15/miner/policy.go +++ b/builtin/v15/miner/policy.go @@ -141,30 +141,24 @@ const MinSectorExpiration = 180 * builtin.EpochsInDay // PARAM_SPEC // the associated seal proof's maximum lifetime. const MaxSectorExpirationExtension = 1278 * builtin.EpochsInDay // PARAM_SPEC -// DealWeight and VerifiedDealWeight are spacetime occupied by regular deals and verified deals in a sector. -// Sum of DealWeight and VerifiedDealWeight should be less than or equal to total SpaceTime of a sector. -// Sectors full of VerifiedDeals will have a SectorQuality of VerifiedDealWeightMultiplier/QualityBaseMultiplier. -// Sectors full of Deals will have a SectorQuality of DealWeightMultiplier/QualityBaseMultiplier. -// Sectors with neither will have a SectorQuality of QualityBaseMultiplier/QualityBaseMultiplier. -// SectorQuality of a sector is a weighted average of multipliers based on their proportions. -func QualityForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.SectorQuality { +// QualityForWeight calculates the quality of a sector with the given size, duration, and verified weight. +// VerifiedDealWeight is spacetime occupied by verified pieces in a sector. +// VerifiedDealWeight should be less than or equal to total SpaceTime of a sector. +// Sectors full of VerifiedDeals will have a BigInt of VerifiedDealWeightMultiplier/QualityBaseMultiplier. +// Sectors without VerifiedDeals will have a BigInt of QualityBaseMultiplier/QualityBaseMultiplier. +// BigInt of a sector is a weighted average of multipliers based on their proportions. +func QualityForWeight(size abi.SectorSize, duration abi.ChainEpoch, verifiedWeight abi.DealWeight) abi.SectorQuality { // sectorSpaceTime = size * duration sectorSpaceTime := big.Mul(big.NewIntUnsigned(uint64(size)), big.NewInt(int64(duration))) - // totalDealSpaceTime = dealWeight + verifiedWeight - totalDealSpaceTime := big.Add(dealWeight, verifiedWeight) - - // Base - all size * duration of non-deals - // weightedBaseSpaceTime = (sectorSpaceTime - totalDealSpaceTime) * QualityBaseMultiplier - weightedBaseSpaceTime := big.Mul(big.Sub(sectorSpaceTime, totalDealSpaceTime), builtin.QualityBaseMultiplier) - // Deal - all deal size * deal duration * 10 - // weightedDealSpaceTime = dealWeight * DealWeightMultiplier - weightedDealSpaceTime := big.Mul(dealWeight, builtin.DealWeightMultiplier) + // Base - all size * duration of non-verified deals + // weightedBaseSpaceTime = (sectorSpaceTime - verifiedWeight) * QualityBaseMultiplier + weightedBaseSpaceTime := big.Mul(big.Sub(sectorSpaceTime, verifiedWeight), builtin.QualityBaseMultiplier) // Verified - all verified deal size * verified deal duration * 100 // weightedVerifiedSpaceTime = verifiedWeight * VerifiedDealWeightMultiplier weightedVerifiedSpaceTime := big.Mul(verifiedWeight, builtin.VerifiedDealWeightMultiplier) // Sum - sum of all spacetime - // weightedSumSpaceTime = weightedBaseSpaceTime + weightedDealSpaceTime + weightedVerifiedSpaceTime - weightedSumSpaceTime := big.Sum(weightedBaseSpaceTime, weightedDealSpaceTime, weightedVerifiedSpaceTime) + // weightedSumSpaceTime = weightedBaseSpaceTime + weightedVerifiedSpaceTime + weightedSumSpaceTime := big.Sum(weightedBaseSpaceTime, weightedVerifiedSpaceTime) // scaledUpWeightedSumSpaceTime = weightedSumSpaceTime * 2^20 scaledUpWeightedSumSpaceTime := big.Lsh(weightedSumSpaceTime, builtin.SectorQualityPrecision) @@ -173,15 +167,15 @@ func QualityForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, } // The power for a sector size, committed duration, and weight. -func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower { - quality := QualityForWeight(size, duration, dealWeight, verifiedWeight) +func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, verifiedWeight abi.DealWeight) abi.StoragePower { + quality := QualityForWeight(size, duration, verifiedWeight) return big.Rsh(big.Mul(big.NewIntUnsigned(uint64(size)), quality), builtin.SectorQualityPrecision) } // The quality-adjusted power for a sector. func QAPowerForSector(size abi.SectorSize, sector *SectorOnChainInfo) abi.StoragePower { duration := sector.Expiration - sector.PowerBaseEpoch - return QAPowerForWeight(size, duration, sector.DealWeight, sector.VerifiedDealWeight) + return QAPowerForWeight(size, duration, sector.VerifiedDealWeight) } const MaxAggregatedSectors = 819 diff --git a/builtin/v15/miner/policy_test.go b/builtin/v15/miner/policy_test.go new file mode 100644 index 00000000..ea58fc2a --- /dev/null +++ b/builtin/v15/miner/policy_test.go @@ -0,0 +1,95 @@ +package miner_test + +import ( + "testing" + + 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" + "github.com/filecoin-project/go-state-types/builtin/v15/miner" + "github.com/stretchr/testify/require" +) + +/* Rust version: +#[test] +fn quality_is_independent_of_size_and_duration() { + // Quality of space with no deals. This doesn't depend on either the sector size or duration. + let empty_quality = BigInt::from(1 << SECTOR_QUALITY_PRECISION); + // Quality space filled with verified deals. + let verified_quality = &empty_quality + * (VERIFIED_DEAL_WEIGHT_MULTIPLIER.clone() / QUALITY_BASE_MULTIPLIER.clone()); + // Quality space half filled with verified deals. + let half_verified_quality = + &empty_quality / BigInt::from(2) + &verified_quality / BigInt::from(2); + + let size_range: Vec = vec![ + SectorSize::_2KiB, + SectorSize::_8MiB, + SectorSize::_512MiB, + SectorSize::_32GiB, + SectorSize::_64GiB, + ]; + let duration_range: Vec = vec![ + ChainEpoch::from(1), + ChainEpoch::from(10), + ChainEpoch::from(1000), + 1000 * EPOCHS_IN_DAY, + ]; + + for size in size_range { + for duration in &duration_range { + let sector_weight = weight(size, *duration); + assert_eq!(empty_quality, quality_for_weight(size, *duration, &BigInt::zero())); + assert_eq!(verified_quality, quality_for_weight(size, *duration, §or_weight)); + assert_eq!( + half_verified_quality, + quality_for_weight( + size, + *duration, + §or_weight.checked_div(&BigInt::from(2)).unwrap() + ) + ); + } + } +} +*/ + +func TestQualityForWeight(t *testing.T) { + emptyQuality := big.NewInt(1 << builtin.SectorQualityPrecision) + verifiedQuality := big.Mul(emptyQuality, big.Div(builtin.VerifiedDealWeightMultiplier, builtin.QualityBaseMultiplier)) + halfVerifiedQuality := big.Add(big.Div(emptyQuality, big.NewInt(2)), big.Div(verifiedQuality, big.NewInt(2))) + + sizeRange := []abi.SectorSize{ + abi.SectorSize(2 << 10), + abi.SectorSize(8 << 20), + abi.SectorSize(512 << 20), + abi.SectorSize(32 << 30), + abi.SectorSize(64 << 30), + } + durationRange := []abi.ChainEpoch{ + abi.ChainEpoch(1), + abi.ChainEpoch(10), + abi.ChainEpoch(1000), + 1000 * builtin.EpochsInDay, + } + + for _, size := range sizeRange { + for _, duration := range durationRange { + sectorWeight := big.NewInt(int64(size) * int64(duration)) + require.Equal(t, emptyQuality, miner.QualityForWeight(size, duration, big.Zero())) + require.Equal(t, verifiedQuality, miner.QualityForWeight(size, duration, sectorWeight)) + require.Equal(t, halfVerifiedQuality, miner.QualityForWeight(size, duration, big.Div(sectorWeight, big.NewInt(2)))) + } + } +} + +/* +fn weight(size: SectorSize, duration: ChainEpoch) -> BigInt { + BigInt::from(size as u64) * BigInt::from(duration) +} + +fn weight_with_size_as_bigint(size: BigInt, duration: ChainEpoch) -> BigInt { + size * BigInt::from(duration) +} + +*/