Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add getProposedValidators RPC method #3497

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions tests/e2e/p/proposed_validators.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package p

import (
"github.com/onsi/ginkgo/v2"
"github.com/stretchr/testify/require"

"github.com/ava-labs/avalanchego/config"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/tests/fixture/e2e"
"github.com/ava-labs/avalanchego/utils/constants"
"github.com/ava-labs/avalanchego/utils/set"
"github.com/ava-labs/avalanchego/vms/platformvm"
)

var _ = e2e.DescribePChain("[Proposed Validators]", func() {
var (
tc = e2e.NewTestContext()
require = require.New(tc)
)

ginkgo.It("should be able to fetch proposed validators", func() {
var (
env = e2e.GetEnv(tc)
network = env.GetNetwork()
)

tc.By("fetching proposed validators", func() {
pvmClient := platformvm.NewClient(env.URIs[0].URI)
proposedVdrs, err := pvmClient.GetProposedValidators(
tc.DefaultContext(),
constants.PrimaryNetworkID,
)
require.NoError(err)

tc.By("confirming proposed validators are the same as current validators", func() {
// Ensure the network is configured to use the current height for the proposer
proposerVMUseCurrentHeight, err := network.DefaultFlags.GetBoolVal(config.ProposerVMUseCurrentHeightKey, true)
require.NoError(err)
require.True(proposerVMUseCurrentHeight)

proposedVdrNodes := set.NewSet[ids.NodeID](len(proposedVdrs))
for _, vdr := range proposedVdrs {
proposedVdrNodes.Add(vdr.NodeID)
}
currentVdrs, err := pvmClient.GetCurrentValidators(
tc.DefaultContext(),
constants.PrimaryNetworkID,
nil,
)
require.NoError(err)
currentVdrNodes := set.NewSet[ids.NodeID](len(currentVdrs))
for _, vdr := range currentVdrs {
currentVdrNodes.Add(vdr.NodeID)
}
require.Equal(proposedVdrNodes, currentVdrNodes)
})
})
_ = e2e.CheckBootstrapIsPossible(tc, network)
})
})
19 changes: 19 additions & 0 deletions vms/platformvm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ type Client interface {
height uint64,
options ...rpc.Option,
) (map[ids.NodeID]*validators.GetValidatorOutput, error)
// GetProposedValidators returns the weights of the validator set of a provided
// subnet at the proposer's height.
GetProposedValidators(
ctx context.Context,
subnetID ids.ID,
options ...rpc.Option,
) (map[ids.NodeID]*validators.GetValidatorOutput, error)
// GetBlock returns the block with the given id.
GetBlock(ctx context.Context, blockID ids.ID, options ...rpc.Option) ([]byte, error)
// GetBlockByHeight returns the block at the given [height].
Expand Down Expand Up @@ -506,6 +513,18 @@ func (c *client) GetValidatorsAt(
return res.Validators, err
}

func (c *client) GetProposedValidators(
marun marked this conversation as resolved.
Show resolved Hide resolved
ctx context.Context,
subnetID ids.ID,
options ...rpc.Option,
) (map[ids.NodeID]*validators.GetValidatorOutput, error) {
res := &GetProposedValidatorsReply{}
err := c.requester.SendRequest(ctx, "platform.getProposedValidators", &GetProposedValidatorsArgs{
SubnetID: subnetID,
}, res, options...)
return res.Validators, err
}

func (c *client) GetBlock(ctx context.Context, blockID ids.ID, options ...rpc.Option) ([]byte, error) {
res := &api.FormattedBlock{}
if err := c.requester.SendRequest(ctx, "platform.getBlock", &api.GetBlockArgs{
Expand Down
27 changes: 27 additions & 0 deletions vms/platformvm/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -1780,6 +1780,33 @@ func (s *Service) GetValidatorsAt(r *http.Request, args *GetValidatorsAtArgs, re
return nil
}

type GetProposedValidatorsArgs struct {
SubnetID ids.ID `json:"subnetID"`
}
type GetProposedValidatorsReply struct {
GetValidatorsAtReply
}

func (s *Service) GetProposedValidators(r *http.Request, args *GetProposedValidatorsArgs, reply *GetProposedValidatorsReply) error {
s.vm.ctx.Log.Debug("API called",
zap.String("service", "platform"),
zap.String("method", "getProposedValidators"),
zap.Stringer("subnetID", args.SubnetID),
)
s.vm.ctx.Lock.Lock()
marun marked this conversation as resolved.
Show resolved Hide resolved
defer s.vm.ctx.Lock.Unlock()

ctx := r.Context()
proposerHeight, err := s.vm.GetMinimumHeight(ctx)
if err != nil {
return fmt.Errorf("failed to get proposer height: %w", err)
}
if reply.Validators, err = s.vm.GetValidatorSet(ctx, proposerHeight, args.SubnetID); err != nil {
return fmt.Errorf("failed to get validator set: %w", err)
}
return nil
}

func (s *Service) GetBlock(_ *http.Request, args *api.GetBlockArgs, response *api.GetBlockResponse) error {
s.vm.ctx.Log.Debug("API called",
zap.String("service", "platform"),
Expand Down
48 changes: 47 additions & 1 deletion vms/platformvm/service.md
Original file line number Diff line number Diff line change
Expand Up @@ -1778,7 +1778,7 @@ platform.getValidatorsAt(
```

- `height` is the P-Chain height to get the validator set at.
- `subnetID` is the Subnet ID to get the validator set of. If not given, gets validator set of the
- `subnetID` is the Subnet ID to get the validator set of. If not given, gets the validator set of the
Primary Network.

**Example Call:**
Expand Down Expand Up @@ -1812,6 +1812,52 @@ curl -X POST --data '{
}
```

### `platform.getProposedValidators`

Get the validators and their weights of a Subnet or the Primary Network at the current proposer VM height.

**Signature:**

```sh
platform.getProposedValidators(
{
subnetID: string, // optional
}
)
```

- `subnetID` is the Subnet ID to get the validator set of. If not given, gets the validator set of the
Primary Network.

**Example Call:**

```bash
curl -X POST --data '{
"jsonrpc": "2.0",
"method": "platform.getValidatorsAt",
"params": {},
"id": 1
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/P
```

**Example Response:**

```json
{
"jsonrpc": "2.0",
"result": {
"validators": {
"NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg": 2000000000000000,
"NodeID-GWPcbFJZFfZreETSoWjPimr846mXEKCtu": 2000000000000000,
"NodeID-MFrZFVCXPv5iCn6M9K6XduxGTYp891xXZ": 2000000000000000,
"NodeID-NFBbbJ4qCmNaCzeW7sxErhvWqvEQMnYcN": 2000000000000000,
"NodeID-P7oB2McjBGgW2NXXWVYjV8JEDFoW9xDE5": 2000000000000000
}
},
"id": 1
}
```

### `platform.issueTx`

Issue a transaction to the Platform Chain.
Expand Down
Loading