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  }