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 P-chain GetBlockByHeight API method #1747

Merged
merged 104 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
9e4302c
add block index by height to platformvm
dhrubabasu Apr 29, 2023
643932e
Update vms/platformvm/state/state.go
dhrubabasu Apr 29, 2023
c6ab13a
Add P-chain `GetBlockByHeight` API method
dhrubabasu Apr 30, 2023
6ea3bd5
Merge branch 'platformvm-block-height-index' into platformvm-getBlock…
dhrubabasu Apr 30, 2023
c9cc1a6
reduce diff
dhrubabasu May 1, 2023
34b9011
nit
dhrubabasu May 15, 2023
4bc89d1
push
dhrubabasu Jul 5, 2023
efd4dff
Merge branch 'dev' into avm-standardize-getblockidatheight
dhrubabasu Jul 5, 2023
495b7c1
wip
dhrubabasu Jul 7, 2023
a79b86b
nit
dhrubabasu Jul 7, 2023
e6e77a6
Merge branch 'dev' into avm-standardize-getblockidatheight
dhrubabasu Jul 7, 2023
55f7278
wip
dhrubabasu Jul 11, 2023
fd95c16
nits
dhrubabasu Jul 11, 2023
7478712
Merge branch 'dev' into avm-standardize-getblockidatheight
dhrubabasu Jul 11, 2023
041e891
fix interface
StephenButtolph Jul 12, 2023
7b1ef34
revert metervm change
StephenButtolph Jul 12, 2023
babc492
index on a going forward basis
dhrubabasu Jul 12, 2023
fd014b1
wip
dhrubabasu Jul 14, 2023
a09090f
wip
dhrubabasu Jul 15, 2023
fbef7ad
merged
dhrubabasu Jul 15, 2023
9f46a44
nit
dhrubabasu Jul 15, 2023
68824dc
nit
dhrubabasu Jul 15, 2023
711c6a6
fix
dhrubabasu Jul 15, 2023
dd526ec
wip
dhrubabasu Jul 17, 2023
ea32bd4
don't return rejected blocks
dhrubabasu Jul 17, 2023
40f5177
fix tests
dhrubabasu Jul 17, 2023
ecb9ff1
only return accepted blocks in `GetStatelessBlock`
dhrubabasu Jul 17, 2023
7e6d58e
cache
dhrubabasu Jul 17, 2023
1c031b4
Merge branch 'dev' into get-stateless-block-accepted-blocks-only
dhrubabasu Jul 17, 2023
e2f5f39
check status before parsing block
dhrubabasu Jul 17, 2023
888b233
first pass
dhrubabasu Jul 17, 2023
8e66845
nits
dhrubabasu Jul 17, 2023
df987bb
nit
dhrubabasu Jul 17, 2023
9084520
Merge branch 'simplify-new-sized-cache' into get-stateless-block-acce…
dhrubabasu Jul 17, 2023
7bb5c24
nit
StephenButtolph Jul 17, 2023
b44ecf2
cleanup
dhrubabasu Jul 17, 2023
0cad7e6
merged
dhrubabasu Jul 18, 2023
dbc447b
named func
dhrubabasu Jul 18, 2023
9e01fb7
nits
dhrubabasu Jul 18, 2023
a16a218
merged
dhrubabasu Jul 18, 2023
69ccdff
niiiit
StephenButtolph Jul 18, 2023
76b1177
merged
dhrubabasu Jul 18, 2023
5278db1
test
dhrubabasu Jul 18, 2023
dcbd029
merged
dhrubabasu Jul 18, 2023
8584ae1
reduce diff
dhrubabasu Jul 18, 2023
1d0e909
make diff cleaner
dhrubabasu Jul 18, 2023
84733c1
nit
dhrubabasu Jul 18, 2023
42e3b2a
try to make diff cleaner
dhrubabasu Jul 18, 2023
77d11c8
wip
dhrubabasu Jul 20, 2023
d7ce227
hold lock
dhrubabasu Jul 20, 2023
6582e40
wip
dhrubabasu Jul 20, 2023
cebedc4
Merge branch 'dev' into platformvm-height-index-state-cleanup
dhrubabasu Jul 20, 2023
969e258
wip
dhrubabasu Jul 20, 2023
234f96f
nit
dhrubabasu Jul 20, 2023
12679ce
re-enable cache
dhrubabasu Jul 20, 2023
1b505ea
wip
dhrubabasu Jul 20, 2023
6f2923b
test
dhrubabasu Jul 20, 2023
828d121
wip
dhrubabasu Jul 20, 2023
55c9ec1
prevent `vm.state` reassignment in tests
dhrubabasu Jul 20, 2023
98c3cdf
Merge branch 'dont-reassign-vm-state' into platformvm-height-index-st…
dhrubabasu Jul 20, 2023
a23f358
reduce dif
dhrubabasu Jul 20, 2023
ce7bd10
Merge branch 'dev' into platformvm-height-index-state-cleanup
dhrubabasu Jul 20, 2023
e3d4b2a
nit
dhrubabasu Jul 21, 2023
cf8d264
nit
dhrubabasu Jul 21, 2023
037e2a2
Merge branch 'dev' into platformvm-height-index-state-cleanup
dhrubabasu Jul 21, 2023
545c93d
Make platformvm implement `block.HeightIndexedChainVM`
dhrubabasu Jul 21, 2023
9013f79
nits
dhrubabasu Jul 21, 2023
df55cbd
merged
dhrubabasu Jul 21, 2023
b5a51ee
reduce diff
dhrubabasu Jul 21, 2023
52f59dc
fix
dhrubabasu Jul 21, 2023
8118e00
nit
dhrubabasu Jul 21, 2023
9376ae4
Merge branch 'platformvm-height-index-state-cleanup' into platformvm-…
dhrubabasu Jul 21, 2023
9853126
merged
dhrubabasu Jul 21, 2023
4e9baac
pr review
dhrubabasu Jul 21, 2023
ffcd444
Merge branch 'dev' into platformvm-height-index-state-cleanup
dhrubabasu Jul 21, 2023
a0c4aa5
Merge branch 'platformvm-height-index-state-cleanup' into platformvm-…
dhrubabasu Jul 21, 2023
0d7e903
Merge branch 'platformvm-proposervm-height-index' into platformvm-get…
dhrubabasu Jul 21, 2023
240e945
pr review
dhrubabasu Jul 21, 2023
55dcac3
Merge branch 'platformvm-height-index-state-cleanup' into platformvm-…
dhrubabasu Jul 21, 2023
cd3f828
Merge branch 'platformvm-proposervm-height-index' into platformvm-get…
dhrubabasu Jul 21, 2023
a2c8d78
nit
dhrubabasu Jul 21, 2023
e47a5b0
return errs
dhrubabasu Jul 21, 2023
adb5e1e
cleanup
dhrubabasu Jul 21, 2023
c36ae7f
Merge branch 'platformvm-height-index-state-cleanup' into platformvm-…
dhrubabasu Jul 21, 2023
018a872
Merge branch 'platformvm-proposervm-height-index' into platformvm-get…
dhrubabasu Jul 21, 2023
f642738
nit
dhrubabasu Jul 21, 2023
3086d76
Merge branch 'platformvm-height-index-state-cleanup' into platformvm-…
dhrubabasu Jul 21, 2023
a5e1556
Merge branch 'platformvm-proposervm-height-index' into platformvm-get…
dhrubabasu Jul 21, 2023
8c538d4
nit
dhrubabasu Jul 21, 2023
5aadbc1
Merge branch 'platformvm-height-index-state-cleanup' into platformvm-…
dhrubabasu Jul 21, 2023
5e2eec3
Merge branch 'platformvm-proposervm-height-index' into platformvm-get…
dhrubabasu Jul 21, 2023
b267b22
alternative approach
dhrubabasu Jul 21, 2023
c70053f
should be atomic
dhrubabasu Jul 21, 2023
8ee1dfc
Merge branch 'platformvm-proposervm-height-index' into platformvm-get…
dhrubabasu Jul 21, 2023
5480580
support storing both `stateBlk`s and `Block`s in `blockDB`
dhrubabasu Jul 22, 2023
927e016
nit
dhrubabasu Jul 22, 2023
55d45c0
nit
dhrubabasu Jul 22, 2023
677ac7f
merged
dhrubabasu Jul 22, 2023
6a26676
reduce diff
dhrubabasu Jul 22, 2023
bdc409a
Merge branch 'platformvm-height-index-state-cleanup' into platformvm-…
dhrubabasu Jul 22, 2023
1db361d
Merge branch 'platformvm-proposervm-height-index' into platformvm-get…
dhrubabasu Jul 22, 2023
56dbef4
merge
StephenButtolph Aug 8, 2023
511abff
nit
StephenButtolph Aug 8, 2023
ff10505
nit
StephenButtolph Aug 8, 2023
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
14 changes: 14 additions & 0 deletions vms/platformvm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ type Client interface {
) (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].
GetBlockByHeight(ctx context.Context, height uint64, options ...rpc.Option) ([]byte, error)
}

// Client implementation for interacting with the P Chain endpoint
Expand Down Expand Up @@ -877,3 +879,15 @@ func (c *client) GetBlock(ctx context.Context, blockID ids.ID, options ...rpc.Op
}
return formatting.Decode(res.Encoding, res.Block)
}

func (c *client) GetBlockByHeight(ctx context.Context, height uint64, options ...rpc.Option) ([]byte, error) {
res := &api.FormattedBlock{}
err := c.requester.SendRequest(ctx, "platform.getBlockByHeight", &api.GetBlockByHeightArgs{
Height: json.Uint64(height),
Encoding: formatting.HexNC,
}, res, options...)
if err != nil {
return nil, err
}
return formatting.Decode(res.Encoding, res.Block)
}
38 changes: 38 additions & 0 deletions vms/platformvm/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2651,6 +2651,44 @@ func (s *Service) GetBlock(_ *http.Request, args *api.GetBlockArgs, response *ap
return nil
}

// GetBlockByHeight returns the block at the given height.
func (s *Service) GetBlockByHeight(_ *http.Request, args *api.GetBlockByHeightArgs, response *api.GetBlockResponse) error {
s.vm.ctx.Log.Debug("API called",
zap.String("service", "platform"),
zap.String("method", "getBlockByHeight"),
zap.Uint64("height", uint64(args.Height)),
zap.Stringer("encoding", args.Encoding),
)

blockID, err := s.vm.state.GetBlockIDAtHeight(uint64(args.Height))
if err != nil {
return fmt.Errorf("couldn't get block at height %d: %w", args.Height, err)
}

block, err := s.vm.manager.GetStatelessBlock(blockID)
if err != nil {
s.vm.ctx.Log.Error("couldn't get accepted block",
zap.Stringer("blkID", blockID),
zap.Error(err),
)
return fmt.Errorf("couldn't get block with id %s: %w", blockID, err)
}
response.Encoding = args.Encoding

if args.Encoding == formatting.JSON {
block.InitCtx(s.vm.ctx)
response.Block = block
return nil
}

response.Block, err = formatting.Encode(args.Encoding, block.Bytes())
if err != nil {
return fmt.Errorf("couldn't encode block %s as %s: %w", blockID, args.Encoding, err)
}

return nil
}

func (s *Service) getAPIUptime(staker *state.Staker) (*json.Float32, error) {
// Only report uptimes that we have been actively tracking.
if constants.PrimaryNetworkID != staker.SubnetID && !s.vm.TrackedSubnets.Contains(staker.SubnetID) {
Expand Down
190 changes: 190 additions & 0 deletions vms/platformvm/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (

stdjson "encoding/json"

"github.com/golang/mock/gomock"

"github.com/stretchr/testify/require"

"github.com/ava-labs/avalanchego/api"
Expand All @@ -24,6 +26,7 @@ import (
"github.com/ava-labs/avalanchego/database/manager"
"github.com/ava-labs/avalanchego/database/prefixdb"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/snow"
"github.com/ava-labs/avalanchego/snow/consensus/snowman"
"github.com/ava-labs/avalanchego/snow/validators"
"github.com/ava-labs/avalanchego/utils/constants"
Expand Down Expand Up @@ -816,3 +819,190 @@ func TestGetValidatorsAtReplyMarshalling(t *testing.T) {
require.NoError(parsedReply.UnmarshalJSON(replyJSON))
require.Equal(reply, &parsedReply)
}

func TestServiceGetBlockByHeight(t *testing.T) {
ctrl := gomock.NewController(t)

blockID := ids.GenerateTestID()
blockHeight := uint64(1337)

type test struct {
name string
serviceAndExpectedBlockFunc func(t *testing.T, ctrl *gomock.Controller) (*Service, interface{})
encoding formatting.Encoding
expectedErr error
}

tests := []test{
{
name: "block height not found",
serviceAndExpectedBlockFunc: func(_ *testing.T, ctrl *gomock.Controller) (*Service, interface{}) {
state := state.NewMockState(ctrl)
state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(ids.Empty, database.ErrNotFound)

manager := blockexecutor.NewMockManager(ctrl)
return &Service{
vm: &VM{
state: state,
manager: manager,
ctx: &snow.Context{
Log: logging.NoLog{},
},
},
}, nil
},
encoding: formatting.Hex,
expectedErr: database.ErrNotFound,
},
{
name: "block not found",
serviceAndExpectedBlockFunc: func(_ *testing.T, ctrl *gomock.Controller) (*Service, interface{}) {
state := state.NewMockState(ctrl)
state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil)

manager := blockexecutor.NewMockManager(ctrl)
manager.EXPECT().GetStatelessBlock(blockID).Return(nil, database.ErrNotFound)
return &Service{
vm: &VM{
state: state,
manager: manager,
ctx: &snow.Context{
Log: logging.NoLog{},
},
},
}, nil
},
encoding: formatting.Hex,
expectedErr: database.ErrNotFound,
},
{
name: "JSON format",
serviceAndExpectedBlockFunc: func(_ *testing.T, ctrl *gomock.Controller) (*Service, interface{}) {
block := blocks.NewMockBlock(ctrl)
block.EXPECT().InitCtx(gomock.Any())

state := state.NewMockState(ctrl)
state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil)

manager := blockexecutor.NewMockManager(ctrl)
manager.EXPECT().GetStatelessBlock(blockID).Return(block, nil)
return &Service{
vm: &VM{
state: state,
manager: manager,
ctx: &snow.Context{
Log: logging.NoLog{},
},
},
}, block
},
encoding: formatting.JSON,
expectedErr: nil,
},
{
name: "hex format",
serviceAndExpectedBlockFunc: func(t *testing.T, ctrl *gomock.Controller) (*Service, interface{}) {
block := blocks.NewMockBlock(ctrl)
blockBytes := []byte("hi mom")
block.EXPECT().Bytes().Return(blockBytes)

state := state.NewMockState(ctrl)
state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil)

expected, err := formatting.Encode(formatting.Hex, blockBytes)
require.NoError(t, err)

manager := blockexecutor.NewMockManager(ctrl)
manager.EXPECT().GetStatelessBlock(blockID).Return(block, nil)
return &Service{
vm: &VM{
state: state,
manager: manager,
ctx: &snow.Context{
Log: logging.NoLog{},
},
},
}, expected
},
encoding: formatting.Hex,
expectedErr: nil,
},
{
name: "hexc format",
serviceAndExpectedBlockFunc: func(t *testing.T, ctrl *gomock.Controller) (*Service, interface{}) {
block := blocks.NewMockBlock(ctrl)
blockBytes := []byte("hi mom")
block.EXPECT().Bytes().Return(blockBytes)

state := state.NewMockState(ctrl)
state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil)

expected, err := formatting.Encode(formatting.HexC, blockBytes)
require.NoError(t, err)

manager := blockexecutor.NewMockManager(ctrl)
manager.EXPECT().GetStatelessBlock(blockID).Return(block, nil)
return &Service{
vm: &VM{
state: state,
manager: manager,
ctx: &snow.Context{
Log: logging.NoLog{},
},
},
}, expected
},
encoding: formatting.HexC,
expectedErr: nil,
},
{
name: "hexnc format",
serviceAndExpectedBlockFunc: func(t *testing.T, ctrl *gomock.Controller) (*Service, interface{}) {
block := blocks.NewMockBlock(ctrl)
blockBytes := []byte("hi mom")
block.EXPECT().Bytes().Return(blockBytes)

state := state.NewMockState(ctrl)
state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil)

expected, err := formatting.Encode(formatting.HexNC, blockBytes)
require.NoError(t, err)

manager := blockexecutor.NewMockManager(ctrl)
manager.EXPECT().GetStatelessBlock(blockID).Return(block, nil)
return &Service{
vm: &VM{
state: state,
manager: manager,
ctx: &snow.Context{
Log: logging.NoLog{},
},
},
}, expected
},
encoding: formatting.HexNC,
expectedErr: nil,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require := require.New(t)

service, expected := tt.serviceAndExpectedBlockFunc(t, ctrl)

args := &api.GetBlockByHeightArgs{
Height: json.Uint64(blockHeight),
Encoding: tt.encoding,
}
reply := &api.GetBlockResponse{}
err := service.GetBlockByHeight(nil, args, reply)
require.ErrorIs(err, tt.expectedErr)
if tt.expectedErr == nil {
return
}
require.Equal(tt.encoding, reply.Encoding)
require.Equal(expected, reply.Block)
})
}
}