wip
This commit is contained in:
parent
5f5491a9e5
commit
3d5ecf25b2
@ -7,6 +7,10 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"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/lotus/chain/actors/builtin/market"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
@ -36,6 +40,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const APPROVE = 49
|
const APPROVE = 49
|
||||||
|
const Reject = 50
|
||||||
|
|
||||||
type Vote struct {
|
type Vote struct {
|
||||||
OptionID uint64 `json: "optionId"`
|
OptionID uint64 `json: "optionId"`
|
||||||
@ -62,8 +67,7 @@ var fip0036PollResultcmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
//spRBPCmd,
|
spRBPAndDealCmd,
|
||||||
//spDealByteCmd,
|
|
||||||
clientCmd,
|
clientCmd,
|
||||||
tokenHolderCmd,
|
tokenHolderCmd,
|
||||||
//coreDevCmd,
|
//coreDevCmd,
|
||||||
@ -85,6 +89,23 @@ func getVoters(file string) ([]Vote, error) {
|
|||||||
return votes, nil
|
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) {
|
func getAllMsig(st *state.StateTree, store adt.Store) ([]msigBriefInfo, error) {
|
||||||
|
|
||||||
var msigActorsInfo []msigBriefInfo
|
var msigActorsInfo []msigBriefInfo
|
||||||
@ -115,6 +136,310 @@ func getAllMsig(st *state.StateTree, store adt.Store) ([]msigBriefInfo, error) {
|
|||||||
return msigActorsInfo, nil
|
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{
|
var tokenHolderCmd = &cli.Command{
|
||||||
Name: "token-holder",
|
Name: "token-holder",
|
||||||
Usage: "get poll result for token holder group",
|
Usage: "get poll result for token holder group",
|
||||||
@ -223,13 +548,11 @@ var tokenHolderCmd = &cli.Command{
|
|||||||
for _, ms := range m.Signer {
|
for _, ms := range m.Signer {
|
||||||
if ms == si {
|
if ms == si {
|
||||||
if mv, found := msigPendingVotes[m.ID]; found { //other singer has voted
|
if mv, found := msigPendingVotes[m.ID]; found { //other singer has voted
|
||||||
|
|
||||||
if v.OptionID == APPROVE {
|
if v.OptionID == APPROVE {
|
||||||
mv.AcceptanceSingers = append(mv.AcceptanceSingers, v.SignerAddress)
|
mv.AcceptanceSingers = append(mv.AcceptanceSingers, v.SignerAddress)
|
||||||
} else {
|
} else {
|
||||||
mv.RejectionSigners = append(mv.RejectionSigners, v.SignerAddress)
|
mv.RejectionSigners = append(mv.RejectionSigners, v.SignerAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if threshold meet
|
//check if threshold meet
|
||||||
if uint64(len(mv.AcceptanceSingers)) == m.Threshold {
|
if uint64(len(mv.AcceptanceSingers)) == m.Threshold {
|
||||||
delete(msigPendingVotes, m.ID)
|
delete(msigPendingVotes, m.ID)
|
||||||
@ -243,7 +566,6 @@ var tokenHolderCmd = &cli.Command{
|
|||||||
msigPendingVotes[m.ID] = mv
|
msigPendingVotes[m.ID] = mv
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
n := msigVote{
|
n := msigVote{
|
||||||
Multisig: m,
|
Multisig: m,
|
||||||
}
|
}
|
||||||
@ -274,9 +596,9 @@ var tokenHolderCmd = &cli.Command{
|
|||||||
fmt.Printf("\nTotal amount of singers: %v\n ", len(votes))
|
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 amount of valid multisig vote: %v\n ", len(msigFinalVotes))
|
||||||
fmt.Printf("Total balance: %v\n", types.BigAdd(acceptanceBalance, rejectionBalance).String())
|
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("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())
|
fmt.Printf("Reject (FIL): %v\n", rejectionBalance.String())
|
||||||
av := types.BigDivFloat(acceptanceBalance, types.BigAdd(acceptanceBalance, rejectionBalance))
|
av := types.BigDivFloat(acceptanceBalance, types.BigAdd(acceptanceBalance, rejectionBalance))
|
||||||
rv := types.BigDivFloat(rejectionBalance, types.BigAdd(rejectionBalance, acceptanceBalance))
|
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)
|
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()
|
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)
|
acceptanceBytes := abi.PaddedPieceSize(0)
|
||||||
rejectionBytes := abi.PaddedPieceSize(0)
|
rejectionBytes := abi.PaddedPieceSize(0)
|
||||||
acceptanceCount := 0
|
acceptanceCount := 0
|
||||||
@ -389,27 +725,22 @@ var clientCmd = &cli.Command{
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("cannot resolve singer: ", ai)
|
return xerrors.Errorf("cannot resolve singer: ", ai)
|
||||||
}
|
}
|
||||||
if err := dps.ForEach(func(dealID abi.DealID, d market.DealProposal) error {
|
|
||||||
|
|
||||||
if d.Client == ai {
|
if ds, found := cds[ai]; found {
|
||||||
if v.OptionID == APPROVE {
|
if v.OptionID == APPROVE {
|
||||||
acceptanceBytes += d.PieceSize
|
acceptanceBytes += ds
|
||||||
acceptanceCount += 1
|
acceptanceCount += 1
|
||||||
} else {
|
} else {
|
||||||
rejectionBytes += d.PieceSize
|
rejectionBytes += ds
|
||||||
rejectionCount += 1
|
rejectionCount += 1
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Printf("\nTotal amount of clients: %v\n", acceptanceCount+rejectionCount)
|
fmt.Printf("\nTotal amount of clients: %v\n", acceptanceCount+rejectionCount)
|
||||||
fmt.Printf("Total deal bytes: %v\n", acceptanceBytes+rejectionBytes)
|
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("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)
|
fmt.Printf("Reject (byte): %v\n", rejectionBytes)
|
||||||
av := float64(acceptanceBytes) / float64(acceptanceBytes+rejectionBytes)
|
av := float64(acceptanceBytes) / float64(acceptanceBytes+rejectionBytes)
|
||||||
rv := float64(rejectionBytes) / float64(acceptanceBytes+rejectionBytes)
|
rv := float64(rejectionBytes) / float64(acceptanceBytes+rejectionBytes)
|
||||||
|
Loading…
Reference in New Issue
Block a user