github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/chain/consensus/neatcon/api.go (about)

     1  package neatcon
     2  
     3  import (
     4  	"errors"
     5  	"math/big"
     6  
     7  	"github.com/neatlab/neatio/chain/consensus"
     8  	"github.com/neatlab/neatio/chain/consensus/neatcon/epoch"
     9  	ntcTypes "github.com/neatlab/neatio/chain/consensus/neatcon/types"
    10  	"github.com/neatlab/neatio/utilities/common"
    11  	"github.com/neatlab/neatio/utilities/common/hexutil"
    12  	neatCrypto "github.com/neatlab/neatio/utilities/crypto"
    13  	"github.com/neatlib/crypto-go"
    14  )
    15  
    16  type API struct {
    17  	chain   consensus.ChainReader
    18  	neatcon *backend
    19  }
    20  
    21  func (api *API) GetCurrentEpochNumber() (hexutil.Uint64, error) {
    22  	return hexutil.Uint64(api.neatcon.core.consensusState.Epoch.Number), nil
    23  }
    24  
    25  func (api *API) GetEpoch(num hexutil.Uint64) (*ntcTypes.EpochApi, error) {
    26  
    27  	number := uint64(num)
    28  	var resultEpoch *epoch.Epoch
    29  	curEpoch := api.neatcon.core.consensusState.Epoch
    30  	if number < 0 || number > curEpoch.Number {
    31  		return nil, errors.New("epoch number out of range")
    32  	}
    33  
    34  	if number == curEpoch.Number {
    35  		resultEpoch = curEpoch
    36  	} else {
    37  		resultEpoch = epoch.LoadOneEpoch(curEpoch.GetDB(), number, nil)
    38  	}
    39  
    40  	validators := make([]*ntcTypes.EpochValidator, len(resultEpoch.Validators.Validators))
    41  	for i, val := range resultEpoch.Validators.Validators {
    42  		validators[i] = &ntcTypes.EpochValidator{
    43  			Address:        common.BytesToAddress(val.Address),
    44  			PubKey:         val.PubKey.KeyString(),
    45  			Amount:         (*hexutil.Big)(val.VotingPower),
    46  			RemainingEpoch: hexutil.Uint64(val.RemainingEpoch),
    47  		}
    48  	}
    49  
    50  	return &ntcTypes.EpochApi{
    51  		Number:         hexutil.Uint64(resultEpoch.Number),
    52  		RewardPerBlock: (*hexutil.Big)(resultEpoch.RewardPerBlock),
    53  		StartBlock:     hexutil.Uint64(resultEpoch.StartBlock),
    54  		EndBlock:       hexutil.Uint64(resultEpoch.EndBlock),
    55  		StartTime:      resultEpoch.StartTime,
    56  		EndTime:        resultEpoch.EndTime,
    57  		Validators:     validators,
    58  	}, nil
    59  }
    60  
    61  func (api *API) GetNextEpochVote() (*ntcTypes.EpochVotesApi, error) {
    62  
    63  	ep := api.neatcon.core.consensusState.Epoch
    64  	if ep.GetNextEpoch() != nil {
    65  
    66  		var votes []*epoch.EpochValidatorVote
    67  		if ep.GetNextEpoch().GetEpochValidatorVoteSet() != nil {
    68  			votes = ep.GetNextEpoch().GetEpochValidatorVoteSet().Votes
    69  		}
    70  		votesApi := make([]*ntcTypes.EpochValidatorVoteApi, 0, len(votes))
    71  		for _, v := range votes {
    72  			var pkstring string
    73  			if v.PubKey != nil {
    74  				pkstring = v.PubKey.KeyString()
    75  			}
    76  
    77  			votesApi = append(votesApi, &ntcTypes.EpochValidatorVoteApi{
    78  				EpochValidator: ntcTypes.EpochValidator{
    79  					Address: v.Address,
    80  					PubKey:  pkstring,
    81  					Amount:  (*hexutil.Big)(v.Amount),
    82  				},
    83  				Salt:     v.Salt,
    84  				VoteHash: v.VoteHash,
    85  				TxHash:   v.TxHash,
    86  			})
    87  		}
    88  
    89  		return &ntcTypes.EpochVotesApi{
    90  			EpochNumber: hexutil.Uint64(ep.GetNextEpoch().Number),
    91  			StartBlock:  hexutil.Uint64(ep.GetNextEpoch().StartBlock),
    92  			EndBlock:    hexutil.Uint64(ep.GetNextEpoch().EndBlock),
    93  			Votes:       votesApi,
    94  		}, nil
    95  	}
    96  	return nil, errors.New("next epoch has not been proposed")
    97  }
    98  
    99  func (api *API) GetNextEpochValidators() ([]*ntcTypes.EpochValidator, error) {
   100  
   101  	ep := api.neatcon.core.consensusState.Epoch
   102  	nextEp := ep.GetNextEpoch()
   103  	if nextEp == nil {
   104  		return nil, errors.New("voting for next epoch has not started yet")
   105  	} else {
   106  		state, err := api.chain.State()
   107  		if err != nil {
   108  			return nil, err
   109  		}
   110  
   111  		nextValidators := ep.Validators.Copy()
   112  
   113  		err = epoch.DryRunUpdateEpochValidatorSet(state, nextValidators, nextEp.GetEpochValidatorVoteSet())
   114  		if err != nil {
   115  			return nil, err
   116  		}
   117  
   118  		validators := make([]*ntcTypes.EpochValidator, 0, len(nextValidators.Validators))
   119  		for _, val := range nextValidators.Validators {
   120  			var pkstring string
   121  			if val.PubKey != nil {
   122  				pkstring = val.PubKey.KeyString()
   123  			}
   124  			validators = append(validators, &ntcTypes.EpochValidator{
   125  				Address:        common.BytesToAddress(val.Address),
   126  				PubKey:         pkstring,
   127  				Amount:         (*hexutil.Big)(val.VotingPower),
   128  				RemainingEpoch: hexutil.Uint64(val.RemainingEpoch),
   129  			})
   130  		}
   131  
   132  		return validators, nil
   133  	}
   134  }
   135  
   136  func (api *API) DecodeExtraData(extra string) (extraApi *ntcTypes.NeatConExtraApi, err error) {
   137  	ncExtra, err := ntcTypes.DecodeExtraData(extra)
   138  	if err != nil {
   139  		return nil, err
   140  	}
   141  	extraApi = &ntcTypes.NeatConExtraApi{
   142  		ChainID:         ncExtra.ChainID,
   143  		Height:          hexutil.Uint64(ncExtra.Height),
   144  		Time:            ncExtra.Time,
   145  		NeedToSave:      ncExtra.NeedToSave,
   146  		NeedToBroadcast: ncExtra.NeedToBroadcast,
   147  		EpochNumber:     hexutil.Uint64(ncExtra.EpochNumber),
   148  		SeenCommitHash:  hexutil.Encode(ncExtra.SeenCommitHash),
   149  		ValidatorsHash:  hexutil.Encode(ncExtra.ValidatorsHash),
   150  		SeenCommit: &ntcTypes.CommitApi{
   151  			BlockID: ntcTypes.BlockIDApi{
   152  				Hash: hexutil.Encode(ncExtra.SeenCommit.BlockID.Hash),
   153  				PartsHeader: ntcTypes.PartSetHeaderApi{
   154  					Total: hexutil.Uint64(ncExtra.SeenCommit.BlockID.PartsHeader.Total),
   155  					Hash:  hexutil.Encode(ncExtra.SeenCommit.BlockID.PartsHeader.Hash),
   156  				},
   157  			},
   158  			Height:   hexutil.Uint64(ncExtra.SeenCommit.Height),
   159  			Round:    ncExtra.SeenCommit.Round,
   160  			SignAggr: ncExtra.SeenCommit.SignAggr,
   161  			BitArray: ncExtra.SeenCommit.BitArray,
   162  		},
   163  		EpochBytes: ncExtra.EpochBytes,
   164  	}
   165  	return extraApi, nil
   166  }
   167  
   168  func (api *API) GetConsensusPublicKey(extra string) ([]string, error) {
   169  	ncExtra, err := ntcTypes.DecodeExtraData(extra)
   170  	if err != nil {
   171  		return nil, err
   172  	}
   173  
   174  	number := uint64(ncExtra.EpochNumber)
   175  	var resultEpoch *epoch.Epoch
   176  	curEpoch := api.neatcon.core.consensusState.Epoch
   177  	if number < 0 || number > curEpoch.Number {
   178  		return nil, errors.New("epoch number out of range")
   179  	}
   180  
   181  	if number == curEpoch.Number {
   182  		resultEpoch = curEpoch
   183  	} else {
   184  		resultEpoch = epoch.LoadOneEpoch(curEpoch.GetDB(), number, nil)
   185  	}
   186  
   187  	validatorSet := resultEpoch.Validators
   188  
   189  	aggr, err := validatorSet.GetAggrPubKeyAndAddress(ncExtra.SeenCommit.BitArray)
   190  	if err != nil {
   191  		return nil, err
   192  	}
   193  
   194  	var pubkeys []string
   195  	if len(aggr.PublicKeys) > 0 {
   196  		for _, v := range aggr.PublicKeys {
   197  			if v != "" {
   198  				pubkeys = append(pubkeys, v)
   199  			}
   200  		}
   201  	}
   202  
   203  	return pubkeys, nil
   204  }
   205  
   206  func (api *API) GetVoteHash(from common.Address, pubkey crypto.BLSPubKey, amount *hexutil.Big, salt string) common.Hash {
   207  	byteData := [][]byte{
   208  		from.Bytes(),
   209  		pubkey.Bytes(),
   210  		(*big.Int)(amount).Bytes(),
   211  		[]byte(salt),
   212  	}
   213  	return neatCrypto.Keccak256Hash(ConcatCopyPreAllocate(byteData))
   214  }