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 d9eb97ced2..25f0a8be6f 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -1021,7 +1021,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