This commit is contained in:
jennijuju 2022-09-24 22:30:00 -04:00 committed by Aayush
parent 5f5491a9e5
commit 3d5ecf25b2

View File

@ -7,6 +7,10 @@ import (
"io"
"io/ioutil"
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/go-state-types/abi"
@ -36,6 +40,7 @@ import (
)
const APPROVE = 49
const Reject = 50
type Vote struct {
OptionID uint64 `json: "optionId"`
@ -62,8 +67,7 @@ var fip0036PollResultcmd = &cli.Command{
},
},
Subcommands: []*cli.Command{
//spRBPCmd,
//spDealByteCmd,
spRBPAndDealCmd,
clientCmd,
tokenHolderCmd,
//coreDevCmd,
@ -85,6 +89,23 @@ func getVoters(file string) ([]Vote, error) {
return votes, nil
}
func getVotesMap(file string, st *state.StateTree) (map[address.Address]uint64, error) {
votes, err := getVoters(file)
if err != nil {
return nil, xerrors.Errorf("cant get voters")
}
vm := make(map[address.Address]uint64)
for _, v := range votes {
si, err := st.LookupID(v.SignerAddress)
if err != nil {
return nil, xerrors.Errorf("fail to lookup address")
}
vm[si] = v.OptionID
}
return vm, nil
}
func getAllMsig(st *state.StateTree, store adt.Store) ([]msigBriefInfo, error) {
var msigActorsInfo []msigBriefInfo
@ -115,6 +136,310 @@ func getAllMsig(st *state.StateTree, store adt.Store) ([]msigBriefInfo, error) {
return msigActorsInfo, nil
}
func getAllMsigMap(st *state.StateTree, store adt.Store) (map[address.Address]msigBriefInfo, error) {
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
}
func getStorageMinerVotes(st *state.StateTree, votes map[address.Address]uint64, store adt.Store) (map[address.Address]MinerVoteInfo /*key: miner actor id*/, error) {
smv := make(map[address.Address]MinerVoteInfo)
msigs, err := getAllMsigMap(st, store)
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 {
//check if it is msig
oa, err := st.GetActor(o)
if err != nil {
return xerrors.Errorf("fail to get owner actor: \n", err)
}
if builtin.IsMultisigActor(oa.Code) {
if ms, found := msigs[o]; found {
ac := uint64(0)
rc := uint64(0)
for _, s := range ms.Signer {
if v, found := votes[s]; found {
if v == APPROVE {
ac += 1
} else {
rc += 1
}
}
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,
}
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
}
}
}
} else { //owner is regular wallet account
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
}
}
//check if owner not voted but worker voted
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{
Name: "sp",
Usage: "get poll result for storage group",
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
}
//get all the votes' singer address && their vote
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)
}
acceptanceVote := 0
rejectionVote := 0
acceptanceRBP := abi.NewStoragePower(0)
rejectRBP := abi.NewStoragePower(0)
acceptanceDealBytes := abi.PaddedPieceSize(0)
rejectDealBytes := abi.PaddedPieceSize(0)
ownerMsigUnderThreshold := 0
//process the votes
//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 {
acceptanceVote += 1
acceptanceRBP = types.BigAdd(acceptanceRBP, mvi.RBP)
if d, found := pds[m]; found {
acceptanceDealBytes += d
}
} else if mvi.Option == Reject {
rejectionVote += 1
rejectRBP = types.BigAdd(rejectRBP, mvi.RBP)
if d, found := pds[m]; found {
rejectDealBytes += d
}
} else { //owner is msig and didnt reach threshold
ownerMsigUnderThreshold += 1
}
}
fmt.Printf("\nTotal amount of storage provider: %v\n", len(smv))
fmt.Printf("Accept (#): %v\n", acceptanceVote)
fmt.Printf("Reject (#): %v\n", rejectionVote)
fmt.Printf("Total RPB voted: %v\n", types.BigAdd(acceptanceRBP, rejectRBP))
fmt.Printf("Accept (rbp): %v\n", acceptanceRBP)
fmt.Printf("Reject (rbp): %v\n", rejectRBP)
if !cctx.Bool("rbp-only") {
fmt.Printf("Total deal bytes: %v\n", acceptanceDealBytes+rejectDealBytes)
fmt.Printf("Accept (deal bytes): %v\n", acceptanceDealBytes)
fmt.Printf("Reject (byte): %v\n", rejectDealBytes)
}
return nil
},
}
var tokenHolderCmd = &cli.Command{
Name: "token-holder",
Usage: "get poll result for token holder group",
@ -223,13 +548,11 @@ var tokenHolderCmd = &cli.Command{
for _, ms := range m.Signer {
if ms == si {
if mv, found := msigPendingVotes[m.ID]; found { //other singer has voted
if v.OptionID == APPROVE {
mv.AcceptanceSingers = append(mv.AcceptanceSingers, v.SignerAddress)
} else {
mv.RejectionSigners = append(mv.RejectionSigners, v.SignerAddress)
}
//check if threshold meet
if uint64(len(mv.AcceptanceSingers)) == m.Threshold {
delete(msigPendingVotes, m.ID)
@ -243,7 +566,6 @@ var tokenHolderCmd = &cli.Command{
msigPendingVotes[m.ID] = mv
}
} else {
n := msigVote{
Multisig: m,
}
@ -274,9 +596,9 @@ var tokenHolderCmd = &cli.Command{
fmt.Printf("\nTotal amount of singers: %v\n ", len(votes))
fmt.Printf("Total amount of valid multisig vote: %v\n ", len(msigFinalVotes))
fmt.Printf("Total balance: %v\n", types.BigAdd(acceptanceBalance, rejectionBalance).String())
fmt.Printf("Approve (#): %v\n", acceptanceVote)
fmt.Printf("Option (#): %v\n", acceptanceVote)
fmt.Printf("Reject (#): %v\n", rejectionVote)
fmt.Printf("Approve (FIL): %v\n", acceptanceBalance.String())
fmt.Printf("Option (FIL): %v\n", acceptanceBalance.String())
fmt.Printf("Reject (FIL): %v\n", rejectionBalance.String())
av := types.BigDivFloat(acceptanceBalance, types.BigAdd(acceptanceBalance, rejectionBalance))
rv := types.BigDivFloat(rejectionBalance, types.BigAdd(rejectionBalance, acceptanceBalance))
@ -376,7 +698,21 @@ var clientCmd = &cli.Command{
return xerrors.Errorf("fail to load market actor: ", err)
}
//get all market proposals, add load the # of the bytes each client has made
dps, _ := ms.Proposals()
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")
}
acceptanceBytes := abi.PaddedPieceSize(0)
rejectionBytes := abi.PaddedPieceSize(0)
acceptanceCount := 0
@ -389,27 +725,22 @@ var clientCmd = &cli.Command{
if err != nil {
return xerrors.Errorf("cannot resolve singer: ", ai)
}
if err := dps.ForEach(func(dealID abi.DealID, d market.DealProposal) error {
if d.Client == ai {
if v.OptionID == APPROVE {
acceptanceBytes += d.PieceSize
acceptanceCount += 1
} else {
rejectionBytes += d.PieceSize
rejectionCount += 1
}
if ds, found := cds[ai]; found {
if v.OptionID == APPROVE {
acceptanceBytes += ds
acceptanceCount += 1
} else {
rejectionBytes += ds
rejectionCount += 1
}
return nil
}); err != nil {
return err
}
}
fmt.Printf("\nTotal amount of clients: %v\n", acceptanceCount+rejectionCount)
fmt.Printf("Total deal bytes: %v\n", acceptanceBytes+rejectionBytes)
fmt.Printf("Approve (#): %v\n", acceptanceCount)
fmt.Printf("Accept (#): %v\n", acceptanceCount)
fmt.Printf("Reject (#): %v\n", rejectionCount)
fmt.Printf("Approve (byte): %v\n", acceptanceBytes)
fmt.Printf("Accept (byte): %v\n", acceptanceBytes)
fmt.Printf("Reject (byte): %v\n", rejectionBytes)
av := float64(acceptanceBytes) / float64(acceptanceBytes+rejectionBytes)
rv := float64(rejectionBytes) / float64(acceptanceBytes+rejectionBytes)