Skip to content

Commit

Permalink
Add platform.getProposedHeight API (#3530)
Browse files Browse the repository at this point in the history
Signed-off-by: Ian Suvak <[email protected]>
Co-authored-by: cam-schultz <[email protected]>
  • Loading branch information
iansuvak and cam-schultz authored Nov 15, 2024
1 parent c0b85a8 commit fbcaf3e
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 0 deletions.
1 change: 1 addition & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### APIs

- Added `platform.getSubnetOnlyValidator`
- Added `platform.getProposedHeight`

### Configs

Expand Down
8 changes: 8 additions & 0 deletions vms/platformvm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ var _ Client = (*client)(nil)
type Client interface {
// GetHeight returns the current block height of the P Chain
GetHeight(ctx context.Context, options ...rpc.Option) (uint64, error)
// GetProposedHeight returns the current height of this node's proposer VM.
GetProposedHeight(ctx context.Context, options ...rpc.Option) (uint64, error)
// ExportKey returns the private key corresponding to [address] from [user]'s account
//
// Deprecated: Keys should no longer be stored on the node.
Expand Down Expand Up @@ -152,6 +154,12 @@ func (c *client) GetHeight(ctx context.Context, options ...rpc.Option) (uint64,
return uint64(res.Height), err
}

func (c *client) GetProposedHeight(ctx context.Context, options ...rpc.Option) (uint64, error) {
res := &api.GetHeightResponse{}
err := c.requester.SendRequest(ctx, "platform.getProposedHeight", struct{}{}, res, options...)
return uint64(res.Height), err
}

func (c *client) ExportKey(ctx context.Context, user api.UserPass, address ids.ShortID, options ...rpc.Option) (*secp256k1.PrivateKey, error) {
res := &ExportKeyReply{}
err := c.requester.SendRequest(ctx, "platform.exportKey", &ExportKeyArgs{
Expand Down
15 changes: 15 additions & 0 deletions vms/platformvm/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,21 @@ func (s *Service) GetHeight(r *http.Request, _ *struct{}, response *api.GetHeigh
return err
}

// GetProposedHeight returns the current ProposerVM height
func (s *Service) GetProposedHeight(r *http.Request, _ *struct{}, reply *api.GetHeightResponse) error {
s.vm.ctx.Log.Debug("API called",
zap.String("service", "platform"),
zap.String("method", "getProposedHeight"),
)
s.vm.ctx.Lock.Lock()
defer s.vm.ctx.Lock.Unlock()

ctx := r.Context()
proposerHeight, err := s.vm.GetMinimumHeight(ctx)
reply.Height = avajson.Uint64(proposerHeight)
return err
}

// ExportKeyArgs are arguments for ExportKey
type ExportKeyArgs struct {
api.UserPass
Expand Down
36 changes: 36 additions & 0 deletions vms/platformvm/service.md
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,42 @@ curl -X POST --data '{
}
```

### `platform.getProposedHeight`

Returns this node's current proposer VM height

**Signature:**

```sh
platform.getProposedHeight() ->
{
height: int,
}
```

**Example Call:**

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

**Example Response:**

```json
{
"jsonrpc": "2.0",
"result": {
"height": "56"
},
"id": 1
}
```

### `platform.getMaxStakeAmount`

:::caution
Expand Down
65 changes: 65 additions & 0 deletions vms/platformvm/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"fmt"
"math"
"math/rand"
"net/http"
"testing"
"time"

Expand Down Expand Up @@ -91,6 +92,70 @@ func defaultService(t *testing.T, fork upgradetest.Fork) (*Service, *mutableShar
}, mutableSharedMemory
}

func TestGetProposedHeight(t *testing.T) {
require := require.New(t)
service, _ := defaultService(t, upgradetest.Latest)

reply := api.GetHeightResponse{}
require.NoError(service.GetProposedHeight(&http.Request{}, nil, &reply))

minHeight, err := service.vm.GetMinimumHeight(context.Background())
require.NoError(err)
require.Equal(minHeight, uint64(reply.Height))

service.vm.ctx.Lock.Lock()

// issue any transaction to put into the new block
subnetID := testSubnet1.ID()
wallet := newWallet(t, service.vm, walletConfig{
subnetIDs: []ids.ID{subnetID},
})

tx, err := wallet.IssueCreateChainTx(
subnetID,
[]byte{},
constants.AVMID,
[]ids.ID{},
"chain name",
common.WithMemo([]byte{}),
)
require.NoError(err)

service.vm.ctx.Lock.Unlock()

// Get the last accepted block which should be genesis
genesisBlockID := service.vm.manager.LastAccepted()

require.NoError(service.vm.Network.IssueTxFromRPC(tx))
service.vm.ctx.Lock.Lock()

block, err := service.vm.BuildBlock(context.Background())
require.NoError(err)

blk := block.(*blockexecutor.Block)
require.NoError(blk.Verify(context.Background()))

require.NoError(blk.Accept(context.Background()))

service.vm.ctx.Lock.Unlock()

latestBlockID := service.vm.manager.LastAccepted()
latestBlock, err := service.vm.manager.GetBlock(latestBlockID)
require.NoError(err)
require.NotEqual(genesisBlockID, latestBlockID)

// Confirm that the proposed height hasn't changed with the new block being accepted.
require.NoError(service.GetProposedHeight(&http.Request{}, nil, &reply))
require.Equal(minHeight, uint64(reply.Height))

// Set the clock to beyond the proposer VM height of the most recent accepted block
service.vm.clock.Set(latestBlock.Timestamp().Add(31 * time.Second))

// Confirm that the proposed height has updated to the latest block height
require.NoError(service.GetProposedHeight(&http.Request{}, nil, &reply))
require.Equal(latestBlock.Height(), uint64(reply.Height))
}

func TestExportKey(t *testing.T) {
require := require.New(t)

Expand Down

0 comments on commit fbcaf3e

Please sign in to comment.