github.com/Gessiux/neatchain@v1.3.1/chain/consensus/neatcon/api.go (about) 1 package neatcon 2 3 import ( 4 "errors" 5 "fmt" 6 "math/big" 7 8 "github.com/Gessiux/go-crypto" 9 "github.com/Gessiux/neatchain/chain/consensus" 10 "github.com/Gessiux/neatchain/chain/consensus/neatcon/epoch" 11 ntcTypes "github.com/Gessiux/neatchain/chain/consensus/neatcon/types" 12 "github.com/Gessiux/neatchain/utilities/common" 13 "github.com/Gessiux/neatchain/utilities/common/hexutil" 14 neatCrypto "github.com/Gessiux/neatchain/utilities/crypto" 15 ) 16 17 // API is a user facing RPC API of NeatCon 18 type API struct { 19 chain consensus.ChainReader 20 neatcon *backend 21 } 22 23 // GetCurrentEpochNumber retrieves the current epoch number. 24 func (api *API) GetCurrentEpochNumber() (hexutil.Uint64, error) { 25 return hexutil.Uint64(api.neatcon.core.consensusState.Epoch.Number), nil 26 } 27 28 // GetEpoch retrieves the Epoch Detail by Number 29 func (api *API) GetEpoch(num hexutil.Uint64) (*ntcTypes.EpochApiForConsole, error) { 30 31 number := uint64(num) 32 var resultEpoch *epoch.Epoch 33 curEpoch := api.neatcon.core.consensusState.Epoch 34 if number < 0 || number > curEpoch.Number { 35 return nil, errors.New("epoch number out of range") 36 } 37 38 if number == curEpoch.Number { 39 resultEpoch = curEpoch 40 } else { 41 resultEpoch = epoch.LoadOneEpoch(curEpoch.GetDB(), number, nil) 42 } 43 44 validators := make([]*ntcTypes.EpochValidatorForConsole, len(resultEpoch.Validators.Validators)) 45 for i, val := range resultEpoch.Validators.Validators { 46 validators[i] = &ntcTypes.EpochValidatorForConsole{ 47 Address: common.BytesToAddress(val.Address).String(), 48 PubKey: val.PubKey.KeyString(), 49 Amount: (*hexutil.Big)(val.VotingPower), 50 RemainingEpoch: hexutil.Uint64(val.RemainingEpoch), 51 } 52 } 53 54 return &ntcTypes.EpochApiForConsole{ 55 Number: hexutil.Uint64(resultEpoch.Number), 56 RewardPerBlock: (*hexutil.Big)(resultEpoch.RewardPerBlock), 57 StartBlock: hexutil.Uint64(resultEpoch.StartBlock), 58 EndBlock: hexutil.Uint64(resultEpoch.EndBlock), 59 StartTime: resultEpoch.StartTime, 60 EndTime: resultEpoch.EndTime, 61 Validators: validators, 62 }, nil 63 } 64 65 // GetEpochVote 66 func (api *API) GetNextEpochVote() (*ntcTypes.EpochVotesApiForConsole, error) { 67 68 ep := api.neatcon.core.consensusState.Epoch 69 if ep.GetNextEpoch() != nil { 70 71 var votes []*epoch.EpochValidatorVote 72 if ep.GetNextEpoch().GetEpochValidatorVoteSet() != nil { 73 votes = ep.GetNextEpoch().GetEpochValidatorVoteSet().Votes 74 } 75 votesApi := make([]*ntcTypes.EpochValidatorVoteApiForConsole, 0, len(votes)) 76 for _, v := range votes { 77 var pkstring string 78 if v.PubKey != nil { 79 pkstring = v.PubKey.KeyString() 80 } 81 82 votesApi = append(votesApi, &ntcTypes.EpochValidatorVoteApiForConsole{ 83 EpochValidatorForConsole: ntcTypes.EpochValidatorForConsole{ 84 Address: v.Address.String(), 85 PubKey: pkstring, 86 Amount: (*hexutil.Big)(v.Amount), 87 }, 88 Salt: v.Salt, 89 VoteHash: v.VoteHash, 90 TxHash: v.TxHash, 91 }) 92 } 93 94 return &ntcTypes.EpochVotesApiForConsole{ 95 EpochNumber: hexutil.Uint64(ep.GetNextEpoch().Number), 96 StartBlock: hexutil.Uint64(ep.GetNextEpoch().StartBlock), 97 EndBlock: hexutil.Uint64(ep.GetNextEpoch().EndBlock), 98 Votes: votesApi, 99 }, nil 100 } 101 return nil, errors.New("next epoch has not been proposed") 102 } 103 104 func (api *API) GetNextEpochValidators() ([]*ntcTypes.EpochValidatorForConsole, error) { 105 106 //height := api.chain.CurrentBlock().NumberU64() 107 108 ep := api.neatcon.core.consensusState.Epoch 109 nextEp := ep.GetNextEpoch() 110 if nextEp == nil { 111 return nil, errors.New("voting for next epoch has not started yet") 112 } else { 113 state, err := api.chain.State() 114 if err != nil { 115 return nil, err 116 } 117 118 nextValidators := ep.Validators.Copy() 119 err = epoch.DryRunUpdateEpochValidatorSet(state, nextValidators, nextEp.GetEpochValidatorVoteSet()) 120 if err != nil { 121 return nil, err 122 } 123 124 validators := make([]*ntcTypes.EpochValidatorForConsole, 0, len(nextValidators.Validators)) 125 for _, val := range nextValidators.Validators { 126 var pkstring string 127 if val.PubKey != nil { 128 pkstring = val.PubKey.KeyString() 129 } 130 validators = append(validators, &ntcTypes.EpochValidatorForConsole{ 131 Address: common.BytesToAddress(val.Address).String(), 132 PubKey: pkstring, 133 Amount: (*hexutil.Big)(val.VotingPower), 134 RemainingEpoch: hexutil.Uint64(val.RemainingEpoch), 135 }) 136 } 137 138 return validators, nil 139 } 140 } 141 142 // CreateValidator 143 func (api *API) CreateValidator(from common.Address) (*ntcTypes.PrivV, error) { 144 validator := ntcTypes.GenPrivValidatorKey(from) 145 privV := &ntcTypes.PrivV{ 146 Address: validator.Address.String(), 147 PubKey: validator.PubKey, 148 PrivKey: validator.PrivKey, 149 } 150 return privV, nil 151 } 152 153 // decode extra data 154 func (api *API) DecodeExtraData(extra string) (extraApi *ntcTypes.NeatConExtraApi, err error) { 155 ncExtra, err := ntcTypes.DecodeExtraData(extra) 156 if err != nil { 157 return nil, err 158 } 159 extraApi = &ntcTypes.NeatConExtraApi{ 160 ChainID: ncExtra.ChainID, 161 Height: hexutil.Uint64(ncExtra.Height), 162 Time: ncExtra.Time, 163 NeedToSave: ncExtra.NeedToSave, 164 NeedToBroadcast: ncExtra.NeedToBroadcast, 165 EpochNumber: hexutil.Uint64(ncExtra.EpochNumber), 166 SeenCommitHash: hexutil.Encode(ncExtra.SeenCommitHash), 167 ValidatorsHash: hexutil.Encode(ncExtra.ValidatorsHash), 168 SeenCommit: &ntcTypes.CommitApi{ 169 BlockID: ntcTypes.BlockIDApi{ 170 Hash: hexutil.Encode(ncExtra.SeenCommit.BlockID.Hash), 171 PartsHeader: ntcTypes.PartSetHeaderApi{ 172 Total: hexutil.Uint64(ncExtra.SeenCommit.BlockID.PartsHeader.Total), 173 Hash: hexutil.Encode(ncExtra.SeenCommit.BlockID.PartsHeader.Hash), 174 }, 175 }, 176 Height: hexutil.Uint64(ncExtra.SeenCommit.Height), 177 Round: ncExtra.SeenCommit.Round, 178 SignAggr: ncExtra.SeenCommit.SignAggr, 179 BitArray: ncExtra.SeenCommit.BitArray, 180 }, 181 EpochBytes: ncExtra.EpochBytes, 182 } 183 return extraApi, nil 184 } 185 186 // get consensus publickey of the block 187 func (api *API) GetConsensusPublicKey(extra string) ([]string, error) { 188 ncExtra, err := ntcTypes.DecodeExtraData(extra) 189 if err != nil { 190 return nil, err 191 } 192 193 //fmt.Printf("GetConsensusPublicKey ncExtra %v\n", ncExtra) 194 number := uint64(ncExtra.EpochNumber) 195 var resultEpoch *epoch.Epoch 196 curEpoch := api.neatcon.core.consensusState.Epoch 197 if number < 0 || number > curEpoch.Number { 198 return nil, errors.New("epoch number out of range") 199 } 200 201 if number == curEpoch.Number { 202 resultEpoch = curEpoch 203 } else { 204 resultEpoch = epoch.LoadOneEpoch(curEpoch.GetDB(), number, nil) 205 } 206 207 //fmt.Printf("GetConsensusPublicKey result epoch %v\n", resultEpoch) 208 validatorSet := resultEpoch.Validators 209 //fmt.Printf("GetConsensusPublicKey validatorset %v\n", validatorSet) 210 211 aggr, err := validatorSet.GetAggrPubKeyAndAddress(ncExtra.SeenCommit.BitArray) 212 if err != nil { 213 return nil, err 214 } 215 216 var pubkeys []string 217 if len(aggr.PublicKeys) > 0 { 218 for _, v := range aggr.PublicKeys { 219 if v != "" { 220 pubkeys = append(pubkeys, v) 221 } 222 } 223 } 224 225 return pubkeys, nil 226 } 227 228 func (api *API) GetVoteHash(from common.Address, pubkey crypto.BLSPubKey, amount *hexutil.Big, salt string) common.Hash { 229 byteData := [][]byte{ 230 from.Bytes(), 231 pubkey.Bytes(), 232 (*big.Int)(amount).Bytes(), 233 []byte(salt), 234 } 235 return neatCrypto.Keccak256Hash(ConcatCopyPreAllocate(byteData)) 236 } 237 238 func (api *API) GetValidatorStatus(from common.Address) (*ntcTypes.ValidatorStatus, error) { 239 state, err := api.chain.State() 240 if state == nil || err != nil { 241 return nil, err 242 } 243 status := &ntcTypes.ValidatorStatus{ 244 IsForbidden: state.GetOrNewStateObject(from).IsForbidden(), 245 } 246 247 return status, nil 248 } 249 250 func (api *API) GetCandidateList() (*ntcTypes.CandidateApi, error) { 251 state, err := api.chain.State() 252 253 if state == nil || err != nil { 254 return nil, err 255 } 256 257 candidateList := make([]string, 0) 258 candidateSet := state.GetCandidateSet() 259 fmt.Printf("candidate set %v", candidateSet) 260 for addr := range candidateSet { 261 candidateList = append(candidateList, addr.String()) 262 } 263 264 candidates := &ntcTypes.CandidateApi{ 265 CandidateList: candidateList, 266 } 267 268 return candidates, nil 269 } 270 271 func (api *API) GetForbiddenList() (*ntcTypes.ForbiddenApi, error) { 272 state, err := api.chain.State() 273 274 if state == nil || err != nil { 275 return nil, err 276 } 277 278 forbiddenList := make([]string, 0) 279 forbiddenSet := state.GetForbiddenSet() 280 fmt.Printf("forbidden set %v", forbiddenSet) 281 for addr := range forbiddenSet { 282 forbiddenList = append(forbiddenList, addr.String()) 283 } 284 285 forbiddenAddresses := &ntcTypes.ForbiddenApi{ 286 ForbiddenList: forbiddenList, 287 } 288 289 return forbiddenAddresses, nil 290 }