Skip to content

Commit

Permalink
go/consensus/tendermint: Allow queries without a full ApplicaitonState
Browse files Browse the repository at this point in the history
The timekeeping part of this (needed for the registry) will be somewhat
annoying to implement, and it's unfortunate that the ApplicationState is
now split into two interfaces, but I can't think of a better way to do
it, and this shouldn't be that bad even if we add more things.
  • Loading branch information
Yawning committed May 20, 2020
1 parent 639f25f commit 9b89233
Show file tree
Hide file tree
Showing 16 changed files with 100 additions and 45 deletions.
2 changes: 1 addition & 1 deletion go/consensus/tendermint/abci/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type ImmutableState struct {
}

// NewImmutableState creates a new immutable consensus backend state wrapper.
func NewImmutableState(ctx context.Context, state api.ApplicationState, version int64) (*ImmutableState, error) {
func NewImmutableState(ctx context.Context, state api.ApplicationQueryState, version int64) (*ImmutableState, error) {
is, err := api.NewImmutableState(ctx, state, version)
if err != nil {
return nil, err
Expand Down
24 changes: 15 additions & 9 deletions go/consensus/tendermint/api/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@ var (

// ApplicationState is the overall past, present and future state of all multiplexed applications.
type ApplicationState interface {
// Storage returns the storage backend.
Storage() storage.LocalBackend

// BlockHeight returns the last committed block height.
BlockHeight() int64
ApplicationQueryState

// BlockHash returns the last committed block hash.
BlockHash() []byte
Expand All @@ -49,9 +45,6 @@ type ApplicationState interface {
// GetBaseEpoch returns the base epoch.
GetBaseEpoch() (epochtime.EpochTime, error)

// GetEpoch returns epoch at block height.
GetEpoch(ctx context.Context, blockHeight int64) (epochtime.EpochTime, error)

// GetCurrentEpoch returns the epoch at the current block height.
GetCurrentEpoch(ctx context.Context) (epochtime.EpochTime, error)

Expand All @@ -69,6 +62,19 @@ type ApplicationState interface {
NewContext(mode ContextMode, now time.Time) *Context
}

// ApplicationQueryState is minimum methods required to service
// ApplicationState queries.
type ApplicationQueryState interface {
// Storage returns the storage backend.
Storage() storage.LocalBackend

// BlockHeight returns the last committed block height.
BlockHeight() int64

// GetEpoch returns epoch at block height.
GetEpoch(ctx context.Context, blockHeight int64) (epochtime.EpochTime, error)
}

// MockApplicationStateConfig is the configuration for the mock application state.
type MockApplicationStateConfig struct {
BlockHeight int64
Expand Down Expand Up @@ -203,7 +209,7 @@ func (s *ImmutableState) Close() {
}

// NewImmutableState creates a new immutable state wrapper.
func NewImmutableState(ctx context.Context, state ApplicationState, version int64) (*ImmutableState, error) {
func NewImmutableState(ctx context.Context, state ApplicationQueryState, version int64) (*ImmutableState, error) {
if state == nil {
return nil, ErrNoState
}
Expand Down
13 changes: 10 additions & 3 deletions go/consensus/tendermint/apps/beacon/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"

beacon "github.com/oasislabs/oasis-core/go/beacon/api"
abciAPI "github.com/oasislabs/oasis-core/go/consensus/tendermint/api"
beaconState "github.com/oasislabs/oasis-core/go/consensus/tendermint/apps/beacon/state"
)

Expand All @@ -15,12 +16,12 @@ type Query interface {

// QueryFactory is the beacon query factory.
type QueryFactory struct {
app *beaconApplication
state abciAPI.ApplicationQueryState
}

// QueryAt returns the beacon query interface for a specific height.
func (sf *QueryFactory) QueryAt(ctx context.Context, height int64) (Query, error) {
state, err := beaconState.NewImmutableState(ctx, sf.app.state, height)
state, err := beaconState.NewImmutableState(ctx, sf.state, height)
if err != nil {
return nil, err
}
Expand All @@ -36,5 +37,11 @@ func (bq *beaconQuerier) Beacon(ctx context.Context) ([]byte, error) {
}

func (app *beaconApplication) QueryFactory() interface{} {
return &QueryFactory{app}
return &QueryFactory{app.state}
}

// NewQueryFactory returns a new QueryFactory backed by the given state
// instance.
func NewQueryFactory(state abciAPI.ApplicationQueryState) *QueryFactory {
return &QueryFactory{state}
}
2 changes: 1 addition & 1 deletion go/consensus/tendermint/apps/beacon/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type ImmutableState struct {
is *abciAPI.ImmutableState
}

func NewImmutableState(ctx context.Context, state abciAPI.ApplicationState, version int64) (*ImmutableState, error) {
func NewImmutableState(ctx context.Context, state abciAPI.ApplicationQueryState, version int64) (*ImmutableState, error) {
is, err := abciAPI.NewImmutableState(ctx, state, version)
if err != nil {
return nil, err
Expand Down
13 changes: 10 additions & 3 deletions go/consensus/tendermint/apps/epochtime_mock/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package epochtimemock
import (
"context"

abciAPI "github.com/oasislabs/oasis-core/go/consensus/tendermint/api"
epochtime "github.com/oasislabs/oasis-core/go/epochtime/api"
)

Expand All @@ -13,12 +14,12 @@ type Query interface {

// QueryFactory is the mock epochtime query factory.
type QueryFactory struct {
app *epochTimeMockApplication
state abciAPI.ApplicationQueryState
}

// QueryAt returns the mock epochtime query interface for a specific height.
func (sf *QueryFactory) QueryAt(ctx context.Context, height int64) (Query, error) {
state, err := newImmutableState(ctx, sf.app.state, height)
state, err := newImmutableState(ctx, sf.state, height)
if err != nil {
return nil, err
}
Expand All @@ -34,5 +35,11 @@ func (eq *epochtimeMockQuerier) Epoch(ctx context.Context) (epochtime.EpochTime,
}

func (app *epochTimeMockApplication) QueryFactory() interface{} {
return &QueryFactory{app}
return &QueryFactory{app.state}
}

// NewQueryFactory returns a new QueryFactory backed by the given state
// instance.
func NewQueryFactory(state abciAPI.ApplicationQueryState) *QueryFactory {
return &QueryFactory{state}
}
2 changes: 1 addition & 1 deletion go/consensus/tendermint/apps/epochtime_mock/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (s *immutableState) getFutureEpoch(ctx context.Context) (*mockEpochTimeStat
return &state, nil
}

func newImmutableState(ctx context.Context, state abciAPI.ApplicationState, version int64) (*immutableState, error) {
func newImmutableState(ctx context.Context, state abciAPI.ApplicationQueryState, version int64) (*immutableState, error) {
is, err := abciAPI.NewImmutableState(ctx, state, version)
if err != nil {
return nil, err
Expand Down
13 changes: 10 additions & 3 deletions go/consensus/tendermint/apps/keymanager/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"

"github.com/oasislabs/oasis-core/go/common"
abciAPI "github.com/oasislabs/oasis-core/go/consensus/tendermint/api"
keymanagerState "github.com/oasislabs/oasis-core/go/consensus/tendermint/apps/keymanager/state"
keymanager "github.com/oasislabs/oasis-core/go/keymanager/api"
)
Expand All @@ -17,12 +18,12 @@ type Query interface {

// QueryFactory is the key manager query factory.
type QueryFactory struct {
app *keymanagerApplication
state abciAPI.ApplicationQueryState
}

// QueryAt returns the key manager query interface for a specific height.
func (sf *QueryFactory) QueryAt(ctx context.Context, height int64) (Query, error) {
state, err := keymanagerState.NewImmutableState(ctx, sf.app.state, height)
state, err := keymanagerState.NewImmutableState(ctx, sf.state, height)
if err != nil {
return nil, err
}
Expand All @@ -42,5 +43,11 @@ func (kq *keymanagerQuerier) Statuses(ctx context.Context) ([]*keymanager.Status
}

func (app *keymanagerApplication) QueryFactory() interface{} {
return &QueryFactory{app}
return &QueryFactory{app.state}
}

// NewQueryFactory returns a new QueryFactory backed by the given state
// instance.
func NewQueryFactory(state abciAPI.ApplicationQueryState) *QueryFactory {
return &QueryFactory{state}
}
2 changes: 1 addition & 1 deletion go/consensus/tendermint/apps/keymanager/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (st *ImmutableState) Status(ctx context.Context, id common.Namespace) (*api
return &status, nil
}

func NewImmutableState(ctx context.Context, state abciAPI.ApplicationState, version int64) (*ImmutableState, error) {
func NewImmutableState(ctx context.Context, state abciAPI.ApplicationQueryState, version int64) (*ImmutableState, error) {
is, err := abciAPI.NewImmutableState(ctx, state, version)
if err != nil {
return nil, err
Expand Down
25 changes: 16 additions & 9 deletions go/consensus/tendermint/apps/registry/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/oasislabs/oasis-core/go/common/crypto/signature"
"github.com/oasislabs/oasis-core/go/common/entity"
"github.com/oasislabs/oasis-core/go/common/node"
abciAPI "github.com/oasislabs/oasis-core/go/consensus/tendermint/api"
registryState "github.com/oasislabs/oasis-core/go/consensus/tendermint/apps/registry/state"
registry "github.com/oasislabs/oasis-core/go/registry/api"
)
Expand All @@ -26,22 +27,22 @@ type Query interface {

// QueryFactory is the registry query factory.
type QueryFactory struct {
app *registryApplication
state abciAPI.ApplicationQueryState
}

// QueryAt returns the registry query interface for a specific height.
func (sf *QueryFactory) QueryAt(ctx context.Context, height int64) (Query, error) {
state, err := registryState.NewImmutableState(ctx, sf.app.state, height)
state, err := registryState.NewImmutableState(ctx, sf.state, height)
if err != nil {
return nil, err
}
return &registryQuerier{sf.app, state, height}, nil
return &registryQuerier{sf.state, state, height}, nil
}

type registryQuerier struct {
app *registryApplication
state *registryState.ImmutableState
height int64
queryState abciAPI.ApplicationQueryState
state *registryState.ImmutableState
height int64
}

func (rq *registryQuerier) Entity(ctx context.Context, id signature.PublicKey) (*entity.Entity, error) {
Expand All @@ -53,7 +54,7 @@ func (rq *registryQuerier) Entities(ctx context.Context) ([]*entity.Entity, erro
}

func (rq *registryQuerier) Node(ctx context.Context, id signature.PublicKey) (*node.Node, error) {
epoch, err := rq.app.state.GetEpoch(ctx, rq.height)
epoch, err := rq.queryState.GetEpoch(ctx, rq.height)
if err != nil {
return nil, fmt.Errorf("failed to get epoch: %w", err)
}
Expand All @@ -75,7 +76,7 @@ func (rq *registryQuerier) NodeStatus(ctx context.Context, id signature.PublicKe
}

func (rq *registryQuerier) Nodes(ctx context.Context) ([]*node.Node, error) {
epoch, err := rq.app.state.GetEpoch(ctx, rq.height)
epoch, err := rq.queryState.GetEpoch(ctx, rq.height)
if err != nil {
return nil, fmt.Errorf("failed to get epoch: %w", err)
}
Expand Down Expand Up @@ -105,5 +106,11 @@ func (rq *registryQuerier) Runtimes(ctx context.Context) ([]*registry.Runtime, e
}

func (app *registryApplication) QueryFactory() interface{} {
return &QueryFactory{app}
return &QueryFactory{app.state}
}

// NewQueryFactory returns a new QueryFactory backed by the given state
// instance.
func NewQueryFactory(state abciAPI.ApplicationQueryState) *QueryFactory {
return &QueryFactory{state}
}
2 changes: 1 addition & 1 deletion go/consensus/tendermint/apps/registry/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ func (s *ImmutableState) NodeBySubKey(ctx context.Context, key signature.PublicK
return s.Node(ctx, id)
}

func NewImmutableState(ctx context.Context, state abciAPI.ApplicationState, version int64) (*ImmutableState, error) {
func NewImmutableState(ctx context.Context, state abciAPI.ApplicationQueryState, version int64) (*ImmutableState, error) {
is, err := abciAPI.NewImmutableState(ctx, state, version)
if err != nil {
return nil, err
Expand Down
13 changes: 10 additions & 3 deletions go/consensus/tendermint/apps/roothash/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"

"github.com/oasislabs/oasis-core/go/common"
abciAPI "github.com/oasislabs/oasis-core/go/consensus/tendermint/api"
roothashState "github.com/oasislabs/oasis-core/go/consensus/tendermint/apps/roothash/state"
roothash "github.com/oasislabs/oasis-core/go/roothash/api"
"github.com/oasislabs/oasis-core/go/roothash/api/block"
Expand All @@ -18,12 +19,12 @@ type Query interface {

// QueryFactory is the roothash query factory.
type QueryFactory struct {
app *rootHashApplication
state abciAPI.ApplicationQueryState
}

// QueryAt returns the roothash query interface for a specific height.
func (sf *QueryFactory) QueryAt(ctx context.Context, height int64) (Query, error) {
state, err := roothashState.NewImmutableState(ctx, sf.app.state, height)
state, err := roothashState.NewImmutableState(ctx, sf.state, height)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -51,5 +52,11 @@ func (rq *rootHashQuerier) GenesisBlock(ctx context.Context, id common.Namespace
}

func (app *rootHashApplication) QueryFactory() interface{} {
return &QueryFactory{app}
return &QueryFactory{app.state}
}

// NewQueryFactory returns a new QueryFactory backed by the given state
// instance.
func NewQueryFactory(state abciAPI.ApplicationQueryState) *QueryFactory {
return &QueryFactory{state}
}
2 changes: 1 addition & 1 deletion go/consensus/tendermint/apps/roothash/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type ImmutableState struct {
is *abciAPI.ImmutableState
}

func NewImmutableState(ctx context.Context, state abciAPI.ApplicationState, version int64) (*ImmutableState, error) {
func NewImmutableState(ctx context.Context, state abciAPI.ApplicationQueryState, version int64) (*ImmutableState, error) {
is, err := abciAPI.NewImmutableState(ctx, state, version)
if err != nil {
return nil, err
Expand Down
15 changes: 11 additions & 4 deletions go/consensus/tendermint/apps/scheduler/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"

"github.com/oasislabs/oasis-core/go/common/crypto/signature"
abciAPI "github.com/oasislabs/oasis-core/go/consensus/tendermint/api"
registryState "github.com/oasislabs/oasis-core/go/consensus/tendermint/apps/registry/state"
schedulerState "github.com/oasislabs/oasis-core/go/consensus/tendermint/apps/scheduler/state"
scheduler "github.com/oasislabs/oasis-core/go/scheduler/api"
Expand All @@ -19,18 +20,18 @@ type Query interface {

// QueryFactory is the scheduler query factory.
type QueryFactory struct {
app *schedulerApplication
state abciAPI.ApplicationQueryState
}

// QueryAt returns the scheduler query interface for a specific height.
func (sf *QueryFactory) QueryAt(ctx context.Context, height int64) (Query, error) {
state, err := schedulerState.NewImmutableState(ctx, sf.app.state, height)
state, err := schedulerState.NewImmutableState(ctx, sf.state, height)
if err != nil {
return nil, err
}

// Some queries need access to the registry to give useful responses.
regState, err := registryState.NewImmutableState(ctx, sf.app.state, height)
regState, err := registryState.NewImmutableState(ctx, sf.state, height)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -98,5 +99,11 @@ func (sq *schedulerQuerier) KindsCommittees(ctx context.Context, kinds []schedul
}

func (app *schedulerApplication) QueryFactory() interface{} {
return &QueryFactory{app}
return &QueryFactory{app.state}
}

// NewQueryFactory returns a new QueryFactory backed by the given state
// instance.
func NewQueryFactory(state abciAPI.ApplicationQueryState) *QueryFactory {
return &QueryFactory{state}
}
2 changes: 1 addition & 1 deletion go/consensus/tendermint/apps/scheduler/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func (s *ImmutableState) ConsensusParameters(ctx context.Context) (*api.Consensu
return &params, nil
}

func NewImmutableState(ctx context.Context, state abciAPI.ApplicationState, version int64) (*ImmutableState, error) {
func NewImmutableState(ctx context.Context, state abciAPI.ApplicationQueryState, version int64) (*ImmutableState, error) {
is, err := abciAPI.NewImmutableState(ctx, state, version)
if err != nil {
return nil, err
Expand Down
Loading

0 comments on commit 9b89233

Please sign in to comment.