From 79ce01215807149059229b37f5dcc4458d51c9e8 Mon Sep 17 00:00:00 2001 From: Bui Quang Minh Date: Thu, 20 Jul 2023 18:19:22 +0700 Subject: [PATCH] consortium/v2: add RPC API for querying finality vote easily This commit adds 2 APIs in consortiumv2 namespace: consortiumv2_getValidatorAtHash, consortiumv2_getFinalityVoteAtHash. consortiumv2_getValidatorAtHash returns the authorized validators that can seal block hash with BLS public key. consortiumv2_getFinalityVoteAtHash returns the finality vote information in the block header at block hash. --- consensus/consortium/v2/api.go | 80 +++++++++++++++++++++++++++ consensus/consortium/v2/consortium.go | 9 ++- 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 consensus/consortium/v2/api.go diff --git a/consensus/consortium/v2/api.go b/consensus/consortium/v2/api.go new file mode 100644 index 0000000000..45c22f65ac --- /dev/null +++ b/consensus/consortium/v2/api.go @@ -0,0 +1,80 @@ +package v2 + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + consortiumCommon "github.com/ethereum/go-ethereum/consensus/consortium/common" + "github.com/ethereum/go-ethereum/consensus/consortium/v2/finality" +) + +type consortiumV2Api struct { + chain consensus.ChainHeaderReader + consortium *Consortium +} + +// GetValidatorAtHash returns the authorized validators that can seal block hash with +// their BLS public key if available +func (api *consortiumV2Api) GetValidatorAtHash(hash common.Hash) ([]finality.ValidatorWithBlsPub, error) { + header := api.chain.GetHeaderByHash(hash) + if header == nil { + return nil, consortiumCommon.ErrUnknownBlock + } + + snap, err := api.consortium.snapshot(api.chain, header.Number.Uint64()-1, header.ParentHash, nil) + if err != nil { + return nil, err + } + + if snap.ValidatorsWithBlsPub != nil { + return snap.ValidatorsWithBlsPub, nil + } + + var validators []finality.ValidatorWithBlsPub + for validator := range snap.Validators { + validators = append(validators, finality.ValidatorWithBlsPub{ + Address: validator, + }) + } + + return validators, nil +} + +type finalityVote struct { + Signature string + VoterPublicKey []string + VoterAddress []string +} + +// GetFinalityVoteAtHash returns the finality vote at block hash +func (api *consortiumV2Api) GetFinalityVoteAtHash(hash common.Hash) (*finalityVote, error) { + header := api.chain.GetHeaderByHash(hash) + if header == nil { + return nil, consortiumCommon.ErrUnknownBlock + } + + isShillin := api.consortium.chainConfig.IsShillin(header.Number) + extraData, err := finality.DecodeExtra(header.Extra, isShillin) + if err != nil { + return nil, err + } + + if extraData.HasFinalityVote == 0 { + return nil, nil + } + + var vote finalityVote + vote.Signature = common.Bytes2Hex(extraData.AggregatedFinalityVotes.Marshal()) + + snap, err := api.consortium.snapshot(api.chain, header.Number.Uint64()-1, header.ParentHash, nil) + if err != nil { + return nil, err + } + position := extraData.FinalityVotedValidators.Indices() + for _, pos := range position { + validator := snap.ValidatorsWithBlsPub[pos] + vote.VoterAddress = append(vote.VoterAddress, validator.Address.Hex()) + vote.VoterPublicKey = append(vote.VoterPublicKey, common.Bytes2Hex(validator.BlsPublicKey.Marshal())) + } + + return &vote, nil +} diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index bfb34f37d2..284cd384bf 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -1024,7 +1024,14 @@ func (c *Consortium) Close() error { // APIs are backward compatible with the v1, so we do not to implement it again func (c *Consortium) APIs(chain consensus.ChainHeaderReader) []rpc.API { - return []rpc.API{} + return []rpc.API{ + { + Namespace: "consortiumv2", + Version: "1.0", + Service: &consortiumV2Api{chain: chain, consortium: c}, + Public: false, + }, + } } // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty