Skip to content

Commit

Permalink
[RPC] Add RPCs to get list of BLS public keys for committees (#3080)
Browse files Browse the repository at this point in the history
* [rpc] Fix sanity check to accept "latest"

* [rpc] Return as much data possible when using GetAllValidatorInformationByBlockNumber

* [rpc] Remove beacon check for getValidators, returns valid information on all shards

* [rpc] Add GetValidatorKeys to get BLS Keys of committee for a particular epoch

* [rpc] Add getBlockSignerKeys to return public bls keys of signers for a block

* [rpc] Fix lint

* [rpc] Address PR comments

* [rpc] Add common function to API backend instead of separate implementations in V1 & V2

* [rpc] Remove extra parenthesis

* [rpc] Fix lint
[validator] Fix typo

* [rpc] Revert change to sanity check in V2

* [rpc] Fix lint
  • Loading branch information
rhazberries authored May 28, 2020
1 parent 607c71a commit c4db1c0
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 110 deletions.
32 changes: 32 additions & 0 deletions hmy/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/rpc"
"github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/api/proto"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/consensus/quorum"
Expand All @@ -20,6 +21,7 @@ import (
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/vm"
internal_bls "github.com/harmony-one/harmony/crypto/bls"
internal_common "github.com/harmony-one/harmony/internal/common"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
commonRPC "github.com/harmony-one/harmony/internal/hmyapi/common"
Expand Down Expand Up @@ -848,3 +850,33 @@ func (b *APIBackend) GetNodeMetadata() commonRPC.NodeMetadata {
c,
}
}

// GetBlockSigners ..
func (b *APIBackend) GetBlockSigners(ctx context.Context, blockNr rpc.BlockNumber) (shard.SlotList, *internal_bls.Mask, error) {
block, err := b.BlockByNumber(ctx, blockNr)
if err != nil {
return nil, nil, err
}
blockWithSigners, err := b.BlockByNumber(ctx, blockNr+1)
if err != nil {
return nil, nil, err
}
committee, err := b.GetValidators(block.Epoch())
if err != nil {
return nil, nil, err
}
pubkeys := make([]*bls.PublicKey, len(committee.Slots))
for i, validator := range committee.Slots {
pubkeys[i] = new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(pubkeys[i])
}
mask, err := internal_bls.NewMask(pubkeys, nil)
if err != nil {
return nil, nil, err
}
err = mask.SetMask(blockWithSigners.Header().LastCommitBitmap())
if err != nil {
return nil, nil, err
}
return committee.Slots, mask, nil
}
2 changes: 2 additions & 0 deletions internal/hmyapi/apiv1/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/vm"
"github.com/harmony-one/harmony/crypto/bls"
commonRPC "github.com/harmony-one/harmony/internal/hmyapi/common"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/shard"
Expand Down Expand Up @@ -91,4 +92,5 @@ type Backend interface {
GetLastCrossLinks() ([]*types.CrossLink, error)
GetLatestChainHeaders() *block.HeaderPair
GetNodeMetadata() commonRPC.NodeMetadata
GetBlockSigners(ctx context.Context, blockNr rpc.BlockNumber) (shard.SlotList, *bls.Mask, error)
}
98 changes: 44 additions & 54 deletions internal/hmyapi/apiv1/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/vm"
internal_bls "github.com/harmony-one/harmony/crypto/bls"
internal_common "github.com/harmony-one/harmony/internal/common"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/internal/utils"
Expand Down Expand Up @@ -183,9 +182,6 @@ func (s *PublicBlockChainAPI) GetBlocks(ctx context.Context, blockStart rpc.Bloc

// GetValidators returns validators list for a particular epoch.
func (s *PublicBlockChainAPI) GetValidators(ctx context.Context, epoch int64) (map[string]interface{}, error) {
if err := s.isBeaconShard(); err != nil {
return nil, err
}
committee, err := s.b.GetValidators(big.NewInt(epoch))
if err != nil {
return nil, err
Expand Down Expand Up @@ -217,6 +213,20 @@ func (s *PublicBlockChainAPI) GetValidators(ctx context.Context, epoch int64) (m
return result, nil
}

// GetValidatorKeys returns list of bls public keys in the committee for a particular epoch.
func (s *PublicBlockChainAPI) GetValidatorKeys(ctx context.Context, epoch int64) ([]string, error) {
committee, err := s.b.GetValidators(big.NewInt(epoch))
if err != nil {
return nil, err
}

validators := make([]string, len(committee.Slots))
for i, v := range committee.Slots {
validators[i] = v.BLSPublicKey.Hex()
}
return validators, nil
}

// IsLastBlock checks if block is last epoch block.
func (s *PublicBlockChainAPI) IsLastBlock(blockNum uint64) (bool, error) {
if err := s.isBeaconShard(); err != nil {
Expand All @@ -241,44 +251,46 @@ func (s *PublicBlockChainAPI) GetBlockSigners(ctx context.Context, blockNr rpc.B
if err := s.isBlockGreaterThanLatest(blockNr); err != nil {
return nil, err
}
block, err := s.b.BlockByNumber(ctx, blockNr)
if err != nil {
return nil, err
}
blockWithSigners, err := s.b.BlockByNumber(ctx, blockNr+1)
slots, mask, err := s.b.GetBlockSigners(ctx, blockNr)
if err != nil {
return nil, err
}
committee, err := s.b.GetValidators(block.Epoch())
if err != nil {
return nil, err
signers := []string{}
for _, validator := range slots {
oneAddress, err := internal_common.AddressToBech32(validator.EcdsaAddress)
if err != nil {
return nil, err
}
blsPublicKey := new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(blsPublicKey)
if ok, err := mask.KeyEnabled(blsPublicKey); err == nil && ok {
signers = append(signers, oneAddress)
}
}
pubkeys := make([]*bls.PublicKey, len(committee.Slots))
for i, validator := range committee.Slots {
pubkeys[i] = new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(pubkeys[i])
return signers, nil
}

// GetBlockSignerKeys returns bls public keys that signed the block.
func (s *PublicBlockChainAPI) GetBlockSignerKeys(ctx context.Context, blockNr rpc.BlockNumber) ([]string, error) {
if uint64(blockNr) == 0 {
return []string{}, nil
}
mask, err := internal_bls.NewMask(pubkeys, nil)
if err != nil {
if err := s.isBlockGreaterThanLatest(blockNr); err != nil {
return nil, err
}
err = mask.SetMask(blockWithSigners.Header().LastCommitBitmap())
slots, mask, err := s.b.GetBlockSigners(ctx, blockNr)
if err != nil {
return nil, err
}
result := []string{}
for _, validator := range committee.Slots {
oneAddress, err := internal_common.AddressToBech32(validator.EcdsaAddress)
if err != nil {
return nil, err
}
signers := []string{}
for _, validator := range slots {
blsPublicKey := new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(blsPublicKey)
if ok, err := mask.KeyEnabled(blsPublicKey); err == nil && ok {
result = append(result, oneAddress)
signers = append(signers, validator.BLSPublicKey.Hex())
}
}
return result, nil
return signers, nil
}

// IsBlockSigner returns true if validator with address signed blockNr block.
Expand All @@ -289,32 +301,11 @@ func (s *PublicBlockChainAPI) IsBlockSigner(ctx context.Context, blockNr rpc.Blo
if err := s.isBlockGreaterThanLatest(blockNr); err != nil {
return false, err
}
block, err := s.b.BlockByNumber(ctx, blockNr)
if err != nil {
return false, err
}
blockWithSigners, err := s.b.BlockByNumber(ctx, blockNr+1)
slots, mask, err := s.b.GetBlockSigners(ctx, blockNr)
if err != nil {
return false, err
}
committee, err := s.b.GetValidators(block.Epoch())
if err != nil {
return false, err
}
pubkeys := make([]*bls.PublicKey, len(committee.Slots))
for i, validator := range committee.Slots {
pubkeys[i] = new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(pubkeys[i])
}
mask, err := internal_bls.NewMask(pubkeys, nil)
if err != nil {
return false, err
}
err = mask.SetMask(blockWithSigners.Header().LastCommitBitmap())
if err != nil {
return false, err
}
for _, validator := range committee.Slots {
for _, validator := range slots {
oneAddress, err := internal_common.AddressToBech32(validator.EcdsaAddress)
if err != nil {
return false, err
Expand Down Expand Up @@ -683,17 +674,16 @@ func (s *PublicBlockChainAPI) getAllValidatorInformation(
validatorsNum = len(addresses) - start
}
}
validators := make([]*staking.ValidatorRPCEnhanced, validatorsNum)
validators := []*staking.ValidatorRPCEnhanced{}
block, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr))
if err != nil {
return nil, errors.Wrapf(err, "could not retrieve the block information for block number: %d", blockNr)
}
for i := start; i < start+validatorsNum; i++ {
information, err := s.b.GetValidatorInformation(addresses[i], block)
if err != nil {
return nil, err
if err == nil {
validators = append(validators, information)
}
validators[i-start] = information
}
return validators, nil
}
Expand Down
2 changes: 2 additions & 0 deletions internal/hmyapi/apiv2/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/vm"
"github.com/harmony-one/harmony/crypto/bls"
commonRPC "github.com/harmony-one/harmony/internal/hmyapi/common"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/shard"
Expand Down Expand Up @@ -87,4 +88,5 @@ type Backend interface {
GetLastCrossLinks() ([]*types.CrossLink, error)
GetLatestChainHeaders() *block.HeaderPair
GetNodeMetadata() commonRPC.NodeMetadata
GetBlockSigners(ctx context.Context, blockNr rpc.BlockNumber) (shard.SlotList, *bls.Mask, error)
}
Loading

0 comments on commit c4db1c0

Please sign in to comment.