Merge pull request #4318 from filecoin-project/asr/shed-won-power
Add a shed util to determine % of power that has won a block
This commit is contained in:
commit
b85bf82d00
@ -2,6 +2,7 @@ package power
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
@ -61,3 +62,10 @@ type Claim struct {
|
||||
// Sum of quality adjusted power for a miner's sectors.
|
||||
QualityAdjPower abi.StoragePower
|
||||
}
|
||||
|
||||
func AddClaims(a Claim, b Claim) Claim {
|
||||
return Claim{
|
||||
RawBytePower: big.Add(a.RawBytePower, b.RawBytePower),
|
||||
QualityAdjPower: big.Add(a.QualityAdjPower, b.QualityAdjPower),
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,15 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
@ -16,6 +25,7 @@ var syncCmd = &cli.Command{
|
||||
Flags: []cli.Flag{},
|
||||
Subcommands: []*cli.Command{
|
||||
syncValidateCmd,
|
||||
syncScrapePowerCmd,
|
||||
},
|
||||
}
|
||||
|
||||
@ -62,3 +72,113 @@ var syncValidateCmd = &cli.Command{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var syncScrapePowerCmd = &cli.Command{
|
||||
Name: "scrape-power",
|
||||
Usage: "given a height and a tipset, reports what percentage of mining power had a winning ticket between the tipset and height",
|
||||
ArgsUsage: "[height tipsetkey]",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if cctx.Args().Len() < 1 {
|
||||
fmt.Println("usage: <height> [blockCid1 blockCid2...]")
|
||||
fmt.Println("Any CIDs passed after the height will be used as the tipset key")
|
||||
fmt.Println("If no block CIDs are provided, chain head will be used")
|
||||
return nil
|
||||
}
|
||||
|
||||
api, closer, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer closer()
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
if cctx.Args().Len() < 1 {
|
||||
fmt.Println("usage: <blockCid1> <blockCid2>...")
|
||||
fmt.Println("At least one block cid must be provided")
|
||||
return nil
|
||||
}
|
||||
|
||||
h, err := strconv.ParseInt(cctx.Args().Get(0), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
height := abi.ChainEpoch(h)
|
||||
|
||||
var ts *types.TipSet
|
||||
var startTsk types.TipSetKey
|
||||
if cctx.NArg() > 1 {
|
||||
var tscids []cid.Cid
|
||||
args := cctx.Args().Slice()
|
||||
|
||||
for _, s := range args[1:] {
|
||||
c, err := cid.Decode(s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("block cid was invalid: %s", err)
|
||||
}
|
||||
tscids = append(tscids, c)
|
||||
}
|
||||
|
||||
startTsk = types.NewTipSetKey(tscids...)
|
||||
ts, err = api.ChainGetTipSet(ctx, startTsk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
ts, err = api.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
startTsk = ts.Key()
|
||||
}
|
||||
|
||||
if ts.Height() < height {
|
||||
return fmt.Errorf("start tipset's height < stop height: %d < %d", ts.Height(), height)
|
||||
}
|
||||
|
||||
miners := make(map[address.Address]struct{})
|
||||
for ts.Height() >= height {
|
||||
for _, blk := range ts.Blocks() {
|
||||
_, found := miners[blk.Miner]
|
||||
if !found {
|
||||
// do the thing
|
||||
miners[blk.Miner] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
ts, err = api.ChainGetTipSet(ctx, ts.Parents())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
totalWonPower := power.Claim{
|
||||
RawBytePower: big.Zero(),
|
||||
QualityAdjPower: big.Zero(),
|
||||
}
|
||||
for miner := range miners {
|
||||
mp, err := api.StateMinerPower(ctx, miner, startTsk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
totalWonPower = power.AddClaims(totalWonPower, mp.MinerPower)
|
||||
}
|
||||
|
||||
totalPower, err := api.StateMinerPower(ctx, address.Undef, startTsk)
|
||||
if err != nil {
|
||||
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)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user