Browse Source

state: avoid panics for marshaling errors (#8125)

pull/8131/head
Sam Kleinman 3 years ago
committed by GitHub
parent
commit
48b1952f18
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 22 deletions
  1. +1
    -3
      internal/rpc/core/blocks.go
  2. +3
    -5
      internal/rpc/core/consensus.go
  3. +16
    -9
      internal/state/state.go
  4. +10
    -3
      internal/state/state_test.go
  5. +12
    -2
      internal/state/store.go

+ 1
- 3
internal/rpc/core/blocks.go View File

@ -23,9 +23,7 @@ import (
// order (highest first). // order (highest first).
// //
// More: https://docs.tendermint.com/master/rpc/#/Info/blockchain // More: https://docs.tendermint.com/master/rpc/#/Info/blockchain
func (env *Environment) BlockchainInfo(
ctx context.Context,
minHeight, maxHeight int64) (*coretypes.ResultBlockchainInfo, error) {
func (env *Environment) BlockchainInfo(ctx context.Context, minHeight, maxHeight int64) (*coretypes.ResultBlockchainInfo, error) {
const limit int64 = 20 const limit int64 = 20


+ 3
- 5
internal/rpc/core/consensus.go View File

@ -14,10 +14,7 @@ import (
// for the validators in the set as used in computing their Merkle root. // for the validators in the set as used in computing their Merkle root.
// //
// More: https://docs.tendermint.com/master/rpc/#/Info/validators // More: https://docs.tendermint.com/master/rpc/#/Info/validators
func (env *Environment) Validators(
ctx context.Context,
heightPtr *int64,
pagePtr, perPagePtr *int) (*coretypes.ResultValidators, error) {
func (env *Environment) Validators(ctx context.Context, heightPtr *int64, pagePtr, perPagePtr *int) (*coretypes.ResultValidators, error) {
// The latest validator that we know is the NextValidator of the last block. // The latest validator that we know is the NextValidator of the last block.
height, err := env.getHeight(env.latestUncommittedHeight(), heightPtr) height, err := env.getHeight(env.latestUncommittedHeight(), heightPtr)
@ -86,7 +83,8 @@ func (env *Environment) DumpConsensusState(ctx context.Context) (*coretypes.Resu
} }
return &coretypes.ResultDumpConsensusState{ return &coretypes.ResultDumpConsensusState{
RoundState: roundState, RoundState: roundState,
Peers: peerStates}, nil
Peers: peerStates,
}, nil
} }
// ConsensusState returns a concise summary of the consensus state. // ConsensusState returns a concise summary of the consensus state.


+ 16
- 9
internal/state/state.go View File

@ -129,23 +129,30 @@ func (state State) Copy() State {
} }
// Equals returns true if the States are identical. // Equals returns true if the States are identical.
func (state State) Equals(state2 State) bool {
sbz, s2bz := state.Bytes(), state2.Bytes()
return bytes.Equal(sbz, s2bz)
func (state State) Equals(state2 State) (bool, error) {
sbz, err := state.Bytes()
if err != nil {
return false, err
}
s2bz, err := state2.Bytes()
if err != nil {
return false, err
}
return bytes.Equal(sbz, s2bz), nil
} }
// Bytes serializes the State using protobuf.
// It panics if either casting to protobuf or serialization fails.
func (state State) Bytes() []byte {
// Bytes serializes the State using protobuf, propagating marshaling
// errors
func (state State) Bytes() ([]byte, error) {
sm, err := state.ToProto() sm, err := state.ToProto()
if err != nil { if err != nil {
panic(err)
return nil, err
} }
bz, err := proto.Marshal(sm) bz, err := proto.Marshal(sm)
if err != nil { if err != nil {
panic(err)
return nil, err
} }
return bz
return bz, nil
} }
// IsEmpty returns true if the State is equal to the empty State. // IsEmpty returns true if the State is equal to the empty State.


+ 10
- 3
internal/state/state_test.go View File

@ -55,13 +55,18 @@ func TestStateCopy(t *testing.T) {
stateCopy := state.Copy() stateCopy := state.Copy()
assert.True(t, state.Equals(stateCopy),
seq, err := state.Equals(stateCopy)
require.NoError(t, err)
assert.True(t, seq,
"expected state and its copy to be identical.\ngot: %v\nexpected: %v", "expected state and its copy to be identical.\ngot: %v\nexpected: %v",
stateCopy, state) stateCopy, state)
stateCopy.LastBlockHeight++ stateCopy.LastBlockHeight++
stateCopy.LastValidators = state.Validators stateCopy.LastValidators = state.Validators
assert.False(t, state.Equals(stateCopy), "expected states to be different. got same %v", state)
seq, err = state.Equals(stateCopy)
require.NoError(t, err)
assert.False(t, seq, "expected states to be different. got same %v", state)
} }
// TestMakeGenesisStateNilValidators tests state's consistency when genesis file's validators field is nil. // TestMakeGenesisStateNilValidators tests state's consistency when genesis file's validators field is nil.
@ -90,7 +95,9 @@ func TestStateSaveLoad(t *testing.T) {
loadedState, err := stateStore.Load() loadedState, err := stateStore.Load()
require.NoError(t, err) require.NoError(t, err)
assert.True(t, state.Equals(loadedState),
seq, err := state.Equals(loadedState)
require.NoError(t, err)
assert.True(t, seq,
"expected state and its copy to be identical.\ngot: %v\nexpected: %v", "expected state and its copy to be identical.\ngot: %v\nexpected: %v",
loadedState, state) loadedState, state)
} }


+ 12
- 2
internal/state/store.go View File

@ -170,7 +170,12 @@ func (store dbStore) save(state State, key []byte) error {
return err return err
} }
if err := batch.Set(key, state.Bytes()); err != nil {
stateBz, err := state.Bytes()
if err != nil {
return err
}
if err := batch.Set(key, stateBz); err != nil {
return err return err
} }
@ -206,7 +211,12 @@ func (store dbStore) Bootstrap(state State) error {
return err return err
} }
if err := batch.Set(stateKey, state.Bytes()); err != nil {
stateBz, err := state.Bytes()
if err != nil {
return err
}
if err := batch.Set(stateKey, stateBz); err != nil {
return err return err
} }


Loading…
Cancel
Save