github.com/datachainlab/burrow@v0.25.0/deploy/proposals/proposals.go (about) 1 package proposals 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "github.com/hyperledger/burrow/deploy/def" 9 "github.com/hyperledger/burrow/logging" 10 "github.com/hyperledger/burrow/txs" 11 "github.com/hyperledger/burrow/txs/payload" 12 ) 13 14 type ProposalState int 15 16 const ( 17 ALL ProposalState = 1 + iota 18 FAILED 19 EXECUTED 20 EXPIRED 21 PROPOSED 22 ) 23 24 func (p *ProposalState) String() string { 25 switch *p { 26 case ALL: 27 return "ALL" 28 case FAILED: 29 return "FAILED" 30 case EXECUTED: 31 return "EXECUTED" 32 case EXPIRED: 33 return "EXPIRED" 34 case PROPOSED: 35 return "PROPOSED" 36 default: 37 panic(fmt.Sprintf("unknown propopsal state %d", *p)) 38 } 39 } 40 41 func ProposalStateFromString(s string) (ProposalState, error) { 42 if strings.EqualFold(s, "all") { 43 return ALL, nil 44 } 45 if strings.EqualFold(s, "failed") { 46 return FAILED, nil 47 } 48 if strings.EqualFold(s, "executed") { 49 return EXECUTED, nil 50 } 51 if strings.EqualFold(s, "expired") { 52 return EXPIRED, nil 53 } 54 if strings.EqualFold(s, "proposed") { 55 return PROPOSED, nil 56 } 57 58 return ALL, fmt.Errorf("Unknown proposal state %s", s) 59 } 60 61 func ListProposals(args *def.DeployArgs, reqState ProposalState, logger *logging.Logger) error { 62 client := def.NewClient(args.Chain, args.KeysService, args.MempoolSign, time.Duration(args.Timeout)*time.Second) 63 64 props, err := client.ListProposals(reqState == PROPOSED, logger) 65 if err != nil { 66 return err 67 } 68 69 for _, prop := range props { 70 var state string 71 switch prop.Ballot.ProposalState { 72 case payload.Ballot_FAILED: 73 state = "FAILED" 74 case payload.Ballot_EXECUTED: 75 state = "EXECUTED" 76 case payload.Ballot_PROPOSED: 77 if ProposalExpired(prop.Ballot.Proposal, client, logger) != nil { 78 state = "EXPIRED" 79 } else { 80 state = "PROPOSED" 81 } 82 } 83 84 if !strings.EqualFold(state, reqState.String()) && reqState != ALL { 85 continue 86 } 87 88 logger.InfoMsg("Proposal", 89 "ProposalHash", fmt.Sprintf("%x", prop.Hash), 90 "Name", prop.Ballot.Proposal.Name, 91 "Description", prop.Ballot.Proposal.Description, 92 "State", state, 93 "Votes", len(prop.Ballot.GetVotes())) 94 } 95 96 return nil 97 } 98 99 func ProposalExpired(proposal *payload.Proposal, client *def.Client, logger *logging.Logger) error { 100 for _, input := range proposal.BatchTx.Inputs { 101 acc, err := client.GetAccount(input.Address) 102 if err != nil { 103 return err 104 } 105 106 if input.Sequence != acc.Sequence+1 { 107 return fmt.Errorf("Proposal has expired, account %s is out of sequence", input.Address.String()) 108 } 109 } 110 111 for i, step := range proposal.BatchTx.Txs { 112 txEnv := txs.EnvelopeFromAny("", step) 113 114 for _, input := range txEnv.Tx.GetInputs() { 115 acc, err := client.GetAccount(input.Address) 116 if err != nil { 117 return err 118 } 119 120 if input.Sequence != acc.Sequence+1 { 121 return fmt.Errorf("Proposal has expired, account %s at step %d is expired", input.Address.String(), i) 122 } 123 } 124 } 125 126 return nil 127 }