github.com/DxChainNetwork/dxc@v0.8.1-0.20220824085222-1162e304b6e7/consensus/dpos/api.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package dpos 18 19 import ( 20 "fmt" 21 "github.com/DxChainNetwork/dxc/common" 22 "github.com/DxChainNetwork/dxc/common/hexutil" 23 "github.com/DxChainNetwork/dxc/consensus" 24 "github.com/DxChainNetwork/dxc/consensus/dpos/systemcontract" 25 "github.com/DxChainNetwork/dxc/core/state" 26 "github.com/DxChainNetwork/dxc/core/types" 27 "github.com/DxChainNetwork/dxc/rpc" 28 "math/big" 29 ) 30 31 // API is a user facing RPC API to allow controlling the validator and voting 32 // mechanisms of the proof-of-authority scheme. 33 type API struct { 34 chain consensus.ChainHeaderReader 35 dpos *Dpos 36 } 37 38 type ProposalInfo struct { 39 Id string 40 Proposer common.Address 41 PType uint8 42 Deposit *big.Int 43 Rate uint8 44 Details string 45 Name string 46 InitBlock *big.Int 47 Guarantee common.Address 48 UpdateBlock *big.Int 49 Status uint8 50 } 51 52 func (api *API) GetHeaderAndState(number *rpc.BlockNumber) (*types.Header, *state.StateDB, error) { 53 var header *types.Header 54 if number == nil || *number == rpc.LatestBlockNumber { 55 header = api.chain.CurrentHeader() 56 } else { 57 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 58 } 59 if header == nil { 60 return nil, nil, errUnknownBlock 61 } 62 statedb, err := api.dpos.stateFn(header.Root) 63 return header, statedb, err 64 } 65 66 // GetSnapshot retrieves the state snapshot at a given block. 67 func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) { 68 // Retrieve the requested block number (or current if none requested) 69 var header *types.Header 70 if number == nil || *number == rpc.LatestBlockNumber { 71 header = api.chain.CurrentHeader() 72 } else { 73 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 74 } 75 // Ensure we have an actually valid block and return its snapshot 76 if header == nil { 77 return nil, errUnknownBlock 78 } 79 return api.dpos.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) 80 } 81 82 // GetSnapshotAtHash retrieves the state snapshot at a given block. 83 func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) { 84 header := api.chain.GetHeaderByHash(hash) 85 if header == nil { 86 return nil, errUnknownBlock 87 } 88 return api.dpos.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) 89 } 90 91 // GetValidators retrieves the list of authorized validators at the specified block. 92 func (api *API) GetValidators(number *rpc.BlockNumber) ([]common.Address, error) { 93 // Retrieve the requested block number (or current if none requested) 94 var header *types.Header 95 if number == nil || *number == rpc.LatestBlockNumber { 96 header = api.chain.CurrentHeader() 97 } else { 98 header = api.chain.GetHeaderByNumber(uint64(number.Int64())) 99 } 100 // Ensure we have an actually valid block and return the validators from its snapshot 101 if header == nil { 102 return nil, errUnknownBlock 103 } 104 snap, err := api.dpos.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) 105 if err != nil { 106 return nil, err 107 } 108 return snap.validators(), nil 109 } 110 111 // GetValidatorsAtHash retrieves the list of authorized validators at the specified block. 112 func (api *API) GetValidatorsAtHash(hash common.Hash) ([]common.Address, error) { 113 header := api.chain.GetHeaderByHash(hash) 114 if header == nil { 115 return nil, errUnknownBlock 116 } 117 snap, err := api.dpos.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) 118 if err != nil { 119 return nil, err 120 } 121 return snap.validators(), nil 122 } 123 124 func (api *API) GetBaseInfos(number *rpc.BlockNumber) (map[string]interface{}, error) { 125 base := systemcontract.NewBase() 126 header, statedb, err := api.GetHeaderAndState(number) 127 if err != nil { 128 return map[string]interface{}{}, err 129 } 130 infos, err := base.GetBaseInfos(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig) 131 if err != nil { 132 return map[string]interface{}{}, err 133 } 134 return infos, nil 135 } 136 137 // GetValidator return the validator of address 138 func (api *API) GetValidator(addr common.Address, number *rpc.BlockNumber) (*systemcontract.Validator, error) { 139 validators := systemcontract.NewValidators() 140 header, statedb, err := api.GetHeaderAndState(number) 141 if err != nil { 142 return &systemcontract.Validator{}, err 143 } 144 val, err := validators.GetValidator(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr) 145 if err != nil { 146 return &systemcontract.Validator{}, err 147 } 148 return val, nil 149 } 150 151 // GetTotalDeposit return total deposit 152 func (api *API) GetTotalDeposit(number *rpc.BlockNumber) (*big.Int, error) { 153 validators := systemcontract.NewValidators() 154 header, statedb, err := api.GetHeaderAndState(number) 155 if err != nil { 156 return big.NewInt(0), err 157 } 158 deposit, err := validators.TotalDeposit(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig) 159 if err != nil { 160 return big.NewInt(0), err 161 } 162 return deposit, nil 163 } 164 165 // GetTotalVotes return total votes 166 func (api *API) GetTotalVotes(number *rpc.BlockNumber) (*big.Int, error) { 167 nodeVotes := systemcontract.NewNodeVotes() 168 header, statedb, err := api.GetHeaderAndState(number) 169 if err != nil { 170 return big.NewInt(0), err 171 } 172 totalVotes, err := nodeVotes.TotalVotes(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig) 173 if err != nil { 174 return big.NewInt(0), err 175 } 176 return totalVotes, nil 177 } 178 179 // GetCurrentEpochValidators return current epoch validators 180 func (api *API) GetCurrentEpochValidators(number *rpc.BlockNumber) ([]common.Address, error) { 181 validators := systemcontract.NewValidators() 182 header, statedb, err := api.GetHeaderAndState(number) 183 if err != nil { 184 return []common.Address{}, err 185 } 186 curValidators, err := validators.GetCurrentEpochValidators(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig) 187 if err != nil { 188 return []common.Address{}, err 189 } 190 return curValidators, nil 191 } 192 193 // GetEffictiveValidators return all effictive validators 194 func (api *API) GetEffictiveValidators(number *rpc.BlockNumber) ([]common.Address, error) { 195 validators := systemcontract.NewValidators() 196 header, statedb, err := api.GetHeaderAndState(number) 197 if err != nil { 198 return []common.Address{}, err 199 } 200 201 size := big.NewInt(50) 202 var allValidators []common.Address 203 204 count, err := validators.EffictiveValsLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig) 205 if err != nil { 206 return []common.Address{}, err 207 } 208 209 if count.Cmp(size) <= 0 { 210 page := big.NewInt(1) 211 allValidators, err = validators.GetEffictiveValidatorsWithPage(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, page, size) 212 if err != nil { 213 return []common.Address{}, err 214 } 215 } else { 216 var res big.Int 217 div := res.Div(count, size) 218 div = res.Add(div, big.NewInt(1)) 219 for i := int64(1); i <= div.Int64(); i++ { 220 voters, err := validators.GetEffictiveValidatorsWithPage(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, big.NewInt(i), size) 221 if err != nil { 222 return []common.Address{}, err 223 } 224 allValidators = append(allValidators, voters...) 225 } 226 } 227 228 return allValidators, nil 229 } 230 231 // GetInvalidValidators return all invalid validators 232 func (api *API) GetInvalidValidators(number *rpc.BlockNumber) ([]common.Address, error) { 233 validators := systemcontract.NewValidators() 234 header, statedb, err := api.GetHeaderAndState(number) 235 if err != nil { 236 return []common.Address{}, err 237 } 238 239 size := big.NewInt(50) 240 var invalidValidators []common.Address 241 242 count, err := validators.InvalidValsLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig) 243 if err != nil { 244 return []common.Address{}, err 245 } 246 247 if count.Cmp(size) <= 0 { 248 page := big.NewInt(1) 249 invalidValidators, err = validators.GetInvalidValidatorsWithPage(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, page, size) 250 if err != nil { 251 return []common.Address{}, err 252 } 253 } else { 254 var res big.Int 255 div := res.Div(count, size) 256 div = res.Add(div, big.NewInt(1)) 257 for i := int64(1); i <= div.Int64(); i++ { 258 voters, err := validators.GetInvalidValidatorsWithPage(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, big.NewInt(i), size) 259 if err != nil { 260 return []common.Address{}, err 261 } 262 invalidValidators = append(invalidValidators, voters...) 263 } 264 } 265 266 return invalidValidators, nil 267 } 268 269 // GetCancelQueueValidators return all canceling queue validators 270 func (api *API) GetCancelQueueValidators(number *rpc.BlockNumber) ([]common.Address, error) { 271 validators := systemcontract.NewValidators() 272 header, statedb, err := api.GetHeaderAndState(number) 273 if err != nil { 274 return []common.Address{}, err 275 } 276 cancelingValidators, err := validators.GetCancelQueueValidators(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig) 277 if err != nil { 278 return []common.Address{}, err 279 } 280 return cancelingValidators, nil 281 } 282 283 // GetValidatorVoters return the address voter 284 func (api *API) GetValidatorVoters(addr common.Address, number *rpc.BlockNumber) ([]common.Address, error) { 285 validators := systemcontract.NewValidators() 286 header, statedb, err := api.GetHeaderAndState(number) 287 if err != nil { 288 return []common.Address{}, err 289 } 290 291 size := big.NewInt(50) 292 var allVoters []common.Address 293 294 count, err := validators.ValidatorVotersLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr) 295 if err != nil { 296 return []common.Address{}, err 297 } 298 299 if count.Cmp(size) <= 0 { 300 page := big.NewInt(1) 301 allVoters, err = validators.GetValidatorVoters(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, page, size) 302 if err != nil { 303 return []common.Address{}, err 304 } 305 } else { 306 var res big.Int 307 div := res.Div(count, size) 308 div = res.Add(div, big.NewInt(1)) 309 for i := int64(1); i <= div.Int64(); i++ { 310 voters, err := validators.GetValidatorVoters(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, big.NewInt(i), size) 311 if err != nil { 312 return []common.Address{}, err 313 } 314 allVoters = append(allVoters, voters...) 315 } 316 } 317 318 return allVoters, nil 319 } 320 321 // EffictiveValsLength return effictive validators length 322 func (api *API) EffictiveValsLength(number *rpc.BlockNumber) (*big.Int, error) { 323 validators := systemcontract.NewValidators() 324 header, statedb, err := api.GetHeaderAndState(number) 325 if err != nil { 326 return big.NewInt(0), err 327 } 328 count, err := validators.EffictiveValsLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig) 329 if err != nil { 330 return big.NewInt(0), err 331 } 332 return count, nil 333 } 334 335 // InvalidValsLength return invalid validators length 336 func (api *API) InvalidValsLength(number *rpc.BlockNumber) (*big.Int, error) { 337 validators := systemcontract.NewValidators() 338 header, statedb, err := api.GetHeaderAndState(number) 339 if err != nil { 340 return big.NewInt(0), err 341 } 342 count, err := validators.InvalidValsLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig) 343 if err != nil { 344 return big.NewInt(0), err 345 } 346 return count, nil 347 } 348 349 // CancelQueueValidatorsLength return cancel queue validators length 350 func (api *API) CancelQueueValidatorsLength(number *rpc.BlockNumber) (*big.Int, error) { 351 validators := systemcontract.NewValidators() 352 header, statedb, err := api.GetHeaderAndState(number) 353 if err != nil { 354 return big.NewInt(0), err 355 } 356 count, err := validators.CancelQueueValidatorsLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig) 357 if err != nil { 358 return big.NewInt(0), err 359 } 360 return count, nil 361 } 362 363 // ValidatorVotersLength return the validator voters length 364 func (api *API) ValidatorVotersLength(addr common.Address, number *rpc.BlockNumber) (*big.Int, error) { 365 validators := systemcontract.NewValidators() 366 header, statedb, err := api.GetHeaderAndState(number) 367 if err != nil { 368 return big.NewInt(0), err 369 } 370 count, err := validators.ValidatorVotersLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr) 371 if err != nil { 372 return big.NewInt(0), err 373 } 374 return count, nil 375 } 376 377 // IsEffictiveValidator return the address is validator 378 func (api *API) IsEffictiveValidator(addr common.Address, number *rpc.BlockNumber) (bool, error) { 379 validators := systemcontract.NewValidators() 380 header, statedb, err := api.GetHeaderAndState(number) 381 if err != nil { 382 return false, err 383 } 384 val, err := validators.IsEffictiveValidator(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr) 385 if err != nil { 386 return false, err 387 } 388 return val, nil 389 } 390 391 // Proposals 392 393 // GetAddressProposalSets return the address proposal id 394 func (api *API) GetAddressProposalSets(addr common.Address, number *rpc.BlockNumber) ([]string, error) { 395 proposals := systemcontract.NewProposals() 396 header, statedb, err := api.GetHeaderAndState(number) 397 if err != nil { 398 return []string{}, err 399 } 400 count, err := proposals.AddressProposalCount(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr) 401 if err != nil { 402 return []string{}, err 403 } 404 405 size := big.NewInt(50) 406 var allSets [][4]byte 407 408 if count.Cmp(size) <= 0 { 409 page := big.NewInt(1) 410 allSets, err = proposals.AddressProposalSets(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, page, size) 411 if err != nil { 412 return []string{}, err 413 } 414 } else { 415 var res big.Int 416 div := res.Div(count, size) 417 div = res.Add(div, big.NewInt(1)) 418 for i := int64(1); i <= div.Int64(); i++ { 419 proposalIds, err := proposals.AddressProposalSets(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, big.NewInt(i), size) 420 if err != nil { 421 return []string{}, err 422 } 423 allSets = append(allSets, proposalIds...) 424 } 425 } 426 427 newProposalIds := []string{} 428 for i := 0; i < len(allSets); i++ { 429 id := hexutil.Encode(allSets[i][0:len(allSets[i])]) 430 newProposalIds = append(newProposalIds, id) 431 } 432 return newProposalIds, nil 433 } 434 435 // GetAllProposalSets return all proposals id 436 func (api *API) GetAllProposalSets(number *rpc.BlockNumber) ([]string, error) { 437 proposals := systemcontract.NewProposals() 438 header, statedb, err := api.GetHeaderAndState(number) 439 if err != nil { 440 return []string{}, err 441 } 442 443 count, err := proposals.ProposalCount(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig) 444 if err != nil { 445 return []string{}, err 446 } 447 448 size := big.NewInt(50) 449 var allSets [][4]byte 450 451 if count.Cmp(size) <= 0 { 452 page := big.NewInt(1) 453 allSets, err = proposals.AllProposalSets(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, page, size) 454 if err != nil { 455 return []string{}, err 456 } 457 } else { 458 var res big.Int 459 div := res.Div(count, size) 460 div = res.Add(div, big.NewInt(1)) 461 for i := int64(1); i <= div.Int64(); i++ { 462 proposalIds, err := proposals.AllProposalSets(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, big.NewInt(i), size) 463 if err != nil { 464 return []string{}, err 465 } 466 allSets = append(allSets, proposalIds...) 467 } 468 } 469 470 newProposalIds := []string{} 471 for i := 0; i < len(allSets); i++ { 472 id := hexutil.Encode(allSets[i][0:len(allSets[i])]) 473 newProposalIds = append(newProposalIds, id) 474 } 475 return newProposalIds, nil 476 477 } 478 479 // GetAllProposals return all proposals 480 func (api *API) GetAllProposals(number *rpc.BlockNumber) ([]ProposalInfo, error) { 481 proposals := systemcontract.NewProposals() 482 header, statedb, err := api.GetHeaderAndState(number) 483 if err != nil { 484 return []ProposalInfo{}, err 485 } 486 487 count, err := proposals.ProposalCount(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig) 488 if err != nil { 489 return []ProposalInfo{}, err 490 } 491 492 size := big.NewInt(50) 493 var allProposals []systemcontract.ProposalInfo 494 495 if count.Cmp(size) <= 0 { 496 page := big.NewInt(1) 497 allProposals, err = proposals.AllProposals(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, page, size) 498 if err != nil { 499 return []ProposalInfo{}, err 500 } 501 } else { 502 var res big.Int 503 div := res.Div(count, size) 504 div = res.Add(div, big.NewInt(1)) 505 for i := int64(1); i <= div.Int64(); i++ { 506 proposals, err := proposals.AllProposals(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, big.NewInt(i), size) 507 if err != nil { 508 return []ProposalInfo{}, err 509 } 510 allProposals = append(allProposals, proposals...) 511 } 512 } 513 514 newProposals := []ProposalInfo{} 515 for i := 0; i < len(allProposals); i++ { 516 detail := ProposalInfo{ 517 Id: hexutil.Encode(allProposals[i].Id[0:len(allProposals[i].Id)]), 518 Proposer: allProposals[i].Proposer, 519 UpdateBlock: allProposals[i].UpdateBlock, 520 PType: allProposals[i].PType, 521 Guarantee: allProposals[i].Guarantee, 522 Deposit: allProposals[i].Deposit, 523 Details: allProposals[i].Details, 524 Name: allProposals[i].Name, 525 InitBlock: allProposals[i].InitBlock, 526 Rate: allProposals[i].Rate, 527 Status: allProposals[i].Status, 528 } 529 newProposals = append(newProposals, detail) 530 } 531 return newProposals, nil 532 533 } 534 535 // GetProposal return the proposal of id 536 func (api *API) GetProposal(id string, number *rpc.BlockNumber) (*ProposalInfo, error) { 537 proposals := systemcontract.NewProposals() 538 header, statedb, err := api.GetHeaderAndState(number) 539 if err != nil { 540 return &ProposalInfo{}, err 541 } 542 proposalInfo, err := proposals.GetProposal(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, id) 543 if err != nil { 544 return &ProposalInfo{}, err 545 } 546 detail := &ProposalInfo{ 547 Id: hexutil.Encode(proposalInfo.Id[0:len(proposalInfo.Id)]), 548 Proposer: proposalInfo.Proposer, 549 UpdateBlock: proposalInfo.UpdateBlock, 550 PType: proposalInfo.PType, 551 Guarantee: proposalInfo.Guarantee, 552 Deposit: proposalInfo.Deposit, 553 Details: proposalInfo.Details, 554 Name: proposalInfo.Name, 555 InitBlock: proposalInfo.InitBlock, 556 Rate: proposalInfo.Rate, 557 Status: proposalInfo.Status, 558 } 559 return detail, nil 560 } 561 562 // GetAddressProposals return the address proposals 563 func (api *API) GetAddressProposals(addr common.Address, number *rpc.BlockNumber) ([]ProposalInfo, error) { 564 proposals := systemcontract.NewProposals() 565 header, statedb, err := api.GetHeaderAndState(number) 566 if err != nil { 567 return []ProposalInfo{}, err 568 } 569 570 var allProposals []systemcontract.ProposalInfo 571 size := big.NewInt(50) 572 573 count, err := proposals.AddressProposalCount(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr) 574 if err != nil { 575 return []ProposalInfo{}, err 576 } 577 578 if count.Cmp(size) <= 0 { 579 page := big.NewInt(1) 580 allProposals, err = proposals.AddressProposals(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, page, size) 581 if err != nil { 582 return []ProposalInfo{}, err 583 } 584 } else { 585 var res big.Int 586 div := res.Div(count, size) 587 div = res.Add(div, big.NewInt(1)) 588 for i := int64(1); i <= div.Int64(); i++ { 589 proposalIds, err := proposals.AddressProposals(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, big.NewInt(i), size) 590 if err != nil { 591 return []ProposalInfo{}, err 592 } 593 allProposals = append(allProposals, proposalIds...) 594 } 595 } 596 597 var newProposals []ProposalInfo 598 for i := 0; i < len(allProposals); i++ { 599 detail := ProposalInfo{ 600 Id: hexutil.Encode(allProposals[i].Id[0:len(allProposals[i].Id)]), 601 Proposer: allProposals[i].Proposer, 602 UpdateBlock: allProposals[i].UpdateBlock, 603 PType: allProposals[i].PType, 604 Guarantee: allProposals[i].Guarantee, 605 Deposit: allProposals[i].Deposit, 606 Details: allProposals[i].Details, 607 Name: allProposals[i].Name, 608 InitBlock: allProposals[i].InitBlock, 609 Rate: allProposals[i].Rate, 610 Status: allProposals[i].Status, 611 } 612 newProposals = append(newProposals, detail) 613 } 614 return newProposals, nil 615 } 616 617 // GetProposalCount return all proposal count 618 func (api *API) GetProposalCount(number *rpc.BlockNumber) (*big.Int, error) { 619 proposals := systemcontract.NewProposals() 620 header, statedb, err := api.GetHeaderAndState(number) 621 if err != nil { 622 return big.NewInt(0), err 623 } 624 count, err := proposals.ProposalCount(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig) 625 if err != nil { 626 return big.NewInt(0), err 627 } 628 return count, nil 629 } 630 631 // GetAddressProposalCount return the address proposal count 632 func (api *API) GetAddressProposalCount(addr common.Address, number *rpc.BlockNumber) (*big.Int, error) { 633 proposals := systemcontract.NewProposals() 634 header, statedb, err := api.GetHeaderAndState(number) 635 if err != nil { 636 return big.NewInt(0), err 637 } 638 count, err := proposals.AddressProposalCount(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr) 639 if err != nil { 640 return big.NewInt(0), err 641 } 642 return count, nil 643 } 644 645 // NodeVotes 646 647 // PendingVoteReward return the voter vote the validator rewards 648 func (api *API) PendingVoteReward(val common.Address, voter common.Address, number *rpc.BlockNumber) (*big.Int, error) { 649 nodeVotes := systemcontract.NewNodeVotes() 650 header, statedb, err := api.GetHeaderAndState(number) 651 if err != nil { 652 return big.NewInt(0), err 653 } 654 value, err := nodeVotes.PendingVoteReward(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, val, voter) 655 if err != nil { 656 return big.NewInt(0), err 657 } 658 return value, nil 659 } 660 661 // PendingVoteRedeem return the voter redeem validators voters 662 func (api *API) PendingVoteRedeem(val common.Address, voter common.Address, number *rpc.BlockNumber) (*big.Int, error) { 663 nodeVotes := systemcontract.NewNodeVotes() 664 header, statedb, err := api.GetHeaderAndState(number) 665 if err != nil { 666 return big.NewInt(0), err 667 } 668 value, err := nodeVotes.PendingVoteRedeem(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, val, voter) 669 if err != nil { 670 return big.NewInt(0), err 671 } 672 return value, nil 673 } 674 675 // VoteListLength return the voter vote list length 676 func (api *API) VoteListLength(addr common.Address, number *rpc.BlockNumber) (*big.Int, error) { 677 nodeVotes := systemcontract.NewNodeVotes() 678 header, statedb, err := api.GetHeaderAndState(number) 679 if err != nil { 680 return big.NewInt(0), err 681 } 682 count, err := nodeVotes.VoteListLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr) 683 if err != nil { 684 return big.NewInt(0), err 685 } 686 return count, nil 687 } 688 689 // VotesRewardRedeemInfo votesRewardRedeemInfo 690 func (api *API) VotesRewardRedeemInfo(val common.Address, voter common.Address, number *rpc.BlockNumber) (*systemcontract.VotesRewardRedeemInfo, error) { 691 nodeVotes := systemcontract.NewNodeVotes() 692 header, statedb, err := api.GetHeaderAndState(number) 693 if err != nil { 694 return &systemcontract.VotesRewardRedeemInfo{}, err 695 } 696 697 info, err := nodeVotes.VotesRewardRedeemInfo(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, val, voter) 698 if err != nil { 699 return &systemcontract.VotesRewardRedeemInfo{}, err 700 } 701 return info, nil 702 } 703 704 // VotesRewardRedeemInfos nodevotes.VotesRewardRedeemInfos 705 func (api *API) VotesRewardRedeemInfos(voter common.Address, number *rpc.BlockNumber) ([]systemcontract.VotesRewardRedeemInfo, error) { 706 nodeVotes := systemcontract.NewNodeVotes() 707 header, statedb, err := api.GetHeaderAndState(number) 708 if err != nil { 709 return []systemcontract.VotesRewardRedeemInfo{}, err 710 } 711 712 size := big.NewInt(50) 713 var allInfos []systemcontract.VotesRewardRedeemInfo 714 715 count, err := nodeVotes.VoteListLength(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, voter) 716 if err != nil { 717 return []systemcontract.VotesRewardRedeemInfo{}, err 718 } 719 720 if count.Cmp(size) <= 0 { 721 page := big.NewInt(1) 722 allInfos, err = nodeVotes.VotesRewardRedeemInfoWithPage(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, voter, page, size) 723 if err != nil { 724 return []systemcontract.VotesRewardRedeemInfo{}, err 725 } 726 } else { 727 var res big.Int 728 div := res.Div(count, size) 729 div = res.Add(div, big.NewInt(1)) 730 for i := int64(1); i <= div.Int64(); i++ { 731 infos, err := nodeVotes.VotesRewardRedeemInfoWithPage(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, voter, big.NewInt(i), size) 732 if err != nil { 733 return []systemcontract.VotesRewardRedeemInfo{}, err 734 } 735 allInfos = append(allInfos, infos...) 736 } 737 return allInfos, nil 738 } 739 740 return allInfos, nil 741 } 742 743 // systemRewards 744 745 type SysRewardsInfo struct { 746 Epochs []*big.Int 747 ValidatorRewards []*big.Int 748 DelegatorsRewards []*big.Int 749 Rates []uint 750 PendingReward *big.Int 751 FrozenReward *big.Int 752 RewardPerVote *big.Int 753 } 754 755 // EpochInfo return the epoch info 756 func (api *API) EpochInfo(epoch *big.Int, number *rpc.BlockNumber) (*systemcontract.EpochInfo, error) { 757 systemRewards := systemcontract.NewSystemRewards() 758 header, statedb, err := api.GetHeaderAndState(number) 759 if err != nil { 760 return &systemcontract.EpochInfo{}, err 761 } 762 epochInfo, err := systemRewards.GetEpochInfo(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, epoch) 763 if err != nil { 764 return &systemcontract.EpochInfo{}, err 765 } 766 return epochInfo, nil 767 } 768 769 // KickoutInfo return kickout addresses in epoch 770 func (api *API) KickoutInfo(epoch *big.Int, number *rpc.BlockNumber) ([]common.Address, error) { 771 systemRewards := systemcontract.NewSystemRewards() 772 header, statedb, err := api.GetHeaderAndState(number) 773 if err != nil { 774 return []common.Address{}, err 775 } 776 vals, err := systemRewards.KickoutInfo(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, epoch) 777 if err != nil { 778 return []common.Address{}, err 779 } 780 return vals, nil 781 } 782 783 // ValidatorRewardsInfo return the sys reward info 784 func (api *API) ValidatorRewardsInfo(addr common.Address, number *rpc.BlockNumber) (*SysRewardsInfo, error) { 785 systemRewards := systemcontract.NewSystemRewards() 786 header, statedb, err := api.GetHeaderAndState(number) 787 if err != nil { 788 return &SysRewardsInfo{}, err 789 } 790 rewardInfo, err := systemRewards.ValidatorRewardsInfo(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr) 791 if err != nil { 792 return &SysRewardsInfo{}, err 793 } 794 newInfo := SysRewardsInfo{ 795 Epochs: rewardInfo.Epochs, 796 ValidatorRewards: rewardInfo.ValidatorRewards, 797 DelegatorsRewards: rewardInfo.DelegatorsRewards, 798 PendingReward: rewardInfo.PendingReward, 799 FrozenReward: rewardInfo.FrozenReward, 800 RewardPerVote: rewardInfo.RewardPerVote, 801 } 802 803 for i := 0; i < len(rewardInfo.Rates); i++ { 804 newInfo.Rates = append(newInfo.Rates, uint(rewardInfo.Rates[i])) 805 } 806 807 return &newInfo, nil 808 } 809 810 // ValidatorRewardInfoByEpoch return the address and the epoch reward info 811 func (api *API) ValidatorRewardInfoByEpoch(addr common.Address, epoch *big.Int, number *rpc.BlockNumber) (*systemcontract.Reward, error) { 812 systemRewards := systemcontract.NewSystemRewards() 813 header, statedb, err := api.GetHeaderAndState(number) 814 if err != nil { 815 return &systemcontract.Reward{}, err 816 } 817 rewards, err := systemRewards.GetValRewardInfoByEpoch(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, epoch) 818 if err != nil { 819 return &systemcontract.Reward{}, err 820 } 821 return rewards, nil 822 } 823 824 // PendingValidatorReward return the address reward 825 func (api *API) PendingValidatorReward(addr common.Address, number *rpc.BlockNumber) (map[string]*big.Int, error) { 826 systemRewards := systemcontract.NewSystemRewards() 827 header, statedb, err := api.GetHeaderAndState(number) 828 if err != nil { 829 return map[string]*big.Int{}, err 830 } 831 avaliable, frozen, err := systemRewards.PendingValidatorReward(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr) 832 if err != nil { 833 return map[string]*big.Int{}, err 834 } 835 result := make(map[string]*big.Int) 836 result["avaliable"] = avaliable 837 result["frozen"] = frozen 838 return result, nil 839 } 840 841 // PunishInfo punishInfo function of systemRewards contract 842 func (api *API) PunishInfo(addr common.Address, epoch *big.Int, number *rpc.BlockNumber) (*systemcontract.Punish, error) { 843 systemRewards := systemcontract.NewSystemRewards() 844 header, statedb, err := api.GetHeaderAndState(number) 845 if err != nil { 846 return &systemcontract.Punish{}, err 847 } 848 punish, err := systemRewards.PunishInfo(statedb, header, newChainContext(api.chain, api.dpos), api.dpos.chainConfig, addr, epoch) 849 if err != nil { 850 return &systemcontract.Punish{}, err 851 } 852 853 return punish, nil 854 } 855 856 type status struct { 857 InturnPercent float64 `json:"inturnPercent"` 858 SigningStatus map[common.Address]int `json:"sealerActivity"` 859 NumBlocks uint64 `json:"numBlocks"` 860 } 861 862 // Status returns the status of the last N blocks, 863 // - the number of active validators, 864 // - the number of validators, 865 // - the percentage of in-turn blocks 866 func (api *API) Status() (*status, error) { 867 var ( 868 numBlocks = uint64(64) 869 header = api.chain.CurrentHeader() 870 diff = uint64(0) 871 optimals = 0 872 ) 873 snap, err := api.dpos.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) 874 if err != nil { 875 return nil, err 876 } 877 var ( 878 validators = snap.validators() 879 end = header.Number.Uint64() 880 start = end - numBlocks 881 ) 882 if numBlocks > end { 883 start = 1 884 numBlocks = end - start 885 } 886 signStatus := make(map[common.Address]int) 887 for _, s := range validators { 888 signStatus[s] = 0 889 } 890 for n := start; n < end; n++ { 891 h := api.chain.GetHeaderByNumber(n) 892 if h == nil { 893 return nil, fmt.Errorf("missing block %d", n) 894 } 895 if h.Difficulty.Cmp(diffInTurn) == 0 { 896 optimals++ 897 } 898 diff += h.Difficulty.Uint64() 899 sealer, err := api.dpos.Author(h) 900 if err != nil { 901 return nil, err 902 } 903 signStatus[sealer]++ 904 } 905 return &status{ 906 InturnPercent: float64(100*optimals) / float64(numBlocks), 907 SigningStatus: signStatus, 908 NumBlocks: numBlocks, 909 }, nil 910 }