Skip to content

Commit

Permalink
go/consensus: Also try to answer light block requests from store
Browse files Browse the repository at this point in the history
  • Loading branch information
kostko committed Nov 24, 2023
1 parent 9c7013d commit a0bd142
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 25 deletions.
4 changes: 4 additions & 0 deletions go/consensus/api/light.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ type LightService interface {

// LightClient is a consensus light client interface.
type LightClient interface {
// GetStoredLightBlock retrieves a light block from the local light block store without doing
// any remote queries.
GetStoredLightBlock(height int64) (*LightBlock, error)

// GetLightBlock queries peers for a specific light block.
GetLightBlock(ctx context.Context, height int64) (*LightBlock, rpc.PeerFeedback, error)

Expand Down
8 changes: 7 additions & 1 deletion go/consensus/cometbft/cometbft.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ func New(
}

// NewLightClient creates a new CometBFT light client service.
func NewLightClient(ctx context.Context, dataDir string, genesis *genesisAPI.Document, consensus consensusAPI.Backend, p2p rpc.P2P) (lightAPI.ClientService, error) {
func NewLightClient(
ctx context.Context,
dataDir string,
genesis *genesisAPI.Document,
consensus consensusAPI.Backend,
p2p rpc.P2P,
) (lightAPI.ClientService, error) {
return light.New(ctx, dataDir, genesis, consensus, p2p)
}
4 changes: 0 additions & 4 deletions go/consensus/cometbft/full/full.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import (
"github.com/oasisprotocol/oasis-core/go/consensus/cometbft/db"
lightAPI "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/light/api"
"github.com/oasisprotocol/oasis-core/go/consensus/metrics"
lightP2P "github.com/oasisprotocol/oasis-core/go/consensus/p2p/light"
genesisAPI "github.com/oasisprotocol/oasis-core/go/genesis/api"
cmflags "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/flags"
cmmetrics "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/metrics"
Expand Down Expand Up @@ -473,9 +472,6 @@ func (t *fullService) RegisterP2PService(p2p p2pAPI.Service) error {
}
t.p2p = p2p

// Register consensus protocol server.
t.p2p.RegisterProtocolServer(lightP2P.NewServer(t.p2p, t.genesis.ChainContext(), t))

return nil
}

Expand Down
18 changes: 18 additions & 0 deletions go/consensus/cometbft/light/api/light.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package api

import (
"context"
"fmt"

cmtlight "github.com/cometbft/cometbft/light"
cmtlightprovider "github.com/cometbft/cometbft/light/provider"
Expand Down Expand Up @@ -54,3 +55,20 @@ type ClientConfig struct {
// TrustOptions are CometBFT light client trust options.
TrustOptions cmtlight.TrustOptions
}

// NewLightBlock creates a new consensus.LightBlock from a CometBFT light block.
func NewLightBlock(clb *cmttypes.LightBlock) (*consensus.LightBlock, error) {
plb, err := clb.ToProto()
if err != nil {
return nil, fmt.Errorf("failed to marshal light block: %w", err)
}
meta, err := plb.Marshal()
if err != nil {
return nil, fmt.Errorf("failed to marshal light block: %w", err)
}

return &consensus.LightBlock{
Height: clb.Height,
Meta: meta,
}, nil
}
9 changes: 9 additions & 0 deletions go/consensus/cometbft/light/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ func tryProviders[R any](
return result, nil, err
}

// GetStoredBlock implements api.Client.
func (lc *lightClient) GetStoredLightBlock(height int64) (*consensus.LightBlock, error) {
clb, err := lc.tmc.TrustedLightBlock(height)
if err != nil {
return nil, err
}
return api.NewLightBlock(clb)
}

// GetLightBlock implements api.Client.
func (lc *lightClient) GetLightBlock(ctx context.Context, height int64) (*consensus.LightBlock, rpc.PeerFeedback, error) {
return tryProviders(ctx, lc, func(p api.Provider) (*consensus.LightBlock, rpc.PeerFeedback, error) {
Expand Down
6 changes: 6 additions & 0 deletions go/consensus/cometbft/light/p2p/p2p.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,12 @@ func (lp *lightClientProvider) SubmitEvidence(ctx context.Context, evidence *con
return pf, nil
}

// GetStoredLightBlock implements api.Provider.
func (lp *lightClientProvider) GetStoredLightBlock(_ int64) (*consensus.LightBlock, error) {
// The remote client provider stores no blocks locally.
return nil, consensus.ErrVersionNotFound
}

// GetLightBlock implements api.Provider.
func (lp *lightClientProvider) GetLightBlock(ctx context.Context, height int64) (*consensus.LightBlock, rpc.PeerFeedback, error) {
peerID := lp.getPeer()
Expand Down
23 changes: 12 additions & 11 deletions go/consensus/cometbft/light/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,15 @@ func (c *client) worker() {
}
}

// GetStoredBlock implements api.Client.
func (c *client) GetStoredLightBlock(height int64) (*consensus.LightBlock, error) {
clb, err := c.store.LightBlock(height)
if err != nil {
return nil, err
}
return api.NewLightBlock(clb)
}

// GetLightBlock implements api.Client.
func (c *client) GetLightBlock(ctx context.Context, height int64) (*consensus.LightBlock, rpc.PeerFeedback, error) {
select {
Expand Down Expand Up @@ -291,19 +300,11 @@ func (c *client) GetLightBlock(ctx context.Context, height int64) (*consensus.Li
return nil, nil, err
}

plb, err := clb.ToProto()
lb, err := api.NewLightBlock(clb)
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal light block: %w", err)
}
meta, err := plb.Marshal()
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal light block: %w", err)
return nil, nil, err
}

return &consensus.LightBlock{
Height: clb.Height,
Meta: meta,
}, rpc.NewNopPeerFeedback(), nil
return lb, rpc.NewNopPeerFeedback(), nil
}

// Direct peer query.
Expand Down
36 changes: 27 additions & 9 deletions go/consensus/p2p/light/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ const (

type service struct {
consensus consensus.Backend
logger *logging.Logger
lc consensus.LightClient

logger *logging.Logger
}

func (s *service) HandleRequest(ctx context.Context, method string, body cbor.RawMessage) (interface{}, error) {
Expand All @@ -30,12 +32,7 @@ func (s *service) HandleRequest(ctx context.Context, method string, body cbor.Ra
if err := cbor.Unmarshal(body, &rq); err != nil {
return nil, rpc.ErrBadRequest
}

lb, err := s.consensus.GetLightBlock(ctx, rq)
if err != nil {
return nil, err
}
return lb, nil
return s.handleGetLightBlock(ctx, rq)
case MethodGetParameters:
var rq int64
if err := cbor.Unmarshal(body, &rq); err != nil {
Expand All @@ -59,11 +56,32 @@ func (s *service) HandleRequest(ctx context.Context, method string, body cbor.Ra
}
}

func (s *service) handleGetLightBlock(ctx context.Context, height int64) (*consensus.LightBlock, error) {
lb, err := s.consensus.GetLightBlock(ctx, height)
if err != nil {
// Also try the local light store.
if lb, err = s.lc.GetStoredLightBlock(height); err != nil {
return nil, err
}
}
return lb, nil
}

// NewServer creates a new light block sync protocol server.
func NewServer(p2p rpc.P2P, chainContext string, consensus consensus.Backend) rpc.Server {
func NewServer(
p2p rpc.P2P,
chainContext string,
consensus consensus.Backend,
lightClient consensus.LightClient,
) rpc.Server {
p2p.RegisterProtocol(ProtocolID(chainContext), minProtocolPeers, totalProtocolPeers)

return rpc.NewServer(
ProtocolID(chainContext),
&service{consensus, logging.GetLogger("consensus/p22/light/server")},
&service{
consensus: consensus,
lc: lightClient,
logger: logging.GetLogger("consensus/p2p/light/server"),
},
)
}
4 changes: 4 additions & 0 deletions go/oasis-node/cmd/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/oasisprotocol/oasis-core/go/config"
consensusAPI "github.com/oasisprotocol/oasis-core/go/consensus/api"
"github.com/oasisprotocol/oasis-core/go/consensus/cometbft"
consensusLightP2P "github.com/oasisprotocol/oasis-core/go/consensus/p2p/light"
controlAPI "github.com/oasisprotocol/oasis-core/go/control/api"
genesisAPI "github.com/oasisprotocol/oasis-core/go/genesis/api"
governanceAPI "github.com/oasisprotocol/oasis-core/go/governance/api"
Expand Down Expand Up @@ -581,6 +582,9 @@ func NewNode() (node *Node, err error) { // nolint: gocyclo
}
node.svcMgr.Register(node.LightClient)

// Register consensus light client P2P protocol server.
node.P2P.RegisterProtocolServer(consensusLightP2P.NewServer(node.P2P, node.chainContext, node.Consensus, node.LightClient))

// If the consensus backend supports communicating with consensus services, we can also start
// all services required for runtime operation.
if node.Consensus.SupportedFeatures().Has(consensusAPI.FeatureServices) {
Expand Down

0 comments on commit a0bd142

Please sign in to comment.