Skip to content

Commit

Permalink
go/consensus/tendermint: Bump Tendermint Core to v0.34-rc4-oasis2
Browse files Browse the repository at this point in the history
  • Loading branch information
kostko committed Sep 4, 2020
1 parent 24c7327 commit a60aff5
Show file tree
Hide file tree
Showing 14 changed files with 137 additions and 232 deletions.
6 changes: 6 additions & 0 deletions .changelog/3229.breaking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
go/consensus: Simplify light client API

Methods `GetSignedHeader` and `GetValidatorSet` have been replaced with
`GetLightBlock` which provides both the signed header and the validator set.
This makes sense as the two are commonly used together so this saves a
round-trip.
7 changes: 1 addition & 6 deletions go/consensus/api/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,7 @@ func (b *BaseBackend) GetSignerNonce(ctx context.Context, req *GetSignerNonceReq
}

// Implements Backend.
func (b *BaseBackend) GetSignedHeader(ctx context.Context, height int64) (*SignedHeader, error) {
panic(ErrUnsupported)
}

// Implements Backend.
func (b *BaseBackend) GetValidatorSet(ctx context.Context, height int64) (*ValidatorSet, error) {
func (b *BaseBackend) GetLightBlock(ctx context.Context, height int64) (*LightBlock, error) {
panic(ErrUnsupported)
}

Expand Down
60 changes: 11 additions & 49 deletions go/consensus/api/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,8 @@ var (
// methodWatchBlocks is the WatchBlocks method.
methodWatchBlocks = serviceName.NewMethod("WatchBlocks", nil)

// methodGetSignedHeader is the GetSignedHeader method.
methodGetSignedHeader = lightServiceName.NewMethod("GetSignedHeader", int64(0))
// methodGetValidatorSet is the GetValidatorSet method.
methodGetValidatorSet = lightServiceName.NewMethod("GetValidatorSet", int64(0))
// methodGetLightBlock is the GetLightBlock method.
methodGetLightBlock = lightServiceName.NewMethod("GetLightBlock", int64(0))
// methodGetParameters is the GetParameters method.
methodGetParameters = lightServiceName.NewMethod("GetParameters", int64(0))
// methodStateSyncGet is the StateSyncGet method.
Expand Down Expand Up @@ -133,12 +131,8 @@ var (
HandlerType: (*LightClientBackend)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: methodGetSignedHeader.ShortName(),
Handler: handlerGetSignedHeader,
},
{
MethodName: methodGetValidatorSet.ShortName(),
Handler: handlerGetValidatorSet,
MethodName: methodGetLightBlock.ShortName(),
Handler: handlerGetLightBlock,
},
{
MethodName: methodGetParameters.ShortName(),
Expand Down Expand Up @@ -460,7 +454,7 @@ func handlerWatchBlocks(srv interface{}, stream grpc.ServerStream) error {
}
}

func handlerGetSignedHeader( // nolint: golint
func handlerGetLightBlock( // nolint: golint
srv interface{},
ctx context.Context,
dec func(interface{}) error,
Expand All @@ -471,37 +465,14 @@ func handlerGetSignedHeader( // nolint: golint
return nil, err
}
if interceptor == nil {
return srv.(LightClientBackend).GetSignedHeader(ctx, height)
return srv.(LightClientBackend).GetLightBlock(ctx, height)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: methodGetSignedHeader.FullName(),
FullMethod: methodGetLightBlock.FullName(),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(LightClientBackend).GetSignedHeader(ctx, req.(int64))
}
return interceptor(ctx, height, info, handler)
}

func handlerGetValidatorSet( // nolint: golint
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).GetValidatorSet(ctx, height)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: methodGetValidatorSet.FullName(),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(LightClientBackend).GetValidatorSet(ctx, req.(int64))
return srv.(LightClientBackend).GetLightBlock(ctx, req.(int64))
}
return interceptor(ctx, height, info, handler)
}
Expand Down Expand Up @@ -660,18 +631,9 @@ type consensusLightClient struct {
}

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

// Implements LightClientBackend.
func (c *consensusLightClient) GetValidatorSet(ctx context.Context, height int64) (*ValidatorSet, error) {
var rsp ValidatorSet
if err := c.conn.Invoke(ctx, methodGetValidatorSet.FullName(), height, &rsp); err != nil {
func (c *consensusLightClient) GetLightBlock(ctx context.Context, height int64) (*LightBlock, error) {
var rsp LightBlock
if err := c.conn.Invoke(ctx, methodGetLightBlock.FullName(), height, &rsp); err != nil {
return nil, err
}
return &rsp, nil
Expand Down
24 changes: 7 additions & 17 deletions go/consensus/api/light.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ import (

// LightClientBackend is the limited consensus interface used by light clients.
type LightClientBackend interface {
// GetSignedHeader returns the signed header for a specific height.
GetSignedHeader(ctx context.Context, height int64) (*SignedHeader, error)

// GetValidatorSet returns the validator set for a specific height.
GetValidatorSet(ctx context.Context, height int64) (*ValidatorSet, error)
// GetLightBlock returns a light version of the consensus layer block that can be used for light
// client verification.
GetLightBlock(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 All @@ -30,19 +28,11 @@ type LightClientBackend interface {
SubmitEvidence(ctx context.Context, evidence *Evidence) error
}

// SignedHeader is a signed consensus block header.
type SignedHeader struct {
// Height contains the block height this header is for.
Height int64 `json:"height"`
// Meta contains the consensus backend specific signed header.
Meta []byte `json:"meta"`
}

// ValidatorSet contains the validator set information.
type ValidatorSet struct {
// Height contains the block height this validator set is for.
// LightBlock is a light consensus block suitable for syncing light clients.
type LightBlock struct {
// Height contains the block height.
Height int64 `json:"height"`
// Meta contains the consensus backend specific validator set.
// Meta contains the consensus backend specific light block.
Meta []byte `json:"meta"`
}

Expand Down
1 change: 0 additions & 1 deletion go/consensus/tendermint/api/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ func genesisToTendermint(d *genesis.Document) (*tmtypes.GenesisDoc, error) {
evCfg.MaxNum = d.Consensus.Parameters.MaxEvidenceNum
evCfg.MaxAgeNumBlocks = debondingInterval * epochInterval
evCfg.MaxAgeDuration = time.Duration(evCfg.MaxAgeNumBlocks) * (d.Consensus.Parameters.TimeoutCommit + 1*time.Second)
evCfg.ProofTrialPeriod = evCfg.MaxAgeNumBlocks / 2

doc := tmtypes.GenesisDoc{
ChainID: d.ChainContext()[:tmtypes.MaxChainIDLen],
Expand Down
3 changes: 1 addition & 2 deletions go/consensus/tendermint/apps/staking/staking.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"

"github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"

"github.com/oasisprotocol/oasis-core/go/common/cbor"
"github.com/oasisprotocol/oasis-core/go/common/quantity"
Expand Down Expand Up @@ -85,7 +84,7 @@ func (app *stakingApplication) BeginBlock(ctx *api.Context, request types.Reques
// the actual evidence has already been verified by Tendermint to be valid.
for _, evidence := range request.ByzantineValidators {
switch evidence.Type {
case tmtypes.ABCIEvidenceTypeDuplicateVote:
case types.EvidenceType_DUPLICATE_VOTE:
if err := onEvidenceDoubleSign(ctx, evidence.Validator.Address, evidence.Height, evidence.Time, evidence.Validator.Power); err != nil {
return err
}
Expand Down
36 changes: 12 additions & 24 deletions go/consensus/tendermint/full/light.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"

tmstate "github.com/tendermint/tendermint/state"
tmtypes "github.com/tendermint/tendermint/types"

"github.com/oasisprotocol/oasis-core/go/common/cbor"
consensusAPI "github.com/oasisprotocol/oasis-core/go/consensus/api"
Expand All @@ -13,7 +14,7 @@ import (
)

// Implements LightClientBackend.
func (t *fullService) GetSignedHeader(ctx context.Context, height int64) (*consensusAPI.SignedHeader, error) {
func (t *fullService) GetLightBlock(ctx context.Context, height int64) (*consensusAPI.LightBlock, error) {
if err := t.ensureStarted(ctx); err != nil {
return nil, err
}
Expand All @@ -27,40 +28,27 @@ func (t *fullService) GetSignedHeader(ctx context.Context, height int64) (*conse
return nil, fmt.Errorf("tendermint: header is nil")
}

meta, err := commit.SignedHeader.ToProto().Marshal()
if err != nil {
return nil, fmt.Errorf("tendermint: failed to marshal signed header: %w", err)
}

return &consensusAPI.SignedHeader{
Height: commit.Header.Height,
Meta: meta,
}, nil
}

// Implements LightClientBackend.
func (t *fullService) GetValidatorSet(ctx context.Context, height int64) (*consensusAPI.ValidatorSet, error) {
if err := t.ensureStarted(ctx); err != nil {
return nil, err
}

// Don't use the client as that imposes stupid pagination. Access the state database directly.
vals, err := tmstate.LoadValidators(t.stateDb, height)
if err != nil {
return nil, consensusAPI.ErrVersionNotFound
}

protoVals, err := vals.ToProto()
lb := tmtypes.LightBlock{
SignedHeader: &commit.SignedHeader,
ValidatorSet: vals,
}
protoLb, err := lb.ToProto()
if err != nil {
return nil, fmt.Errorf("tendermint: failed to convert validators: %w", err)
return nil, fmt.Errorf("tendermint: failed to convert light block: %w", err)
}
meta, err := protoVals.Marshal()
meta, err := protoLb.Marshal()
if err != nil {
return nil, fmt.Errorf("tendermint: failed to marshal validators: %w", err)
return nil, fmt.Errorf("tendermint: failed to marshal light block: %w", err)
}

return &consensusAPI.ValidatorSet{
Height: height,
return &consensusAPI.LightBlock{
Height: commit.Header.Height,
Meta: meta,
}, nil
}
Expand Down
56 changes: 26 additions & 30 deletions go/consensus/tendermint/full/statesync.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,23 @@ func (sp *stateProvider) AppHash(height uint64) ([]byte, error) {
defer sp.Unlock()

// We have to fetch the next height, which contains the app hash for the previous height.
header, err := sp.lc.GetVerifiedSignedHeader(sp.ctx, int64(height+1))
lb, err := sp.lc.GetVerifiedLightBlock(sp.ctx, int64(height+1))
if err != nil {
return nil, err
}
return header.AppHash, nil
return lb.AppHash, nil
}

// Implements tmstatesync.StateProvider.
func (sp *stateProvider) Commit(height uint64) (*tmtypes.Commit, error) {
sp.Lock()
defer sp.Unlock()

header, err := sp.lc.GetVerifiedSignedHeader(sp.ctx, int64(height))
lb, err := sp.lc.GetVerifiedLightBlock(sp.ctx, int64(height))
if err != nil {
return nil, err
}
return header.Commit, nil
return lb.Commit, nil
}

// Implements tmstatesync.StateProvider.
Expand All @@ -62,45 +62,41 @@ func (sp *stateProvider) State(height uint64) (tmstate.State, error) {
// XXX: This will fail in case an upgrade happened in-between.
state.Version.Consensus.App = version.ConsensusProtocol.ToU64()

// We need to verify up until h+2, to get the validator set. This also prefetches the headers
// for h and h+1 in the typical case where the trusted header is after the snapshot height.
_, err := sp.lc.GetVerifiedSignedHeader(sp.ctx, int64(height+2))
// The snapshot height maps onto the state heights as follows:
//
// height: last block, i.e. the snapshotted height
// height+1: current block, i.e. the first block we'll process after the snapshot
// height+2: next block, i.e. the second block after the snapshot
//
// We need to fetch the NextValidators from height+2 because if the application changed
// the validator set at the snapshot height then this only takes effect at height+2.
lastLightBlock, err := sp.lc.GetVerifiedLightBlock(sp.ctx, int64(height))
if err != nil {
return tmstate.State{}, err
}
header, err := sp.lc.GetVerifiedSignedHeader(sp.ctx, int64(height))
curLightBlock, err := sp.lc.GetVerifiedLightBlock(sp.ctx, int64(height)+1)
if err != nil {
return tmstate.State{}, err
}
nextHeader, err := sp.lc.GetVerifiedSignedHeader(sp.ctx, int64(height+1))
nextLightBlock, err := sp.lc.GetVerifiedLightBlock(sp.ctx, int64(height)+2)
if err != nil {
return tmstate.State{}, err
}
state.LastBlockHeight = header.Height
state.LastBlockTime = header.Time
state.LastBlockID = header.Commit.BlockID
state.AppHash = nextHeader.AppHash
state.LastResultsHash = nextHeader.LastResultsHash

state.LastValidators, _, err = sp.lc.GetVerifiedValidatorSet(sp.ctx, int64(height))
if err != nil {
return tmstate.State{}, err
}
state.Validators, _, err = sp.lc.GetVerifiedValidatorSet(sp.ctx, int64(height+1))
if err != nil {
return tmstate.State{}, err
}
state.NextValidators, _, err = sp.lc.GetVerifiedValidatorSet(sp.ctx, int64(height+2))
if err != nil {
return tmstate.State{}, err
}
state.LastHeightValidatorsChanged = int64(height)
state.LastBlockHeight = lastLightBlock.Height
state.LastBlockTime = lastLightBlock.Time
state.LastBlockID = lastLightBlock.Commit.BlockID
state.AppHash = curLightBlock.AppHash
state.LastResultsHash = curLightBlock.LastResultsHash
state.LastValidators = lastLightBlock.ValidatorSet
state.Validators = curLightBlock.ValidatorSet
state.NextValidators = nextLightBlock.ValidatorSet
state.LastHeightValidatorsChanged = nextLightBlock.Height

// Fetch consensus parameters with light client verification.
params, err := sp.lc.GetVerifiedParameters(sp.ctx, nextHeader.Height)
params, err := sp.lc.GetVerifiedParameters(sp.ctx, nextLightBlock.Height)
if err != nil {
return tmstate.State{}, fmt.Errorf("failed to fetch consensus parameters for height %d: %w",
nextHeader.Height,
nextLightBlock.Height,
err,
)
}
Expand Down
Loading

0 comments on commit a60aff5

Please sign in to comment.