lotus/cmd/lotus-shed/fip-0036.go

790 lines
22 KiB
Go
Raw Normal View History

2022-09-23 03:28:46 +00:00
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
2022-09-26 12:13:00 +00:00
"github.com/urfave/cli/v2"
"github.com/filecoin-project/go-address"
"github.com/mitchellh/go-homedir"
2022-09-25 02:30:00 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
2022-09-23 20:00:22 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
2022-09-23 03:28:46 +00:00
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/consensus/filcns"
"github.com/filecoin-project/lotus/chain/store"
"github.com/ipfs/go-cid"
2022-09-26 12:13:00 +00:00
cbor "github.com/ipfs/go-ipld-cbor"
2022-09-23 03:28:46 +00:00
"github.com/filecoin-project/lotus/chain/actors/adt"
2022-09-26 12:13:00 +00:00
"github.com/filecoin-project/lotus/node/repo"
2022-09-23 03:28:46 +00:00
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/types"
"golang.org/x/xerrors"
)
const APPROVE = 49
2022-09-25 02:30:00 +00:00
const Reject = 50
2022-09-23 03:28:46 +00:00
type Vote struct {
OptionID uint64 `json: "optionId"`
SignerAddress address.Address `json: "signerAddress"`
}
type msigVote struct {
2022-09-26 12:13:00 +00:00
Multisig msigBriefInfo
ApproveCount uint64
RejectCount uint64
2022-09-23 03:28:46 +00:00
}
// https://filpoll.io/poll/16
// snapshot height: 2162760
// state root: bafy2bzacebdnzh43hw66bmvguk65wiwr5ssaejlq44fpdei2ysfh3eefpdlqs
2022-09-26 12:13:00 +00:00
var fip36PollCmd = &cli.Command{
Name: "fip36poll",
2022-09-23 03:28:46 +00:00
Usage: "Process the FIP0036 FilPoll result",
ArgsUsage: "[state root, votes]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "repo",
Value: "~/.lotus",
},
},
Subcommands: []*cli.Command{
2022-09-25 02:30:00 +00:00
spRBPAndDealCmd,
2022-09-23 20:00:22 +00:00
clientCmd,
2022-09-23 03:28:46 +00:00
tokenHolderCmd,
//coreDevCmd,
//finalResultCmd,
},
}
2022-09-26 12:13:00 +00:00
func getVotesMap(file string, st *state.StateTree) (map[address.Address]uint64 /*map[Signer ID address]Option*/, error) {
2022-09-23 03:28:46 +00:00
var votes []Vote
vb, err := ioutil.ReadFile(file)
if err != nil {
return nil, xerrors.Errorf("read vote: %w", err)
}
if err := json.Unmarshal(vb, &votes); err != nil {
return nil, xerrors.Errorf("unmarshal vote: %w", err)
}
2022-09-25 02:30:00 +00:00
vm := make(map[address.Address]uint64)
for _, v := range votes {
si, err := st.LookupID(v.SignerAddress)
if err != nil {
2022-09-26 12:13:00 +00:00
return nil, xerrors.Errorf("fail to lookup address", err)
2022-09-25 02:30:00 +00:00
}
vm[si] = v.OptionID
}
return vm, nil
}
2022-09-27 20:58:25 +00:00
func getAllMsigSignerMap(st *state.StateTree, store adt.Store) (map[address.Address][]address.Address /*map[Signer ID address]msigActorId[]*/, error) {
2022-09-26 12:13:00 +00:00
sm := make(map[address.Address][]address.Address)
2022-09-23 03:28:46 +00:00
err := st.ForEach(func(addr address.Address, act *types.Actor) error {
if builtin.IsMultisigActor(act.Code) {
ms, err := multisig.Load(store, act)
if err != nil {
return fmt.Errorf("load msig failed %v", err)
}
2022-09-26 12:13:00 +00:00
ss, err := ms.Signers()
if err != nil {
return xerrors.Errorf("fail to get msig signers", err)
}
for _, s := range ss {
if m, found := sm[s]; found { //add msig id to signer's collection
m = append(m, addr)
sm[s] = m
} else {
n := []address.Address{addr}
sm[s] = n
}
2022-09-23 03:28:46 +00:00
}
}
return nil
})
if err != nil {
return nil, err
}
2022-09-26 12:13:00 +00:00
return sm, nil
2022-09-23 03:28:46 +00:00
}
2022-09-26 12:13:00 +00:00
func getAllMsigIDMap(st *state.StateTree, store adt.Store) (map[address.Address]msigBriefInfo /*map[Multisig Actor ID]msigBriefInfo*/, error) {
2022-09-25 02:30:00 +00:00
msigActorsInfo := make(map[address.Address]msigBriefInfo)
err := st.ForEach(func(addr address.Address, act *types.Actor) error {
if builtin.IsMultisigActor(act.Code) {
ms, err := multisig.Load(store, act)
if err != nil {
return fmt.Errorf("load msig failed %v", err)
}
signers, _ := ms.Signers()
threshold, _ := ms.Threshold()
info := msigBriefInfo{
ID: addr,
Signer: signers,
Balance: act.Balance,
Threshold: threshold,
}
msigActorsInfo[addr] = info
}
return nil
})
if err != nil {
return nil, err
}
return msigActorsInfo, nil
}
type MinerVoteInfo struct {
AvailableBalance abi.TokenAmount
DealBytes abi.PaddedPieceSize
RBP abi.StoragePower
Option uint64
}
func getStorageMinerRBP(miner address.Address, st *state.StateTree, store adt.Store) (abi.StoragePower, error) {
pa, err := st.GetActor(power.Address)
if err != nil {
return types.NewInt(0), xerrors.Errorf("failed to get power actor: \n", err)
}
ps, err := power.Load(store, pa)
if err != nil {
return types.NewInt(0), xerrors.Errorf("failed to get power state: \n", err)
}
mp, _, err := ps.MinerPower(miner)
if err != nil {
return types.NewInt(0), xerrors.Errorf("failed to get miner power: \n", err)
}
return mp.RawBytePower, nil
}
2022-09-26 12:13:00 +00:00
func getStorageMinerVotes(st *state.StateTree, votes map[address.Address]uint64, store adt.Store) (map[address.Address]MinerVoteInfo /*map[Storage Miner Actor]Option*/, error) {
2022-09-25 02:30:00 +00:00
smv := make(map[address.Address]MinerVoteInfo)
2022-09-26 12:13:00 +00:00
msigs, err := getAllMsigIDMap(st, store)
2022-09-25 02:30:00 +00:00
if err != nil {
xerrors.Errorf("fail to get msigs", err)
}
err = st.ForEach(func(addr address.Address, act *types.Actor) error {
if builtin.IsStorageMinerActor(act.Code) {
m, err := miner.Load(store, act)
if err != nil {
return xerrors.Errorf("fail to load miner actor: \n", err)
}
info, err := m.Info()
if err != nil {
return xerrors.Errorf("fail to get miner info: \n", err)
}
//check if owner voted
o := info.Owner
if v, found := votes[o]; found {
2022-09-26 12:13:00 +00:00
//check if owner is msig
if ms, found := msigs[o]; found { //owner is a msig
ac := uint64(0)
rc := uint64(0)
for _, s := range ms.Signer {
if v, found := votes[s]; found {
if v == APPROVE {
ac += 1
2022-09-25 02:30:00 +00:00
} else {
2022-09-26 12:13:00 +00:00
rc += 1
2022-09-25 02:30:00 +00:00
}
}
2022-09-26 12:13:00 +00:00
mp, err := getStorageMinerRBP(addr, st, store)
if err != nil {
return xerrors.Errorf("fail to get miner actor rbp", err)
}
m := MinerVoteInfo{
AvailableBalance: act.Balance,
RBP: mp,
}
//check if msig threshold is met for casting the vote
if ac == ms.Threshold {
m.Option = APPROVE
smv[addr] = m
} else if rc == ms.Threshold {
m.Option = Reject
smv[addr] = m
} else {
smv[addr] = m //no valid vote yet, option value should be 0
}
2022-09-25 02:30:00 +00:00
}
2022-09-26 12:13:00 +00:00
} else { //owner is a regular wallet account
2022-09-25 02:30:00 +00:00
mp, err := getStorageMinerRBP(addr, st, store)
if err != nil {
return xerrors.Errorf("fail to get miner actor rbp", err)
}
m := MinerVoteInfo{
AvailableBalance: act.Balance,
RBP: mp,
Option: v,
}
smv[addr] = m
}
}
2022-09-26 12:13:00 +00:00
//check if owner has not voted but worker voted
2022-09-25 02:30:00 +00:00
if _, found := smv[addr]; !found {
w := info.Worker
if v, found := votes[w]; found {
mp, err := getStorageMinerRBP(addr, st, store)
if err != nil {
return xerrors.Errorf("fail to get miner actor rbp", err)
}
m := MinerVoteInfo{
AvailableBalance: act.Balance,
RBP: mp,
Option: v,
}
smv[addr] = m
}
}
}
return nil
})
if err != nil {
return nil, err
}
return smv, nil
}
var spRBPAndDealCmd = &cli.Command{
2022-09-26 12:13:00 +00:00
Name: "sp",
Usage: "get poll result for storage group. Weighted by RBP(raw byte power) and deal bytes stored in valid deals." +
"\nNote that: if both owner key and worker key has voted, the vote made by owner key will be casted the storage provider actor.",
2022-09-25 02:30:00 +00:00
ArgsUsage: "[state root]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "repo",
Value: "~/.lotus",
},
&cli.BoolFlag{
Name: "rbp-only",
Value: false,
},
},
Action: func(cctx *cli.Context) error {
if cctx.NArg() != 2 {
return xerrors.New("filpoll0036 token-holder [state root] [votes.json]")
}
ctx := context.TODO()
if !cctx.Args().Present() {
return fmt.Errorf("must pass state root")
}
sroot, err := cid.Decode(cctx.Args().First())
if err != nil {
return fmt.Errorf("failed to parse input: %w", err)
}
fsrepo, err := repo.NewFS(cctx.String("repo"))
if err != nil {
return err
}
lkrepo, err := fsrepo.Lock(repo.FullNode)
if err != nil {
return err
}
defer lkrepo.Close() //nolint:errcheck
bs, err := lkrepo.Blockstore(ctx, repo.UniversalBlockstore)
if err != nil {
return fmt.Errorf("failed to open blockstore: %w", err)
}
defer func() {
if c, ok := bs.(io.Closer); ok {
if err := c.Close(); err != nil {
log.Warnf("failed to close blockstore: %s", err)
}
}
}()
mds, err := lkrepo.Datastore(context.Background(), "/metadata")
if err != nil {
return err
}
cs := store.NewChainStore(bs, bs, mds, filcns.Weight, nil)
defer cs.Close() //nolint:errcheck
cst := cbor.NewCborStore(bs)
store := adt.WrapStore(ctx, cst)
tree, err := state.LoadStateTree(cst, sroot)
if err != nil {
return err
}
2022-09-27 20:58:25 +00:00
//get all the votes' signer ID address && their vote
2022-09-25 02:30:00 +00:00
vj, err := homedir.Expand(cctx.Args().Get(1))
if err != nil {
return xerrors.Errorf("fail to get votes json")
}
votes, err := getVotesMap(vj, tree)
if err != nil {
return xerrors.Errorf("fail to get votesrs: ", err)
}
//get all storage miner votes
smv, err := getStorageMinerVotes(tree, votes, store)
if err != nil {
return xerrors.Errorf("fail to get storage miner votes", err)
}
2022-09-26 12:13:00 +00:00
approveVote := 0
2022-09-25 02:30:00 +00:00
rejectionVote := 0
2022-09-26 12:13:00 +00:00
approveRBP := abi.NewStoragePower(0)
2022-09-25 02:30:00 +00:00
rejectRBP := abi.NewStoragePower(0)
2022-09-26 12:13:00 +00:00
approveDealBytes := abi.PaddedPieceSize(0)
2022-09-25 02:30:00 +00:00
rejectDealBytes := abi.PaddedPieceSize(0)
ownerMsigUnderThreshold := 0
//get all market proposals, add load the # of the bytes each provider has made
pds := make(map[address.Address]abi.PaddedPieceSize)
if !cctx.Bool("rbp-only") {
ma, err := tree.GetActor(market.Address)
if err != nil {
return xerrors.Errorf("fail to get market actor: ", err)
}
ms, err := market.Load(store, ma)
if err != nil {
return xerrors.Errorf("fail to load market actor: ", err)
}
dps, _ := ms.Proposals()
if err := dps.ForEach(func(dealID abi.DealID, d market.DealProposal) error {
if pd, found := pds[d.Provider]; found {
s := d.PieceSize + pd
pds[d.Provider] = s
} else {
pds[d.Provider] = d.PieceSize
}
return xerrors.Errorf("fail to load deals")
}); err != nil {
return xerrors.Errorf("fail to get deals")
}
}
//process the vote
for m, mvi := range smv {
if mvi.Option == APPROVE {
2022-09-26 12:13:00 +00:00
approveVote += 1
approveRBP = types.BigAdd(approveRBP, mvi.RBP)
if d, found := pds[m]; !cctx.Bool("rbp-only") && found {
approveDealBytes += d
2022-09-25 02:30:00 +00:00
}
} else if mvi.Option == Reject {
rejectionVote += 1
rejectRBP = types.BigAdd(rejectRBP, mvi.RBP)
2022-09-26 12:13:00 +00:00
if d, found := pds[m]; !cctx.Bool("rbp-only") && found {
2022-09-25 02:30:00 +00:00
rejectDealBytes += d
}
} else { //owner is msig and didnt reach threshold
ownerMsigUnderThreshold += 1
}
}
fmt.Printf("\nTotal amount of storage provider: %v\n", len(smv))
2022-09-26 12:13:00 +00:00
fmt.Printf("Approve (#): %v\n", approveVote)
2022-09-25 02:30:00 +00:00
fmt.Printf("Reject (#): %v\n", rejectionVote)
2022-09-26 12:13:00 +00:00
fmt.Printf("SP owner is multisig and the vote is invalid due to under threshold: %v\n", ownerMsigUnderThreshold)
fmt.Printf("Total RPB voted: %v\n", types.BigAdd(approveRBP, rejectRBP))
fmt.Printf("Approve (rbp): %v\n", approveRBP)
2022-09-25 02:30:00 +00:00
fmt.Printf("Reject (rbp): %v\n", rejectRBP)
2022-09-26 12:13:00 +00:00
av := types.BigDivFloat(approveRBP, types.BigAdd(approveRBP, rejectRBP))
rv := types.BigDivFloat(rejectRBP, types.BigAdd(approveRBP, rejectRBP))
if av > 0.05 {
fmt.Printf("Storage Miner Group By RBP Result: Pass. approve: %.5f, reject: %.5f\n", av, rv)
} else {
fmt.Printf("Storage Miner Group By RBP Result: Not Pass. approve: %.5f, reject: %.5f\n", av, rv)
}
2022-09-25 02:30:00 +00:00
if !cctx.Bool("rbp-only") {
2022-09-26 12:13:00 +00:00
fmt.Printf("Total deal bytes: %v\n", approveDealBytes+rejectDealBytes)
fmt.Printf("Approve (deal bytes): %v\n", approveDealBytes)
2022-09-25 02:30:00 +00:00
fmt.Printf("Reject (byte): %v\n", rejectDealBytes)
2022-09-26 12:13:00 +00:00
av := float64(approveDealBytes) / float64(approveDealBytes+rejectDealBytes)
rv := float64(rejectDealBytes) / float64(approveDealBytes+rejectDealBytes)
if av > 0.05 {
fmt.Printf("Storage Miner Group By Deal Bytes Result: Pass. approve: %.5f, reject: %.5f\n", av, rv)
} else {
fmt.Printf("Storage Miner Group By Deal Bytes: Not Pass. approve: %.5f, reject: %.5f\n", av, rv)
}
2022-09-25 02:30:00 +00:00
}
2022-09-26 12:13:00 +00:00
2022-09-25 02:30:00 +00:00
return nil
},
}
2022-09-23 03:28:46 +00:00
var tokenHolderCmd = &cli.Command{
Name: "token-holder",
2022-09-26 12:13:00 +00:00
Usage: "get poll result for token holder group. balance includes, regular wallet accounts, multisig wallet that has valid vote that meets threshold, and the available balance of the storage miner actors that voted",
2022-09-23 03:28:46 +00:00
ArgsUsage: "[state root]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "repo",
Value: "~/.lotus",
},
},
Action: func(cctx *cli.Context) error {
if cctx.NArg() != 2 {
return xerrors.New("filpoll0036 token-holder [state root] [votes.json]")
}
ctx := context.TODO()
if !cctx.Args().Present() {
return fmt.Errorf("must pass state root")
}
sroot, err := cid.Decode(cctx.Args().First())
if err != nil {
return fmt.Errorf("failed to parse input: %w", err)
}
fsrepo, err := repo.NewFS(cctx.String("repo"))
if err != nil {
return err
}
lkrepo, err := fsrepo.Lock(repo.FullNode)
if err != nil {
return err
}
defer lkrepo.Close() //nolint:errcheck
bs, err := lkrepo.Blockstore(ctx, repo.UniversalBlockstore)
if err != nil {
return fmt.Errorf("failed to open blockstore: %w", err)
}
defer func() {
if c, ok := bs.(io.Closer); ok {
if err := c.Close(); err != nil {
log.Warnf("failed to close blockstore: %s", err)
}
}
}()
mds, err := lkrepo.Datastore(context.Background(), "/metadata")
if err != nil {
return err
}
cs := store.NewChainStore(bs, bs, mds, filcns.Weight, nil)
defer cs.Close() //nolint:errcheck
cst := cbor.NewCborStore(bs)
store := adt.WrapStore(ctx, cst)
tree, err := state.LoadStateTree(cst, sroot)
if err != nil {
return err
}
2022-09-27 20:58:25 +00:00
//get all the votes' signer address && their vote
2022-09-23 03:28:46 +00:00
vj, err := homedir.Expand(cctx.Args().Get(1))
if err != nil {
return xerrors.Errorf("fail to get votes json")
}
2022-09-26 12:13:00 +00:00
vm, err := getVotesMap(vj, tree)
2022-09-23 03:28:46 +00:00
if err != nil {
2022-09-26 12:13:00 +00:00
return xerrors.Errorf("fail to get voter map ", err)
2022-09-23 03:28:46 +00:00
}
2022-09-27 20:58:25 +00:00
//get all the msig signers & their msigs
msigs, err := getAllMsigSignerMap(tree, store)
2022-09-26 12:13:00 +00:00
approveVote := 0
2022-09-23 20:00:22 +00:00
rejectionVote := 0
2022-09-26 12:13:00 +00:00
approveBalance := abi.NewTokenAmount(0)
2022-09-23 03:28:46 +00:00
rejectionBalance := abi.NewTokenAmount(0)
2022-09-26 12:13:00 +00:00
msigPendingVotes := make(map[address.Address]msigVote) //map[msig ID]msigVote
msigFinalVotes := 0
2022-09-23 03:28:46 +00:00
2022-09-26 12:13:00 +00:00
for s, v := range vm {
//process votes for regular accounts
a, err := tree.GetActor(s)
2022-09-23 03:28:46 +00:00
if err != nil {
2022-09-26 12:13:00 +00:00
return xerrors.Errorf("fail to get account account for signer: ", err)
2022-09-23 03:28:46 +00:00
}
2022-09-26 12:13:00 +00:00
if v == APPROVE {
approveVote += 1
approveBalance = types.BigAdd(approveBalance, a.Balance)
2022-09-23 03:28:46 +00:00
} else {
2022-09-23 20:00:22 +00:00
rejectionVote += 1
2022-09-23 03:28:46 +00:00
rejectionBalance = types.BigAdd(rejectionBalance, a.Balance)
}
2022-09-26 12:13:00 +00:00
//process msigs
if mss, found := msigs[s]; found {
2022-09-27 20:58:25 +00:00
for _, ms := range mss { //get all the msig signer has
2022-09-26 12:13:00 +00:00
if mpv, found := msigPendingVotes[ms]; found { //other signers of the multisig have voted, yet the threshold has not met
if v == APPROVE {
if mpv.ApproveCount+1 == mpv.Multisig.Threshold { //met threshold
approveVote += 1
approveBalance = types.BigAdd(approveBalance, mpv.Multisig.Balance)
msigFinalVotes += 1
delete(msigPendingVotes, ms) //threshold, can skip later signer votes
2022-09-23 03:28:46 +00:00
} else {
2022-09-26 12:13:00 +00:00
mpv.ApproveCount += 1
msigPendingVotes[ms] = mpv
2022-09-23 03:28:46 +00:00
}
} else {
2022-09-26 12:13:00 +00:00
if mpv.RejectCount+1 == mpv.Multisig.Threshold { //met threshold
rejectionVote += 1
rejectionBalance = types.BigAdd(rejectionBalance, mpv.Multisig.Balance)
msigFinalVotes += 1
delete(msigPendingVotes, ms) //threshold, can skip later signer votes
2022-09-23 03:28:46 +00:00
} else {
2022-09-26 12:13:00 +00:00
mpv.RejectCount += 1
msigPendingVotes[ms] = mpv
2022-09-23 03:28:46 +00:00
}
2022-09-26 12:13:00 +00:00
}
} else { //first vote received from one of the signers of the msig
msa, err := tree.GetActor(ms)
if err != nil {
return fmt.Errorf("load msig actor failed %v", err)
}
msas, err := multisig.Load(store, msa)
if err != nil {
return fmt.Errorf("load msig failed %v", err)
2022-09-23 03:28:46 +00:00
2022-09-26 12:13:00 +00:00
}
t, _ := msas.Threshold()
if t == 1 { //met threshold with this signer's single vote
if v == APPROVE {
approveVote += 1
approveBalance = types.BigAdd(approveBalance, msa.Balance)
} else {
rejectionVote += 1
rejectionBalance = types.BigAdd(rejectionBalance, msa.Balance)
}
msigFinalVotes += 1
} else { //threshold not met, add to pending vote
if v == APPROVE {
msigPendingVotes[ms] = msigVote{
Multisig: msigBriefInfo{
Balance: msa.Balance,
Threshold: t,
},
ApproveCount: 1,
}
2022-09-23 03:28:46 +00:00
} else {
2022-09-26 12:13:00 +00:00
msigPendingVotes[ms] = msigVote{
Multisig: msigBriefInfo{
Balance: msa.Balance,
Threshold: t,
},
RejectCount: 1,
}
2022-09-23 03:28:46 +00:00
}
}
}
}
}
}
2022-09-26 12:13:00 +00:00
// add miner available balance
mvs, err := getStorageMinerVotes(tree, vm, store)
if err != nil {
return xerrors.Errorf("fail to get storage miner vote ", err)
}
spApproveAvailableBalance := abi.NewTokenAmount(0)
spRejectionAvailableBalance := abi.NewTokenAmount(0)
for _, mv := range mvs {
if mv.Option == APPROVE {
approveVote += 1
approveBalance = types.BigAdd(approveBalance, mv.AvailableBalance)
spApproveAvailableBalance = types.BigAdd(approveBalance, spApproveAvailableBalance)
} else if mv.Option == Reject {
rejectionVote += 1
rejectionBalance = types.BigAdd(rejectionBalance, mv.AvailableBalance)
spRejectionAvailableBalance = types.BigAdd(rejectionBalance, spRejectionAvailableBalance)
} else {
continue
}
}
2022-09-27 20:58:25 +00:00
fmt.Printf("\nTotal amount of signer: %v\n ", len(vm))
2022-09-26 12:13:00 +00:00
fmt.Printf("Total amount of valid multisig vote: %v\n ", msigFinalVotes)
fmt.Printf("Total balance: %v\n", types.BigAdd(approveBalance, rejectionBalance).String())
fmt.Printf("Approve (#): %v\n", approveVote)
2022-09-23 20:00:22 +00:00
fmt.Printf("Reject (#): %v\n", rejectionVote)
2022-09-26 12:13:00 +00:00
fmt.Printf("Approve (FIL): %v\n", approveBalance.String())
2022-09-23 20:00:22 +00:00
fmt.Printf("Reject (FIL): %v\n", rejectionBalance.String())
2022-09-26 12:13:00 +00:00
fmt.Printf("Approve - Storage Miner Portion (FIL in account): %v\n", spApproveAvailableBalance.String())
fmt.Printf("Reject - Storage Miner Portion (FIL in account): %v\n", spRejectionAvailableBalance.String())
av := types.BigDivFloat(approveBalance, types.BigAdd(approveBalance, rejectionBalance))
rv := types.BigDivFloat(rejectionBalance, types.BigAdd(rejectionBalance, approveBalance))
2022-09-23 03:28:46 +00:00
if av > 0.05 {
2022-09-26 12:13:00 +00:00
fmt.Printf("Token Holder Group Result: Pass. approve: %.5f, reject: %.5f,\n", av, rv)
2022-09-23 03:28:46 +00:00
} else {
fmt.Printf("Token Holder Group Result: Not Pass. approve: %.5f, reject: %.5f\n", av, rv)
}
return nil
},
}
2022-09-23 20:00:22 +00:00
var clientCmd = &cli.Command{
Name: "client",
2022-09-26 12:13:00 +00:00
Usage: "get poll result for client, weighted by deal bytes that are in valid deals in the storage market.",
2022-09-23 20:00:22 +00:00
ArgsUsage: "[state root]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "repo",
Value: "~/.lotus",
},
},
Action: func(cctx *cli.Context) error {
if cctx.NArg() != 2 {
return xerrors.New("filpoll0036 token-holder [state root] [votes.json]")
}
ctx := context.TODO()
if !cctx.Args().Present() {
return fmt.Errorf("must pass state root")
}
sroot, err := cid.Decode(cctx.Args().First())
if err != nil {
return fmt.Errorf("failed to parse input: %w", err)
}
fsrepo, err := repo.NewFS(cctx.String("repo"))
if err != nil {
return err
}
lkrepo, err := fsrepo.Lock(repo.FullNode)
if err != nil {
return err
}
defer lkrepo.Close() //nolint:errcheck
bs, err := lkrepo.Blockstore(ctx, repo.UniversalBlockstore)
if err != nil {
return fmt.Errorf("failed to open blockstore: %w", err)
}
defer func() {
if c, ok := bs.(io.Closer); ok {
if err := c.Close(); err != nil {
log.Warnf("failed to close blockstore: %s", err)
}
}
}()
mds, err := lkrepo.Datastore(context.Background(), "/metadata")
if err != nil {
return err
}
cs := store.NewChainStore(bs, bs, mds, filcns.Weight, nil)
defer cs.Close() //nolint:errcheck
cst := cbor.NewCborStore(bs)
store := adt.WrapStore(ctx, cst)
tree, err := state.LoadStateTree(cst, sroot)
if err != nil {
return err
}
2022-09-27 20:58:25 +00:00
//get all the votes' signer ID address && their voted option
2022-09-23 20:00:22 +00:00
vj, err := homedir.Expand(cctx.Args().Get(1))
if err != nil {
return xerrors.Errorf("fail to get votes json")
}
2022-09-26 12:13:00 +00:00
vm, err := getVotesMap(vj, tree)
2022-09-23 20:00:22 +00:00
if err != nil {
return xerrors.Errorf("fail to get votesrs: ", err)
}
//market actor
ma, err := tree.GetActor(market.Address)
if err != nil {
return xerrors.Errorf("fail to get market actor: ", err)
}
ms, err := market.Load(store, ma)
if err != nil {
return xerrors.Errorf("fail to load market actor: ", err)
}
2022-09-25 02:30:00 +00:00
//get all market proposals, add load the # of the bytes each client has made
2022-09-23 20:00:22 +00:00
dps, _ := ms.Proposals()
2022-09-25 02:30:00 +00:00
cds := make(map[address.Address]abi.PaddedPieceSize)
if err := dps.ForEach(func(dealID abi.DealID, d market.DealProposal) error {
if cd, found := cds[d.Client]; found {
s := d.PieceSize + cd
cds[d.Client] = s
} else {
cds[d.Client] = d.PieceSize
}
return xerrors.Errorf("fail to load deals")
}); err != nil {
return xerrors.Errorf("fail to get deals")
}
2022-09-26 12:13:00 +00:00
approveBytes := abi.PaddedPieceSize(0)
2022-09-23 20:00:22 +00:00
rejectionBytes := abi.PaddedPieceSize(0)
2022-09-26 12:13:00 +00:00
approveCount := 0
2022-09-23 20:00:22 +00:00
rejectionCount := 0
2022-09-26 12:13:00 +00:00
for s, o := range vm {
if ds, found := cds[s]; found {
if o == APPROVE {
approveBytes += ds
approveCount += 1
2022-09-25 02:30:00 +00:00
} else {
rejectionBytes += ds
rejectionCount += 1
2022-09-23 20:00:22 +00:00
}
}
}
2022-09-26 12:13:00 +00:00
fmt.Printf("\nTotal amount of clients: %v\n", approveCount+rejectionCount)
fmt.Printf("Total deal bytes: %v\n", approveBytes+rejectionBytes)
fmt.Printf("Approve (#): %v\n", approveCount)
2022-09-23 20:00:22 +00:00
fmt.Printf("Reject (#): %v\n", rejectionCount)
2022-09-26 12:13:00 +00:00
fmt.Printf("Approve (byte): %v\n", approveBytes)
2022-09-23 20:00:22 +00:00
fmt.Printf("Reject (byte): %v\n", rejectionBytes)
2022-09-26 12:13:00 +00:00
av := float64(approveBytes) / float64(approveBytes+rejectionBytes)
rv := float64(rejectionBytes) / float64(approveBytes+rejectionBytes)
2022-09-23 20:00:22 +00:00
if av > 0.05 {
fmt.Printf("Deal Client Group Result: Pass. approve: %.5f, reject: %.5f\n", av, rv)
} else {
fmt.Printf("Deal Client Group Result: Not Pass. approve: %.5f, reject: %.5f\n", av, rv)
}
return nil
},
}