Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust various CLI display ratios to arbitrary precision #6309

Merged
merged 4 commits into from
Jun 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions chain/types/bigint.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ func BigDiv(a, b BigInt) BigInt {
return BigInt{Int: big.NewInt(0).Div(a.Int, b.Int)}
}

func BigDivFloat(num, den BigInt) float64 {
res, _ := new(big.Rat).SetFrac(num.Int, den.Int).Float64()
return res
}

func BigMod(a, b BigInt) BigInt {
return BigInt{Int: big.NewInt(0).Mod(a.Int, b.Int)}
}
Expand Down
26 changes: 19 additions & 7 deletions cli/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,18 +183,23 @@ var StateMinerInfo = &cli.Command{
return err
}

rpercI := types.BigDiv(types.BigMul(pow.MinerPower.RawBytePower, types.NewInt(1000000)), pow.TotalPower.RawBytePower)
qpercI := types.BigDiv(types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(1000000)), pow.TotalPower.QualityAdjPower)

fmt.Printf("Byte Power: %s / %s (%0.4f%%)\n",
color.BlueString(types.SizeStr(pow.MinerPower.RawBytePower)),
types.SizeStr(pow.TotalPower.RawBytePower),
float64(rpercI.Int64())/10000)
types.BigDivFloat(
types.BigMul(pow.MinerPower.RawBytePower, big.NewInt(100)),
pow.TotalPower.RawBytePower,
),
)

fmt.Printf("Actual Power: %s / %s (%0.4f%%)\n",
color.GreenString(types.DeciStr(pow.MinerPower.QualityAdjPower)),
types.DeciStr(pow.TotalPower.QualityAdjPower),
float64(qpercI.Int64())/10000)
types.BigDivFloat(
types.BigMul(pow.MinerPower.QualityAdjPower, big.NewInt(100)),
pow.TotalPower.QualityAdjPower,
),
)

fmt.Println()

Expand Down Expand Up @@ -302,8 +307,15 @@ var StatePowerCmd = &cli.Command{
tp := power.TotalPower
if cctx.Args().Present() {
mp := power.MinerPower
percI := types.BigDiv(types.BigMul(mp.QualityAdjPower, types.NewInt(1000000)), tp.QualityAdjPower)
fmt.Printf("%s(%s) / %s(%s) ~= %0.4f%%\n", mp.QualityAdjPower.String(), types.SizeStr(mp.QualityAdjPower), tp.QualityAdjPower.String(), types.SizeStr(tp.QualityAdjPower), float64(percI.Int64())/10000)
fmt.Printf(
"%s(%s) / %s(%s) ~= %0.4f%%\n",
mp.QualityAdjPower.String(), types.SizeStr(mp.QualityAdjPower),
tp.QualityAdjPower.String(), types.SizeStr(tp.QualityAdjPower),
types.BigDivFloat(
types.BigMul(mp.QualityAdjPower, big.NewInt(100)),
tp.QualityAdjPower,
),
)
} else {
fmt.Printf("%s(%s)\n", tp.QualityAdjPower.String(), types.SizeStr(tp.QualityAdjPower))
}
Expand Down
7 changes: 4 additions & 3 deletions cmd/lotus-shed/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,13 @@ var syncScrapePowerCmd = &cli.Command{
return err
}

qpercI := types.BigDiv(types.BigMul(totalWonPower.QualityAdjPower, types.NewInt(1000000)), totalPower.TotalPower.QualityAdjPower)

fmt.Println("Number of winning miners: ", len(miners))
fmt.Println("QAdjPower of winning miners: ", totalWonPower.QualityAdjPower)
fmt.Println("QAdjPower of all miners: ", totalPower.TotalPower.QualityAdjPower)
fmt.Println("Percentage of winning QAdjPower: ", float64(qpercI.Int64())/10000)
fmt.Println("Percentage of winning QAdjPower: ", types.BigDivFloat(
types.BigMul(totalWonPower.QualityAdjPower, big.NewInt(100)),
totalPower.TotalPower.QualityAdjPower,
))

return nil
},
Expand Down
75 changes: 60 additions & 15 deletions cmd/lotus-storage-miner/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package main
import (
"context"
"fmt"
"math"
corebig "math/big"
"sort"
"time"

Expand All @@ -21,6 +23,7 @@ import (
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
Expand Down Expand Up @@ -120,19 +123,23 @@ func infoCmdAct(cctx *cli.Context) error {
return err
}

rpercI := types.BigDiv(types.BigMul(pow.MinerPower.RawBytePower, types.NewInt(1000000)), pow.TotalPower.RawBytePower)
qpercI := types.BigDiv(types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(1000000)), pow.TotalPower.QualityAdjPower)

fmt.Printf("Power: %s / %s (%0.4f%%)\n",
color.GreenString(types.DeciStr(pow.MinerPower.QualityAdjPower)),
types.DeciStr(pow.TotalPower.QualityAdjPower),
float64(qpercI.Int64())/10000)
types.BigDivFloat(
types.BigMul(pow.MinerPower.QualityAdjPower, big.NewInt(100)),
pow.TotalPower.QualityAdjPower,
),
)

fmt.Printf("\tRaw: %s / %s (%0.4f%%)\n",
color.BlueString(types.SizeStr(pow.MinerPower.RawBytePower)),
types.SizeStr(pow.TotalPower.RawBytePower),
float64(rpercI.Int64())/10000)

types.BigDivFloat(
types.BigMul(pow.MinerPower.RawBytePower, big.NewInt(100)),
pow.TotalPower.RawBytePower,
),
)
secCounts, err := api.StateMinerSectorCount(ctx, maddr, types.EmptyTSK)
if err != nil {
return err
Expand All @@ -146,7 +153,7 @@ func infoCmdAct(cctx *cli.Context) error {
} else {
var faultyPercentage float64
if secCounts.Live != 0 {
faultyPercentage = float64(10000*nfaults/secCounts.Live) / 100.
faultyPercentage = float64(100*nfaults) / float64(secCounts.Live)
}
fmt.Printf("\tProving: %s (%s Faulty, %.2f%%)\n",
types.SizeStr(types.BigMul(types.NewInt(proving), types.NewInt(uint64(mi.SectorSize)))),
Expand All @@ -157,16 +164,54 @@ func infoCmdAct(cctx *cli.Context) error {
if !pow.HasMinPower {
fmt.Print("Below minimum power threshold, no blocks will be won")
} else {
expWinChance := float64(types.BigMul(qpercI, types.NewInt(build.BlocksPerEpoch)).Int64()) / 1000000
if expWinChance > 0 {
if expWinChance > 1 {
expWinChance = 1

winRatio := new(corebig.Rat).SetFrac(
types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(build.BlocksPerEpoch)).Int,
pow.TotalPower.QualityAdjPower.Int,
)

if winRatioFloat, _ := winRatio.Float64(); winRatioFloat > 0 {

// if the corresponding poisson distribution isn't infinitely small then
// throw it into the mix as well, accounting for multi-wins
winRationWithPoissonFloat := -math.Expm1(-winRatioFloat)
winRationWithPoisson := new(corebig.Rat).SetFloat64(winRationWithPoissonFloat)
if winRationWithPoisson != nil {
winRatio = winRationWithPoisson
winRatioFloat = winRationWithPoissonFloat
}
winRate := time.Duration(float64(time.Second*time.Duration(build.BlockDelaySecs)) / expWinChance)
winPerDay := float64(time.Hour*24) / float64(winRate)

fmt.Print("Expected block win rate: ")
color.Blue("%.4f/day (every %s)", winPerDay, winRate.Truncate(time.Second))
weekly, _ := new(corebig.Rat).Mul(
winRatio,
new(corebig.Rat).SetInt64(7*builtin.EpochsInDay),
).Float64()

avgDuration, _ := new(corebig.Rat).Mul(
new(corebig.Rat).SetInt64(builtin.EpochDurationSeconds),
new(corebig.Rat).Inv(winRatio),
).Float64()

fmt.Print("Projected average block win rate: ")
color.Blue(
"%.02f/week (every %s)",
weekly,
(time.Second * time.Duration(avgDuration)).Truncate(time.Second).String(),
)

// Geometric distribution of P(Y < k) calculated as described in https://en.wikipedia.org/wiki/Geometric_distribution#Probability_Outcomes_Examples
// https://www.wolframalpha.com/input/?i=t+%3E+0%3B+p+%3E+0%3B+p+%3C+1%3B+c+%3E+0%3B+c+%3C1%3B+1-%281-p%29%5E%28t%29%3Dc%3B+solve+t
// t == how many dice-rolls (epochs) before win
// p == winRate == ( minerPower / netPower )
// c == target probability of win ( 99.9% in this case )
fmt.Print("Projected block win with ")
color.Green(
"99.9%% probability every %s",
(time.Second * time.Duration(
builtin.EpochDurationSeconds*math.Log(1-0.999)/
math.Log(1-winRatioFloat),
)).Truncate(time.Second).String(),
)
fmt.Println("(projections DO NOT account for future network and miner growth)")
}
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/lotus-storage-miner/proving.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ var provingInfoCmd = &cli.Command{

var faultPerc float64
if proving > 0 {
faultPerc = float64(faults*10000/proving) / 100
faultPerc = float64(faults * 100 / proving)
}

fmt.Printf("Current Epoch: %d\n", cd.CurrentEpoch)
Expand Down
67 changes: 55 additions & 12 deletions testplans/lotus-soup/rfwp/chain_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"encoding/json"
"fmt"
"io"
"math"
corebig "math/big"
"os"
"sort"
"text/tabwriter"
Expand All @@ -27,6 +29,7 @@ import (
"github.com/filecoin-project/go-state-types/abi"
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"

"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
tstats "github.com/filecoin-project/lotus/tools/stats"
)
Expand Down Expand Up @@ -581,18 +584,24 @@ func (i *MinerInfo) MarshalPlainText() ([]byte, error) {
fmt.Fprintf(w, "Sector Size: %s\n", i.SectorSize)

pow := i.MinerPower
rpercI := types.BigDiv(types.BigMul(pow.MinerPower.RawBytePower, types.NewInt(1000000)), pow.TotalPower.RawBytePower)
qpercI := types.BigDiv(types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(1000000)), pow.TotalPower.QualityAdjPower)

fmt.Fprintf(w, "Byte Power: %s / %s (%0.4f%%)\n",
types.SizeStr(pow.MinerPower.RawBytePower),
types.SizeStr(pow.TotalPower.RawBytePower),
float64(rpercI.Int64())/10000)
types.BigDivFloat(
types.BigMul(pow.MinerPower.RawBytePower, big.NewInt(100)),
pow.TotalPower.RawBytePower,
),
)

fmt.Fprintf(w, "Actual Power: %s / %s (%0.4f%%)\n",
types.DeciStr(pow.MinerPower.QualityAdjPower),
types.DeciStr(pow.TotalPower.QualityAdjPower),
float64(qpercI.Int64())/10000)
types.BigDivFloat(
types.BigMul(pow.MinerPower.QualityAdjPower, big.NewInt(100)),
pow.TotalPower.QualityAdjPower,
),
)

fmt.Fprintf(w, "\tCommitted: %s\n", types.SizeStr(i.CommittedBytes))

Expand All @@ -608,16 +617,50 @@ func (i *MinerInfo) MarshalPlainText() ([]byte, error) {
if !i.MinerPower.HasMinPower {
fmt.Fprintf(w, "Below minimum power threshold, no blocks will be won\n")
} else {
expWinChance := float64(types.BigMul(qpercI, types.NewInt(build.BlocksPerEpoch)).Int64()) / 1000000
if expWinChance > 0 {
if expWinChance > 1 {
expWinChance = 1

winRatio := new(corebig.Rat).SetFrac(
types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(build.BlocksPerEpoch)).Int,
pow.TotalPower.QualityAdjPower.Int,
)

if winRatioFloat, _ := winRatio.Float64(); winRatioFloat > 0 {

// if the corresponding poisson distribution isn't infinitely small then
// throw it into the mix as well, accounting for multi-wins
winRationWithPoissonFloat := -math.Expm1(-winRatioFloat)
winRationWithPoisson := new(corebig.Rat).SetFloat64(winRationWithPoissonFloat)
if winRationWithPoisson != nil {
winRatio = winRationWithPoisson
winRatioFloat = winRationWithPoissonFloat
}
winRate := time.Duration(float64(time.Second*time.Duration(build.BlockDelaySecs)) / expWinChance)
winPerDay := float64(time.Hour*24) / float64(winRate)

fmt.Fprintln(w, "Expected block win rate: ")
fmt.Fprintf(w, "%.4f/day (every %s)\n", winPerDay, winRate.Truncate(time.Second))
weekly, _ := new(corebig.Rat).Mul(
winRatio,
new(corebig.Rat).SetInt64(7*builtin.EpochsInDay),
).Float64()

avgDuration, _ := new(corebig.Rat).Mul(
new(corebig.Rat).SetInt64(builtin.EpochDurationSeconds),
new(corebig.Rat).Inv(winRatio),
).Float64()

fmt.Fprintf(w, "Projected average block win rate: %.02f/week (every %s)\n",
weekly,
(time.Second * time.Duration(avgDuration)).Truncate(time.Second).String(),
)

// Geometric distribution of P(Y < k) calculated as described in https://en.wikipedia.org/wiki/Geometric_distribution#Probability_Outcomes_Examples
// https://www.wolframalpha.com/input/?i=t+%3E+0%3B+p+%3E+0%3B+p+%3C+1%3B+c+%3E+0%3B+c+%3C1%3B+1-%281-p%29%5E%28t%29%3Dc%3B+solve+t
// t == how many dice-rolls (epochs) before win
// p == winRate == ( minerPower / netPower )
// c == target probability of win ( 99.9% in this case )
fmt.Fprintf(w, "Projected block win with 99.9%% probability every %s\n",
(time.Second * time.Duration(
builtin.EpochDurationSeconds*math.Log(1-0.999)/
math.Log(1-winRatioFloat),
)).Truncate(time.Second).String(),
)
fmt.Fprintln(w, "(projections DO NOT account for future network and miner growth)")
}
}

Expand Down