Skip to content

Commit

Permalink
Merge pull request #4904 from oasisprotocol/kostko/feature/rhp-consen…
Browse files Browse the repository at this point in the history
…sus-events

runtime: Support consensus event queries
  • Loading branch information
kostko committed Sep 9, 2022
2 parents 5940ea4 + 9cde8d9 commit da6efaf
Show file tree
Hide file tree
Showing 29 changed files with 1,074 additions and 133 deletions.
2 changes: 1 addition & 1 deletion .changelog/4694.feature.md
@@ -1 +1 @@
runtime: verify consensus state integrity for queries
runtime: Enable dispatcher to verify state integrity for queries
1 change: 0 additions & 1 deletion .changelog/4830.bugfix.md

This file was deleted.

1 change: 1 addition & 0 deletions .changelog/4830.feature.md
@@ -0,0 +1 @@
runtime: Enable dispatcher to verify state integrity for queries
1 change: 1 addition & 0 deletions .changelog/4904.feature.2.md
@@ -0,0 +1 @@
runtime: Enable dispatcher to verify state integrity for queries
1 change: 1 addition & 0 deletions .changelog/4904.feature.md
@@ -0,0 +1 @@
runtime: Support consensus event queries
2 changes: 1 addition & 1 deletion go/common/version/version.go
Expand Up @@ -131,7 +131,7 @@ var (
// the runtime.
//
// NOTE: This version must be synced with runtime/src/common/version.rs.
RuntimeHostProtocol = Version{Major: 5, Minor: 0, Patch: 0}
RuntimeHostProtocol = Version{Major: 5, Minor: 1, Patch: 0}

// RuntimeCommitteeProtocol versions the P2P protocol used by the runtime
// committee members.
Expand Down
38 changes: 38 additions & 0 deletions go/consensus/api/grpc.go
Expand Up @@ -54,6 +54,8 @@ var (

// methodGetLightBlock is the GetLightBlock method.
methodGetLightBlock = lightServiceName.NewMethod("GetLightBlock", int64(0))
// methodGetLightBlockForState is the GetLightBlockForState method.
methodGetLightBlockForState = lightServiceName.NewMethod("GetLightBlockForState", int64(0))
// methodGetParameters is the GetParameters method.
methodGetParameters = lightServiceName.NewMethod("GetParameters", int64(0))
// methodStateSyncGet is the StateSyncGet method.
Expand Down Expand Up @@ -139,6 +141,10 @@ var (
MethodName: methodGetLightBlock.ShortName(),
Handler: handlerGetLightBlock,
},
{
MethodName: methodGetLightBlockForState.ShortName(),
Handler: handlerGetLightBlockForState,
},
{
MethodName: methodGetParameters.ShortName(),
Handler: handlerGetParameters,
Expand Down Expand Up @@ -474,6 +480,29 @@ func handlerGetLightBlock(
return interceptor(ctx, height, info, handler)
}

func handlerGetLightBlockForState(
srv interface{},
ctx context.Context,
dec func(interface{}) error,
interceptor grpc.UnaryServerInterceptor,
) (interface{}, error) {
var height int64
if err := dec(&height); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(LightClientBackend).GetLightBlockForState(ctx, height)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: methodGetLightBlockForState.FullName(),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(LightClientBackend).GetLightBlockForState(ctx, req.(int64))
}
return interceptor(ctx, height, info, handler)
}

func handlerGetParameters(
srv interface{},
ctx context.Context,
Expand Down Expand Up @@ -636,6 +665,15 @@ func (c *consensusLightClient) GetLightBlock(ctx context.Context, height int64)
return &rsp, nil
}

// Implements LightClientBackend.
func (c *consensusLightClient) GetLightBlockForState(ctx context.Context, height int64) (*LightBlock, error) {
var rsp LightBlock
if err := c.conn.Invoke(ctx, methodGetLightBlockForState.FullName(), height, &rsp); err != nil {
return nil, err
}
return &rsp, nil
}

// Implements LightClientBackend.
func (c *consensusLightClient) GetParameters(ctx context.Context, height int64) (*Parameters, error) {
var rsp Parameters
Expand Down
7 changes: 7 additions & 0 deletions go/consensus/api/light.go
Expand Up @@ -14,6 +14,13 @@ type LightClientBackend interface {
// client verification.
GetLightBlock(ctx context.Context, height int64) (*LightBlock, error)

// GetLightBlockForState returns a light block for the state as of executing the consensus layer
// block at the specified height. Note that the height of the returned block may differ
// depending on consensus layer implementation details.
//
// In case light block for the given height is not yet available, it returns ErrVersionNotFound.
GetLightBlockForState(ctx context.Context, height int64) (*LightBlock, error)

// GetParameters returns the consensus parameters for a specific height.
GetParameters(ctx context.Context, height int64) (*Parameters, error)

Expand Down
34 changes: 31 additions & 3 deletions go/consensus/tendermint/full/light.go
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"

tmcore "github.com/tendermint/tendermint/rpc/core"
tmstate "github.com/tendermint/tendermint/state"
tmtypes "github.com/tendermint/tendermint/types"

"github.com/oasisprotocol/oasis-core/go/common/cbor"
Expand All @@ -14,8 +15,7 @@ import (
"github.com/oasisprotocol/oasis-core/go/storage/mkvs/syncer"
)

// Implements LightClientBackend.
func (n *commonNode) GetLightBlock(ctx context.Context, height int64) (*consensusAPI.LightBlock, error) {
func (n *commonNode) getLightBlock(ctx context.Context, height int64, allowPending bool) (*consensusAPI.LightBlock, error) {
if err := n.ensureStarted(ctx); err != nil {
return nil, err
}
Expand All @@ -33,9 +33,27 @@ func (n *commonNode) GetLightBlock(ctx context.Context, height int64) (*consensu
return nil, consensusAPI.ErrVersionNotFound
}

if commit, cerr := tmcore.Commit(n.rpcCtx, &tmHeight); cerr == nil && commit.Header != nil {
commit, err := tmcore.Commit(n.rpcCtx, &tmHeight)
if err == nil && commit.Header != nil {
lb.SignedHeader = &commit.SignedHeader
tmHeight = commit.Header.Height
} else if allowPending {
// The specified height seems to be for the "next" block that has not yet been finalized. We
// construct a "pending" block instead (this block cannot be verified by a light client as
// it doesn't have any commits).
var state tmstate.State
state, err = n.stateStore.Load()
if err != nil {
return nil, fmt.Errorf("tendermint: failed to fetch latest blockchain state: %w", err)
}

commit := tmtypes.NewCommit(height, 0, tmtypes.BlockID{}, nil)
var proposerAddr [20]byte
blk, _ := state.MakeBlock(height, nil, commit, nil, proposerAddr[:])
lb.SignedHeader = &tmtypes.SignedHeader{
Header: &blk.Header,
Commit: commit,
}
}
protoLb, err := lb.ToProto()
if err != nil {
Expand All @@ -59,6 +77,16 @@ func (n *commonNode) GetLightBlock(ctx context.Context, height int64) (*consensu
}, nil
}

// Implements LightClientBackend.
func (n *commonNode) GetLightBlock(ctx context.Context, height int64) (*consensusAPI.LightBlock, error) {
return n.getLightBlock(ctx, height, false)
}

// Implements LightClientBackend.
func (n *commonNode) GetLightBlockForState(ctx context.Context, height int64) (*consensusAPI.LightBlock, error) {
return n.getLightBlock(ctx, height+1, true)
}

// Implements LightClientBackend.
func (n *commonNode) GetParameters(ctx context.Context, height int64) (*consensusAPI.Parameters, error) {
if err := n.ensureStarted(ctx); err != nil {
Expand Down
5 changes: 5 additions & 0 deletions go/consensus/tendermint/light/client.go
Expand Up @@ -134,6 +134,11 @@ func (lc *lightClient) GetLightBlock(ctx context.Context, height int64) (*consen
return lc.getPrimary().GetLightBlock(ctx, height)
}

// Implements consensus.LightClientBackend.
func (lc *lightClient) GetLightBlockForState(ctx context.Context, height int64) (*consensus.LightBlock, error) {
return lc.getPrimary().GetLightBlockForState(ctx, height)
}

// Implements consensus.LightClientBackend.
func (lc *lightClient) GetParameters(ctx context.Context, height int64) (*consensus.Parameters, error) {
return lc.getPrimary().GetParameters(ctx, height)
Expand Down
5 changes: 5 additions & 0 deletions go/consensus/tendermint/seed/seed.go
Expand Up @@ -246,6 +246,11 @@ func (srv *seedService) GetLightBlock(ctx context.Context, height int64) (*conse
return nil, consensus.ErrUnsupported
}

// Implements consensus.Backend.
func (srv *seedService) GetLightBlockForState(ctx context.Context, height int64) (*consensus.LightBlock, error) {
return nil, consensus.ErrUnsupported
}

// Implements consensus.Backend.
func (srv *seedService) GetParameters(ctx context.Context, height int64) (*consensus.Parameters, error) {
return nil, consensus.ErrUnsupported
Expand Down
55 changes: 41 additions & 14 deletions go/runtime/host/protocol/types.go
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/oasisprotocol/oasis-core/go/common/sgx/quote"
"github.com/oasisprotocol/oasis-core/go/common/version"
consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"
consensusResults "github.com/oasisprotocol/oasis-core/go/consensus/api/transaction/results"
roothash "github.com/oasisprotocol/oasis-core/go/roothash/api"
"github.com/oasisprotocol/oasis-core/go/roothash/api/block"
"github.com/oasisprotocol/oasis-core/go/roothash/api/commitment"
Expand Down Expand Up @@ -95,20 +96,22 @@ type Body struct {
RuntimeConsensusSyncResponse *Empty `json:",omitempty"`

// Host interface.
HostRPCCallRequest *HostRPCCallRequest `json:",omitempty"`
HostRPCCallResponse *HostRPCCallResponse `json:",omitempty"`
HostStorageSyncRequest *HostStorageSyncRequest `json:",omitempty"`
HostStorageSyncResponse *HostStorageSyncResponse `json:",omitempty"`
HostLocalStorageGetRequest *HostLocalStorageGetRequest `json:",omitempty"`
HostLocalStorageGetResponse *HostLocalStorageGetResponse `json:",omitempty"`
HostLocalStorageSetRequest *HostLocalStorageSetRequest `json:",omitempty"`
HostLocalStorageSetResponse *Empty `json:",omitempty"`
HostFetchConsensusBlockRequest *HostFetchConsensusBlockRequest `json:",omitempty"`
HostFetchConsensusBlockResponse *HostFetchConsensusBlockResponse `json:",omitempty"`
HostFetchTxBatchRequest *HostFetchTxBatchRequest `json:",omitempty"`
HostFetchTxBatchResponse *HostFetchTxBatchResponse `json:",omitempty"`
HostFetchGenesisHeightRequest *HostFetchGenesisHeightRequest `json:",omitempty"`
HostFetchGenesisHeightResponse *HostFetchGenesisHeightResponse `json:",omitempty"`
HostRPCCallRequest *HostRPCCallRequest `json:",omitempty"`
HostRPCCallResponse *HostRPCCallResponse `json:",omitempty"`
HostStorageSyncRequest *HostStorageSyncRequest `json:",omitempty"`
HostStorageSyncResponse *HostStorageSyncResponse `json:",omitempty"`
HostLocalStorageGetRequest *HostLocalStorageGetRequest `json:",omitempty"`
HostLocalStorageGetResponse *HostLocalStorageGetResponse `json:",omitempty"`
HostLocalStorageSetRequest *HostLocalStorageSetRequest `json:",omitempty"`
HostLocalStorageSetResponse *Empty `json:",omitempty"`
HostFetchConsensusBlockRequest *HostFetchConsensusBlockRequest `json:",omitempty"`
HostFetchConsensusBlockResponse *HostFetchConsensusBlockResponse `json:",omitempty"`
HostFetchConsensusEventsRequest *HostFetchConsensusEventsRequest `json:",omitempty"`
HostFetchConsensusEventsResponse *HostFetchConsensusEventsResponse `json:",omitempty"`
HostFetchTxBatchRequest *HostFetchTxBatchRequest `json:",omitempty"`
HostFetchTxBatchResponse *HostFetchTxBatchResponse `json:",omitempty"`
HostFetchGenesisHeightRequest *HostFetchGenesisHeightRequest `json:",omitempty"`
HostFetchGenesisHeightResponse *HostFetchGenesisHeightResponse `json:",omitempty"`
}

// Type returns the message type by determining the name of the first non-nil member.
Expand Down Expand Up @@ -480,6 +483,30 @@ type HostFetchConsensusBlockResponse struct {
Block consensus.LightBlock `json:"block"`
}

// EventKind is the consensus event kind.
type EventKind uint8

// Supported consensus event kinds.
const (
EventKindStaking EventKind = 1
EventKindRegistry EventKind = 2
EventKindRootHash EventKind = 3
EventKindGovernance EventKind = 4
)

// HostFetchConsensusEventsRequest is a request to host to fetch the consensus events for the given
// height.
type HostFetchConsensusEventsRequest struct {
Height uint64 `json:"height"`
Kind EventKind `json:"kind"`
}

// HostFetchConsensusEventsResponse is a response from host fetching the consensus events for the
// given height.
type HostFetchConsensusEventsResponse struct {
Events []*consensusResults.Event `json:"events,omitempty"`
}

// HostFetchGenesisHeightRequest is a request to host to fetch the consensus genesis height.
type HostFetchGenesisHeightRequest struct{}

Expand Down

0 comments on commit da6efaf

Please sign in to comment.