github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/chain/consensus/neatcon/api.go (about) 1 package neatcon 2 3 import ( 4 "errors" 5 "math/big" 6 7 "github.com/neatio-net/crypto-go" 8 "github.com/neatio-net/neatio/chain/consensus" 9 "github.com/neatio-net/neatio/chain/consensus/neatcon/epoch" 10 ntcTypes "github.com/neatio-net/neatio/chain/consensus/neatcon/types" 11 "github.com/neatio-net/neatio/utilities/common" 12 "github.com/neatio-net/neatio/utilities/common/hexutil" 13 neatCrypto "github.com/neatio-net/neatio/utilities/crypto" 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 }