mirror of
https://github.com/tendermint/tendermint.git
synced 2026-05-01 21:05:43 +00:00
proto: seperate native and proto types (#5994)
## Description Separate protobuf and domain types. We should avoid using protobuf in our core logic. ref #5460
This commit is contained in:
@@ -52,10 +52,12 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
|
||||
- [cli] \#5772 `gen_node_key` output now contains node ID (`id` field) (@melekes)
|
||||
- [blockchain/v2] \#5774 Send status request when new peer joins (@melekes)
|
||||
- [consensus] \#5792 Deprecates the `time_iota_ms` consensus parameter, to reduce the bug surface. The parameter is no longer used. (@valardragon)
|
||||
- [types] \#5994 Reduce the use of protobuf types in core logic.
|
||||
- `ConsensusParams`, `BlockParams`, `ValidatorParams`, `EvidenceParams`, `VersionParams`, `sm.Version` and `version.Consensus` have become native types. They still utilize protobuf when being sent over the wire or written to disk.
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
- [types] \#5523 Change json naming of `PartSetHeader` within `BlockID` from `parts` to `part_set_header` (@marbar3778)
|
||||
- [privval] \#5638 Increase read/write timeout to 5s and calculate ping interval based on it (@JoeKash)
|
||||
- [blockchain/v1] [\#5701](https://github.com/tendermint/tendermint/pull/5701) Handle peers without blocks (@melekes)
|
||||
- [blockchain/v1] \#5711 Fix deadlock (@melekes)
|
||||
- [blockchain/v1] \#5711 Fix deadlock (@melekes)
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
"github.com/tendermint/tendermint/privval"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
)
|
||||
@@ -79,7 +78,7 @@ func initFilesWithConfig(config *cfg.Config) error {
|
||||
ConsensusParams: types.DefaultConsensusParams(),
|
||||
}
|
||||
if keyType == "secp256k1" {
|
||||
genDoc.ConsensusParams.Validator = tmproto.ValidatorParams{
|
||||
genDoc.ConsensusParams.Validator = types.ValidatorParams{
|
||||
PubKeyTypes: []string{types.ABCIPubKeyTypeSecp256k1},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
"github.com/tendermint/tendermint/privval"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
)
|
||||
@@ -189,7 +188,7 @@ func testnetFiles(cmd *cobra.Command, args []string) error {
|
||||
ConsensusParams: types.DefaultConsensusParams(),
|
||||
}
|
||||
if keyType == "secp256k1" {
|
||||
genDoc.ConsensusParams.Validator = tmproto.ValidatorParams{
|
||||
genDoc.ConsensusParams.Validator = types.ValidatorParams{
|
||||
PubKeyTypes: []string{types.ABCIPubKeyTypeSecp256k1},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ func (h *Handshaker) ReplayBlocks(
|
||||
}
|
||||
|
||||
if res.ConsensusParams != nil {
|
||||
state.ConsensusParams = types.UpdateConsensusParams(state.ConsensusParams, res.ConsensusParams)
|
||||
state.ConsensusParams = state.ConsensusParams.UpdateConsensusParams(res.ConsensusParams)
|
||||
state.Version.Consensus.App = state.ConsensusParams.Version.AppVersion
|
||||
}
|
||||
// We update the last results hash with the empty hash, to conform with RFC-6962.
|
||||
|
||||
@@ -1164,14 +1164,14 @@ func stateAndStore(
|
||||
|
||||
type mockBlockStore struct {
|
||||
config *cfg.Config
|
||||
params tmproto.ConsensusParams
|
||||
params types.ConsensusParams
|
||||
chain []*types.Block
|
||||
commits []*types.Commit
|
||||
base int64
|
||||
}
|
||||
|
||||
// TODO: NewBlockStore(db.NewMemDB) ...
|
||||
func newMockBlockStore(config *cfg.Config, params tmproto.ConsensusParams) *mockBlockStore {
|
||||
func newMockBlockStore(config *cfg.Config, params types.ConsensusParams) *mockBlockStore {
|
||||
return &mockBlockStore{config, params, nil, nil, 0}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"github.com/tendermint/tendermint/evidence/mocks"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
smmocks "github.com/tendermint/tendermint/state/mocks"
|
||||
"github.com/tendermint/tendermint/store"
|
||||
@@ -364,12 +363,12 @@ func TestRecoverPendingEvidence(t *testing.T) {
|
||||
newStateStore.On("Load").Return(sm.State{
|
||||
LastBlockTime: defaultEvidenceTime.Add(25 * time.Minute),
|
||||
LastBlockHeight: height + 15,
|
||||
ConsensusParams: tmproto.ConsensusParams{
|
||||
Block: tmproto.BlockParams{
|
||||
ConsensusParams: types.ConsensusParams{
|
||||
Block: types.BlockParams{
|
||||
MaxBytes: 22020096,
|
||||
MaxGas: -1,
|
||||
},
|
||||
Evidence: tmproto.EvidenceParams{
|
||||
Evidence: types.EvidenceParams{
|
||||
MaxAgeNumBlocks: 20,
|
||||
MaxAgeDuration: 20 * time.Minute,
|
||||
MaxBytes: 1000,
|
||||
@@ -399,12 +398,12 @@ func initializeStateFromValidatorSet(t *testing.T, valSet *types.ValidatorSet, h
|
||||
NextValidators: valSet.CopyIncrementProposerPriority(1),
|
||||
LastValidators: valSet,
|
||||
LastHeightValidatorsChanged: 1,
|
||||
ConsensusParams: tmproto.ConsensusParams{
|
||||
Block: tmproto.BlockParams{
|
||||
ConsensusParams: types.ConsensusParams{
|
||||
Block: types.BlockParams{
|
||||
MaxBytes: 22020096,
|
||||
MaxGas: -1,
|
||||
},
|
||||
Evidence: tmproto.EvidenceParams{
|
||||
Evidence: types.EvidenceParams{
|
||||
MaxAgeNumBlocks: 20,
|
||||
MaxAgeDuration: 20 * time.Minute,
|
||||
MaxBytes: 1000,
|
||||
@@ -444,7 +443,7 @@ func initializeBlockStore(db dbm.DB, state sm.State, valAddr []byte) *store.Bloc
|
||||
block, _ := state.MakeBlock(i, []types.Tx{}, lastCommit, nil,
|
||||
state.Validators.GetProposer().Address)
|
||||
block.Header.Time = defaultEvidenceTime.Add(time.Duration(i) * time.Minute)
|
||||
block.Header.Version = tmversion.Consensus{Block: version.BlockProtocol, App: 1}
|
||||
block.Header.Version = version.Consensus{Block: version.BlockProtocol, App: 1}
|
||||
const parts = 1
|
||||
partSet := block.MakePartSet(parts)
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/tendermint/tendermint/evidence/mocks"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
smmocks "github.com/tendermint/tendermint/state/mocks"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
@@ -410,7 +409,7 @@ func makeVote(
|
||||
|
||||
func makeHeaderRandom(height int64) *types.Header {
|
||||
return &types.Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol, App: 1},
|
||||
Version: version.Consensus{Block: version.BlockProtocol, App: 1},
|
||||
ChainID: evidenceChainID,
|
||||
Height: height,
|
||||
Time: defaultEvidenceTime,
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
@@ -125,7 +124,7 @@ func genHeader(chainID string, height int64, bTime time.Time, txs types.Txs,
|
||||
valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte) *types.Header {
|
||||
|
||||
return &types.Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol, App: 0},
|
||||
Version: version.Consensus{Block: version.BlockProtocol, App: 0},
|
||||
ChainID: chainID,
|
||||
Height: height,
|
||||
Time: bTime,
|
||||
|
||||
@@ -205,7 +205,7 @@ func (c *Client) ConsensusParams(ctx context.Context, height *int64) (*ctypes.Re
|
||||
}
|
||||
|
||||
// Validate res.
|
||||
if err := types.ValidateConsensusParams(res.ConsensusParams); err != nil {
|
||||
if err := res.ConsensusParams.ValidateConsensusParams(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.BlockHeight <= 0 {
|
||||
@@ -219,7 +219,7 @@ func (c *Client) ConsensusParams(ctx context.Context, height *int64) (*ctypes.Re
|
||||
}
|
||||
|
||||
// Verify hash.
|
||||
if cH, tH := types.HashConsensusParams(res.ConsensusParams), l.ConsensusHash; !bytes.Equal(cH, tH) {
|
||||
if cH, tH := res.ConsensusParams.HashConsensusParams(), l.ConsensusHash; !bytes.Equal(cH, tH) {
|
||||
return nil, fmt.Errorf("params hash %X does not match trusted hash %X",
|
||||
cH, tH)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
)
|
||||
@@ -188,7 +187,7 @@ func randLightBlock(height int64) *types.LightBlock {
|
||||
return &types.LightBlock{
|
||||
SignedHeader: &types.SignedHeader{
|
||||
Header: &types.Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol, App: 0},
|
||||
Version: version.Consensus{Block: version.BlockProtocol, App: 0},
|
||||
ChainID: tmrand.Str(12),
|
||||
Height: height,
|
||||
Time: time.Now(),
|
||||
|
||||
@@ -102,7 +102,8 @@ func ConsensusParams(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultCon
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params := types.ConsensusParamsFromProto(consensusParams)
|
||||
return &ctypes.ResultConsensusParams{
|
||||
BlockHeight: height,
|
||||
ConsensusParams: consensusParams}, nil
|
||||
ConsensusParams: params}, nil
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/libs/bytes"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
@@ -134,8 +133,8 @@ type ResultValidators struct {
|
||||
|
||||
// ConsensusParams for given height
|
||||
type ResultConsensusParams struct {
|
||||
BlockHeight int64 `json:"block_height"`
|
||||
ConsensusParams tmproto.ConsensusParams `json:"consensus_params"`
|
||||
BlockHeight int64 `json:"block_height"`
|
||||
ConsensusParams types.ConsensusParams `json:"consensus_params"`
|
||||
}
|
||||
|
||||
// Info about the consensus state.
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
mempl "github.com/tendermint/tendermint/mempool"
|
||||
tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
"github.com/tendermint/tendermint/proxy"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
@@ -378,7 +377,7 @@ func getBeginBlockValidatorInfo(block *types.Block, store Store,
|
||||
}
|
||||
|
||||
func validateValidatorUpdates(abciUpdates []abci.ValidatorUpdate,
|
||||
params tmproto.ValidatorParams) error {
|
||||
params types.ValidatorParams) error {
|
||||
for _, valUpdate := range abciUpdates {
|
||||
if valUpdate.GetPower() < 0 {
|
||||
return fmt.Errorf("voting power can't be negative %v", valUpdate)
|
||||
@@ -394,7 +393,7 @@ func validateValidatorUpdates(abciUpdates []abci.ValidatorUpdate,
|
||||
return err
|
||||
}
|
||||
|
||||
if !types.IsValidPubkeyType(params, pk.Type()) {
|
||||
if !params.IsValidPubkeyType(pk.Type()) {
|
||||
return fmt.Errorf("validator %v is using pubkey %s, which is unsupported for consensus",
|
||||
valUpdate, pk.Type())
|
||||
}
|
||||
@@ -434,8 +433,8 @@ func updateState(
|
||||
lastHeightParamsChanged := state.LastHeightConsensusParamsChanged
|
||||
if abciResponses.EndBlock.ConsensusParamUpdates != nil {
|
||||
// NOTE: must not mutate s.ConsensusParams
|
||||
nextParams = types.UpdateConsensusParams(state.ConsensusParams, abciResponses.EndBlock.ConsensusParamUpdates)
|
||||
err := types.ValidateConsensusParams(nextParams)
|
||||
nextParams = state.ConsensusParams.UpdateConsensusParams(abciResponses.EndBlock.ConsensusParamUpdates)
|
||||
err := nextParams.ValidateConsensusParams()
|
||||
if err != nil {
|
||||
return state, fmt.Errorf("error updating consensus params: %v", err)
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
mmock "github.com/tendermint/tendermint/mempool/mock"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
"github.com/tendermint/tendermint/proxy"
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
"github.com/tendermint/tendermint/state/mocks"
|
||||
@@ -136,7 +134,7 @@ func TestBeginBlockByzantineValidators(t *testing.T) {
|
||||
privVal := privVals[state.Validators.Validators[0].Address.String()]
|
||||
blockID := makeBlockID([]byte("headerhash"), 1000, []byte("partshash"))
|
||||
header := &types.Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol, App: 1},
|
||||
Version: version.Consensus{Block: version.BlockProtocol, App: 1},
|
||||
ChainID: state.ChainID,
|
||||
Height: 10,
|
||||
Time: defaultEvidenceTime,
|
||||
@@ -222,13 +220,13 @@ func TestValidateValidatorUpdates(t *testing.T) {
|
||||
pk2, err := cryptoenc.PubKeyToProto(pubkey2)
|
||||
assert.NoError(t, err)
|
||||
|
||||
defaultValidatorParams := tmproto.ValidatorParams{PubKeyTypes: []string{types.ABCIPubKeyTypeEd25519}}
|
||||
defaultValidatorParams := types.ValidatorParams{PubKeyTypes: []string{types.ABCIPubKeyTypeEd25519}}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
|
||||
abciUpdates []abci.ValidatorUpdate
|
||||
validatorParams tmproto.ValidatorParams
|
||||
validatorParams types.ValidatorParams
|
||||
|
||||
shouldErr bool
|
||||
}{
|
||||
|
||||
@@ -3,7 +3,6 @@ package state
|
||||
import (
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
@@ -32,6 +31,6 @@ func UpdateState(
|
||||
|
||||
// ValidateValidatorUpdates is an alias for validateValidatorUpdates exported
|
||||
// from execution.go, exclusively and explicitly for testing.
|
||||
func ValidateValidatorUpdates(abciUpdates []abci.ValidatorUpdate, params tmproto.ValidatorParams) error {
|
||||
func ValidateValidatorUpdates(abciUpdates []abci.ValidatorUpdate, params types.ValidatorParams) error {
|
||||
return validateValidatorUpdates(abciUpdates, params)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
|
||||
type paramsChangeTestCase struct {
|
||||
height int64
|
||||
params tmproto.ConsensusParams
|
||||
params types.ConsensusParams
|
||||
}
|
||||
|
||||
func newTestApp() proxy.AppConns {
|
||||
@@ -200,13 +200,13 @@ func makeHeaderPartsResponsesValPowerChange(
|
||||
|
||||
func makeHeaderPartsResponsesParams(
|
||||
state sm.State,
|
||||
params tmproto.ConsensusParams,
|
||||
params *types.ConsensusParams,
|
||||
) (types.Header, types.BlockID, *tmstate.ABCIResponses) {
|
||||
|
||||
block := makeBlock(state, state.LastBlockHeight+1)
|
||||
abciResponses := &tmstate.ABCIResponses{
|
||||
BeginBlock: &abci.ResponseBeginBlock{},
|
||||
EndBlock: &abci.ResponseEndBlock{ConsensusParamUpdates: types.TM2PB.ConsensusParams(¶ms)},
|
||||
EndBlock: &abci.ResponseEndBlock{ConsensusParamUpdates: types.TM2PB.ConsensusParams(params)},
|
||||
}
|
||||
return block.Header, types.BlockID{Hash: block.Hash(), PartSetHeader: types.PartSetHeader{}}, abciResponses
|
||||
}
|
||||
@@ -245,7 +245,7 @@ func makeRandomStateFromValidatorSet(
|
||||
}
|
||||
}
|
||||
|
||||
func makeRandomStateFromConsensusParams(consensusParams *tmproto.ConsensusParams,
|
||||
func makeRandomStateFromConsensusParams(consensusParams *types.ConsensusParams,
|
||||
height, lastHeightConsensusParamsChanged int64) sm.State {
|
||||
val, _ := types.RandValidator(true, 10)
|
||||
valSet := types.NewValidatorSet([]*types.Validator{val})
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
@@ -24,18 +23,43 @@ var (
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type Version struct {
|
||||
Consensus version.Consensus ` json:"consensus"`
|
||||
Software string ` json:"software"`
|
||||
}
|
||||
|
||||
// InitStateVersion sets the Consensus.Block and Software versions,
|
||||
// but leaves the Consensus.App version blank.
|
||||
// The Consensus.App version will be set during the Handshake, once
|
||||
// we hear from the app what protocol version it is running.
|
||||
var InitStateVersion = tmstate.Version{
|
||||
Consensus: tmversion.Consensus{
|
||||
var InitStateVersion = Version{
|
||||
Consensus: version.Consensus{
|
||||
Block: version.BlockProtocol,
|
||||
App: 0,
|
||||
},
|
||||
Software: version.TMCoreSemVer,
|
||||
}
|
||||
|
||||
func (v *Version) ToProto() tmstate.Version {
|
||||
return tmstate.Version{
|
||||
Consensus: tmversion.Consensus{
|
||||
Block: v.Consensus.Block,
|
||||
App: v.Consensus.App,
|
||||
},
|
||||
Software: v.Software,
|
||||
}
|
||||
}
|
||||
|
||||
func VersionFromProto(v tmstate.Version) Version {
|
||||
return Version{
|
||||
Consensus: version.Consensus{
|
||||
Block: v.Consensus.Block,
|
||||
App: v.Consensus.App,
|
||||
},
|
||||
Software: v.Software,
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// State is a short description of the latest committed block of the Tendermint consensus.
|
||||
@@ -46,7 +70,7 @@ var InitStateVersion = tmstate.Version{
|
||||
// Instead, use state.Copy() or state.NextState(...).
|
||||
// NOTE: not goroutine-safe.
|
||||
type State struct {
|
||||
Version tmstate.Version
|
||||
Version Version
|
||||
|
||||
// immutable
|
||||
ChainID string
|
||||
@@ -70,7 +94,7 @@ type State struct {
|
||||
|
||||
// Consensus parameters used for validating blocks.
|
||||
// Changes returned by EndBlock and updated after Commit.
|
||||
ConsensusParams tmproto.ConsensusParams
|
||||
ConsensusParams types.ConsensusParams
|
||||
LastHeightConsensusParamsChanged int64
|
||||
|
||||
// Merkle root of the results from executing prev block
|
||||
@@ -139,7 +163,7 @@ func (state *State) ToProto() (*tmstate.State, error) {
|
||||
|
||||
sm := new(tmstate.State)
|
||||
|
||||
sm.Version = state.Version
|
||||
sm.Version = state.Version.ToProto()
|
||||
sm.ChainID = state.ChainID
|
||||
sm.InitialHeight = state.InitialHeight
|
||||
sm.LastBlockHeight = state.LastBlockHeight
|
||||
@@ -167,7 +191,7 @@ func (state *State) ToProto() (*tmstate.State, error) {
|
||||
}
|
||||
|
||||
sm.LastHeightValidatorsChanged = state.LastHeightValidatorsChanged
|
||||
sm.ConsensusParams = state.ConsensusParams
|
||||
sm.ConsensusParams = state.ConsensusParams.ToProto()
|
||||
sm.LastHeightConsensusParamsChanged = state.LastHeightConsensusParamsChanged
|
||||
sm.LastResultsHash = state.LastResultsHash
|
||||
sm.AppHash = state.AppHash
|
||||
@@ -183,7 +207,7 @@ func StateFromProto(pb *tmstate.State) (*State, error) { //nolint:golint
|
||||
|
||||
state := new(State)
|
||||
|
||||
state.Version = pb.Version
|
||||
state.Version = VersionFromProto(pb.Version)
|
||||
state.ChainID = pb.ChainID
|
||||
state.InitialHeight = pb.InitialHeight
|
||||
|
||||
@@ -218,7 +242,7 @@ func StateFromProto(pb *tmstate.State) (*State, error) { //nolint:golint
|
||||
}
|
||||
|
||||
state.LastHeightValidatorsChanged = pb.LastHeightValidatorsChanged
|
||||
state.ConsensusParams = pb.ConsensusParams
|
||||
state.ConsensusParams = types.ConsensusParamsFromProto(pb.ConsensusParams)
|
||||
state.LastHeightConsensusParamsChanged = pb.LastHeightConsensusParamsChanged
|
||||
state.LastResultsHash = pb.LastResultsHash
|
||||
state.AppHash = pb.AppHash
|
||||
@@ -256,7 +280,7 @@ func (state State) MakeBlock(
|
||||
state.Version.Consensus, state.ChainID,
|
||||
timestamp, state.LastBlockID,
|
||||
state.Validators.Hash(), state.NextValidators.Hash(),
|
||||
types.HashConsensusParams(state.ConsensusParams), state.AppHash, state.LastResultsHash,
|
||||
state.ConsensusParams.HashConsensusParams(), state.AppHash, state.LastResultsHash,
|
||||
proposerAddress,
|
||||
)
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
cryptoenc "github.com/tendermint/tendermint/crypto/encoding"
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
@@ -998,7 +997,7 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) {
|
||||
|
||||
// Each valset is just one validator.
|
||||
// create list of them.
|
||||
params := make([]tmproto.ConsensusParams, N+1)
|
||||
params := make([]types.ConsensusParams, N+1)
|
||||
params[0] = state.ConsensusParams
|
||||
for i := 1; i < N+1; i++ {
|
||||
params[i] = *types.DefaultConsensusParams()
|
||||
@@ -1019,7 +1018,7 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) {
|
||||
changeIndex++
|
||||
cp = params[changeIndex]
|
||||
}
|
||||
header, blockID, responses := makeHeaderPartsResponsesParams(state, cp)
|
||||
header, blockID, responses := makeHeaderPartsResponsesParams(state, &cp)
|
||||
validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.EndBlock.ValidatorUpdates)
|
||||
require.NoError(t, err)
|
||||
state, err = sm.UpdateState(state, blockID, &header, responses, validatorUpdates)
|
||||
|
||||
@@ -617,13 +617,13 @@ func (store dbStore) loadConsensusParamsInfo(height int64) (*tmstate.ConsensusPa
|
||||
// It should be called from s.Save(), right before the state itself is persisted.
|
||||
// If the consensus params did not change after processing the latest block,
|
||||
// only the last height for which they changed is persisted.
|
||||
func (store dbStore) saveConsensusParamsInfo(nextHeight, changeHeight int64, params tmproto.ConsensusParams) error {
|
||||
func (store dbStore) saveConsensusParamsInfo(nextHeight, changeHeight int64, params types.ConsensusParams) error {
|
||||
paramsInfo := &tmstate.ConsensusParamsInfo{
|
||||
LastHeightChanged: changeHeight,
|
||||
}
|
||||
|
||||
if changeHeight == nextHeight {
|
||||
paramsInfo.ConsensusParams = params
|
||||
paramsInfo.ConsensusParams = params.ToProto()
|
||||
}
|
||||
bz, err := paramsInfo.Marshal()
|
||||
if err != nil {
|
||||
|
||||
@@ -142,8 +142,9 @@ func TestStoreLoadConsensusParams(t *testing.T) {
|
||||
stateStore := sm.NewStore(stateDB)
|
||||
err := stateStore.Save(makeRandomStateFromConsensusParams(types.DefaultConsensusParams(), 1, 1))
|
||||
require.NoError(t, err)
|
||||
params, err := stateStore.LoadConsensusParams(1)
|
||||
pbParams, err := stateStore.LoadConsensusParams(1)
|
||||
require.NoError(t, err)
|
||||
params := types.ConsensusParamsFromProto(pbParams)
|
||||
require.Equal(t, types.DefaultConsensusParams(), ¶ms)
|
||||
|
||||
// we give the state store different params but say that the height hasn't changed, hence
|
||||
@@ -152,7 +153,8 @@ func TestStoreLoadConsensusParams(t *testing.T) {
|
||||
differentParams.Block.MaxBytes = 20000
|
||||
err = stateStore.Save(makeRandomStateFromConsensusParams(differentParams, 10, 1))
|
||||
require.NoError(t, err)
|
||||
res, err := stateStore.LoadConsensusParams(10)
|
||||
pbRes, err := stateStore.LoadConsensusParams(10)
|
||||
res := types.ConsensusParamsFromProto(pbRes)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, res, params)
|
||||
require.NotEqual(t, res, differentParams)
|
||||
@@ -206,8 +208,8 @@ func TestPruneStates(t *testing.T) {
|
||||
LastBlockHeight: h - 1,
|
||||
Validators: validatorSet,
|
||||
NextValidators: validatorSet,
|
||||
ConsensusParams: tmproto.ConsensusParams{
|
||||
Block: tmproto.BlockParams{MaxBytes: 10e6},
|
||||
ConsensusParams: types.ConsensusParams{
|
||||
Block: types.BlockParams{MaxBytes: 10e6},
|
||||
},
|
||||
LastHeightValidatorsChanged: valsChanged,
|
||||
LastHeightConsensusParamsChanged: paramsChanged,
|
||||
|
||||
@@ -56,7 +56,7 @@ func validateBlock(state State, block *types.Block) error {
|
||||
block.AppHash,
|
||||
)
|
||||
}
|
||||
hashCP := types.HashConsensusParams(state.ConsensusParams)
|
||||
hashCP := state.ConsensusParams.HashConsensusParams()
|
||||
if !bytes.Equal(block.ConsensusHash, hashCP) {
|
||||
return fmt.Errorf("wrong Block.Header.ConsensusHash. Expected %X, got %v",
|
||||
hashCP,
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
lighthttp "github.com/tendermint/tendermint/light/provider/http"
|
||||
lightrpc "github.com/tendermint/tendermint/light/rpc"
|
||||
lightdb "github.com/tendermint/tendermint/light/store/db"
|
||||
tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
|
||||
rpchttp "github.com/tendermint/tendermint/rpc/client/http"
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
@@ -38,7 +37,7 @@ type StateProvider interface {
|
||||
type lightClientStateProvider struct {
|
||||
tmsync.Mutex // light.Client is not concurrency-safe
|
||||
lc *light.Client
|
||||
version tmstate.Version
|
||||
version sm.Version
|
||||
initialHeight int64
|
||||
providers map[lightprovider.Provider]string
|
||||
}
|
||||
@@ -47,7 +46,7 @@ type lightClientStateProvider struct {
|
||||
func NewLightClientStateProvider(
|
||||
ctx context.Context,
|
||||
chainID string,
|
||||
version tmstate.Version,
|
||||
version sm.Version,
|
||||
initialHeight int64,
|
||||
servers []string,
|
||||
trustOptions light.TrustOptions,
|
||||
|
||||
@@ -14,9 +14,7 @@ import (
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmsync "github.com/tendermint/tendermint/libs/sync"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
|
||||
ssproto "github.com/tendermint/tendermint/proto/tendermint/statesync"
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
"github.com/tendermint/tendermint/proxy"
|
||||
proxymocks "github.com/tendermint/tendermint/proxy/mocks"
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
@@ -30,8 +28,8 @@ var ctx = context.Background()
|
||||
func TestSyncer_SyncAny(t *testing.T) {
|
||||
state := sm.State{
|
||||
ChainID: "chain",
|
||||
Version: tmstate.Version{
|
||||
Consensus: tmversion.Consensus{
|
||||
Version: sm.Version{
|
||||
Consensus: version.Consensus{
|
||||
Block: version.BlockProtocol,
|
||||
App: 0,
|
||||
},
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
@@ -122,7 +121,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
|
||||
header1 := types.Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
Height: 1,
|
||||
ChainID: "block_test",
|
||||
Time: tmtime.Now(),
|
||||
@@ -158,7 +157,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) {
|
||||
{
|
||||
block: newBlock( // New block at height 5 in empty block store is fine
|
||||
types.Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
Height: 5,
|
||||
ChainID: "block_test",
|
||||
Time: tmtime.Now(),
|
||||
@@ -461,7 +460,7 @@ func TestLoadBlockMeta(t *testing.T) {
|
||||
|
||||
// 3. A good blockMeta serialized and saved to the DB should be retrievable
|
||||
meta := &types.BlockMeta{Header: types.Header{
|
||||
Version: tmversion.Consensus{
|
||||
Version: version.Consensus{
|
||||
Block: version.BlockProtocol, App: 0}, Height: 1, ProposerAddress: tmrand.Bytes(crypto.AddressSize)}}
|
||||
pbm := meta.ToProto()
|
||||
err = db.Set(blockMetaKey(height), mustEncode(pbm))
|
||||
|
||||
@@ -345,7 +345,7 @@ func (h *Handshaker) ReplayBlocks(
|
||||
}
|
||||
|
||||
if res.ConsensusParams != nil {
|
||||
state.ConsensusParams = types.UpdateConsensusParams(state.ConsensusParams, res.ConsensusParams)
|
||||
state.ConsensusParams = state.ConsensusParams.UpdateConsensusParams(res.ConsensusParams)
|
||||
state.Version.Consensus.App = state.ConsensusParams.Version.AppVersion
|
||||
}
|
||||
// We update the last results hash with the empty hash, to conform with RFC-6962.
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
tmos "github.com/tendermint/tendermint/libs/os"
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
cs "github.com/tendermint/tendermint/test/maverick/consensus"
|
||||
nd "github.com/tendermint/tendermint/test/maverick/node"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
@@ -212,7 +211,7 @@ func initFilesWithConfig(config *cfg.Config) error {
|
||||
ConsensusParams: types.DefaultConsensusParams(),
|
||||
}
|
||||
if keyType == "secp256k1" {
|
||||
genDoc.ConsensusParams.Validator = tmproto.ValidatorParams{
|
||||
genDoc.ConsensusParams.Validator = types.ValidatorParams{
|
||||
PubKeyTypes: []string{types.ABCIPubKeyTypeSecp256k1},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
tmmath "github.com/tendermint/tendermint/libs/math"
|
||||
tmsync "github.com/tendermint/tendermint/libs/sync"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
)
|
||||
|
||||
@@ -311,7 +310,7 @@ func MaxDataBytesNoEvidence(maxBytes int64, valsCount int) int64 {
|
||||
func MakeBlock(height int64, txs []Tx, lastCommit *Commit, evidence []Evidence) *Block {
|
||||
block := &Block{
|
||||
Header: Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol, App: 0},
|
||||
Version: version.Consensus{Block: version.BlockProtocol, App: 0},
|
||||
Height: height,
|
||||
},
|
||||
Data: Data{
|
||||
@@ -333,10 +332,10 @@ func MakeBlock(height int64, txs []Tx, lastCommit *Commit, evidence []Evidence)
|
||||
// - https://github.com/tendermint/spec/blob/master/spec/blockchain/blockchain.md
|
||||
type Header struct {
|
||||
// basic block info
|
||||
Version tmversion.Consensus `json:"version"`
|
||||
ChainID string `json:"chain_id"`
|
||||
Height int64 `json:"height"`
|
||||
Time time.Time `json:"time"`
|
||||
Version version.Consensus `json:"version"`
|
||||
ChainID string `json:"chain_id"`
|
||||
Height int64 `json:"height"`
|
||||
Time time.Time `json:"time"`
|
||||
|
||||
// prev block info
|
||||
LastBlockID BlockID `json:"last_block_id"`
|
||||
@@ -361,7 +360,7 @@ type Header struct {
|
||||
// Populate the Header with state-derived data.
|
||||
// Call this after MakeBlock to complete the Header.
|
||||
func (h *Header) Populate(
|
||||
version tmversion.Consensus, chainID string,
|
||||
version version.Consensus, chainID string,
|
||||
timestamp time.Time, lastBlockID BlockID,
|
||||
valHash, nextValHash []byte,
|
||||
consensusHash, appHash, lastResultsHash []byte,
|
||||
@@ -449,7 +448,8 @@ func (h *Header) Hash() tmbytes.HexBytes {
|
||||
if h == nil || len(h.ValidatorsHash) == 0 {
|
||||
return nil
|
||||
}
|
||||
hbz, err := h.Version.Marshal()
|
||||
hpb := h.Version.ToProto()
|
||||
hbz, err := hpb.Marshal()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -527,7 +527,7 @@ func (h *Header) ToProto() *tmproto.Header {
|
||||
}
|
||||
|
||||
return &tmproto.Header{
|
||||
Version: h.Version,
|
||||
Version: h.Version.ToProto(),
|
||||
ChainID: h.ChainID,
|
||||
Height: h.Height,
|
||||
Time: h.Time,
|
||||
@@ -558,7 +558,7 @@ func HeaderFromProto(ph *tmproto.Header) (Header, error) {
|
||||
return Header{}, err
|
||||
}
|
||||
|
||||
h.Version = ph.Version
|
||||
h.Version = version.Consensus{Block: ph.Version.Block, App: ph.Version.App}
|
||||
h.ChainID = ph.ChainID
|
||||
h.Height = ph.Height
|
||||
h.Time = ph.Time
|
||||
|
||||
@@ -320,7 +320,7 @@ func TestHeaderHash(t *testing.T) {
|
||||
expectHash bytes.HexBytes
|
||||
}{
|
||||
{"Generates expected hash", &Header{
|
||||
Version: tmversion.Consensus{Block: 1, App: 2},
|
||||
Version: version.Consensus{Block: 1, App: 2},
|
||||
ChainID: "chainId",
|
||||
Height: 3,
|
||||
Time: time.Date(2019, 10, 13, 16, 14, 44, 0, time.UTC),
|
||||
@@ -337,7 +337,7 @@ func TestHeaderHash(t *testing.T) {
|
||||
}, hexBytesFromString("F740121F553B5418C3EFBD343C2DBFE9E007BB67B0D020A0741374BAB65242A4")},
|
||||
{"nil header yields nil", nil, nil},
|
||||
{"nil ValidatorsHash yields nil", &Header{
|
||||
Version: tmversion.Consensus{Block: 1, App: 2},
|
||||
Version: version.Consensus{Block: 1, App: 2},
|
||||
ChainID: "chainId",
|
||||
Height: 3,
|
||||
Time: time.Date(2019, 10, 13, 16, 14, 44, 0, time.UTC),
|
||||
@@ -377,8 +377,12 @@ func TestHeaderHash(t *testing.T) {
|
||||
bz, err := gogotypes.StdTimeMarshal(f)
|
||||
require.NoError(t, err)
|
||||
byteSlices = append(byteSlices, bz)
|
||||
case tmversion.Consensus:
|
||||
bz, err := f.Marshal()
|
||||
case version.Consensus:
|
||||
pbc := tmversion.Consensus{
|
||||
Block: f.Block,
|
||||
App: f.App,
|
||||
}
|
||||
bz, err := pbc.Marshal()
|
||||
require.NoError(t, err)
|
||||
byteSlices = append(byteSlices, bz)
|
||||
case BlockID:
|
||||
@@ -412,7 +416,7 @@ func TestMaxHeaderBytes(t *testing.T) {
|
||||
timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
|
||||
|
||||
h := Header{
|
||||
Version: tmversion.Consensus{Block: math.MaxInt64, App: math.MaxInt64},
|
||||
Version: version.Consensus{Block: math.MaxInt64, App: math.MaxInt64},
|
||||
ChainID: maxChainID,
|
||||
Height: math.MaxInt64,
|
||||
Time: timestamp,
|
||||
@@ -750,7 +754,7 @@ func makeRandHeader() Header {
|
||||
randBytes := tmrand.Bytes(tmhash.Size)
|
||||
randAddress := tmrand.Bytes(crypto.AddressSize)
|
||||
h := Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol, App: 1},
|
||||
Version: version.Consensus{Block: version.BlockProtocol, App: 1},
|
||||
ChainID: chainID,
|
||||
Height: height,
|
||||
Time: t,
|
||||
@@ -956,13 +960,13 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
"invalid version block",
|
||||
Header{Version: tmversion.Consensus{Block: version.BlockProtocol + 1}},
|
||||
Header{Version: version.Consensus{Block: version.BlockProtocol + 1}},
|
||||
true, "block protocol is incorrect",
|
||||
},
|
||||
{
|
||||
"invalid chain ID length",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen+1)),
|
||||
},
|
||||
true, "chainID is too long",
|
||||
@@ -970,7 +974,7 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
{
|
||||
"invalid height (negative)",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen)),
|
||||
Height: -1,
|
||||
},
|
||||
@@ -979,7 +983,7 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
{
|
||||
"invalid height (zero)",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen)),
|
||||
Height: 0,
|
||||
},
|
||||
@@ -988,7 +992,7 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
{
|
||||
"invalid block ID hash",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen)),
|
||||
Height: 1,
|
||||
LastBlockID: BlockID{
|
||||
@@ -1000,7 +1004,7 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
{
|
||||
"invalid block ID parts header hash",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen)),
|
||||
Height: 1,
|
||||
LastBlockID: BlockID{
|
||||
@@ -1015,7 +1019,7 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
{
|
||||
"invalid last commit hash",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen)),
|
||||
Height: 1,
|
||||
LastBlockID: BlockID{
|
||||
@@ -1031,7 +1035,7 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
{
|
||||
"invalid data hash",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen)),
|
||||
Height: 1,
|
||||
LastBlockID: BlockID{
|
||||
@@ -1048,7 +1052,7 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
{
|
||||
"invalid evidence hash",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen)),
|
||||
Height: 1,
|
||||
LastBlockID: BlockID{
|
||||
@@ -1066,7 +1070,7 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
{
|
||||
"invalid proposer address",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen)),
|
||||
Height: 1,
|
||||
LastBlockID: BlockID{
|
||||
@@ -1085,7 +1089,7 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
{
|
||||
"invalid validator hash",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen)),
|
||||
Height: 1,
|
||||
LastBlockID: BlockID{
|
||||
@@ -1105,7 +1109,7 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
{
|
||||
"invalid next validator hash",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen)),
|
||||
Height: 1,
|
||||
LastBlockID: BlockID{
|
||||
@@ -1126,7 +1130,7 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
{
|
||||
"invalid consensus hash",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen)),
|
||||
Height: 1,
|
||||
LastBlockID: BlockID{
|
||||
@@ -1148,7 +1152,7 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
{
|
||||
"invalid last results hash",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen)),
|
||||
Height: 1,
|
||||
LastBlockID: BlockID{
|
||||
@@ -1171,7 +1175,7 @@ func TestHeader_ValidateBasic(t *testing.T) {
|
||||
{
|
||||
"valid header",
|
||||
Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol},
|
||||
Version: version.Consensus{Block: version.BlockProtocol},
|
||||
ChainID: string(make([]byte, MaxChainIDLen)),
|
||||
Height: 1,
|
||||
LastBlockID: BlockID{
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
)
|
||||
|
||||
@@ -244,7 +243,7 @@ func makeVote(
|
||||
|
||||
func makeHeaderRandom() *Header {
|
||||
return &Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol, App: 1},
|
||||
Version: version.Consensus{Block: version.BlockProtocol, App: 1},
|
||||
ChainID: tmrand.Str(12),
|
||||
Height: int64(tmrand.Uint16()) + 1,
|
||||
Time: time.Now(),
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
tmbytes "github.com/tendermint/tendermint/libs/bytes"
|
||||
tmjson "github.com/tendermint/tendermint/libs/json"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
)
|
||||
|
||||
@@ -36,13 +35,13 @@ type GenesisValidator struct {
|
||||
|
||||
// GenesisDoc defines the initial conditions for a tendermint blockchain, in particular its validator set.
|
||||
type GenesisDoc struct {
|
||||
GenesisTime time.Time `json:"genesis_time"`
|
||||
ChainID string `json:"chain_id"`
|
||||
InitialHeight int64 `json:"initial_height"`
|
||||
ConsensusParams *tmproto.ConsensusParams `json:"consensus_params,omitempty"`
|
||||
Validators []GenesisValidator `json:"validators,omitempty"`
|
||||
AppHash tmbytes.HexBytes `json:"app_hash"`
|
||||
AppState json.RawMessage `json:"app_state,omitempty"`
|
||||
GenesisTime time.Time `json:"genesis_time"`
|
||||
ChainID string `json:"chain_id"`
|
||||
InitialHeight int64 `json:"initial_height"`
|
||||
ConsensusParams *ConsensusParams `json:"consensus_params,omitempty"`
|
||||
Validators []GenesisValidator `json:"validators,omitempty"`
|
||||
AppHash tmbytes.HexBytes `json:"app_hash"`
|
||||
AppState json.RawMessage `json:"app_state,omitempty"`
|
||||
}
|
||||
|
||||
// SaveAs is a utility method for saving GenensisDoc as a JSON file.
|
||||
@@ -83,7 +82,7 @@ func (genDoc *GenesisDoc) ValidateAndComplete() error {
|
||||
|
||||
if genDoc.ConsensusParams == nil {
|
||||
genDoc.ConsensusParams = DefaultConsensusParams()
|
||||
} else if err := ValidateConsensusParams(*genDoc.ConsensusParams); err != nil {
|
||||
} else if err := genDoc.ConsensusParams.ValidateConsensusParams(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
)
|
||||
|
||||
@@ -115,7 +114,7 @@ func TestSignedHeaderValidateBasic(t *testing.T) {
|
||||
chainID := "𠜎"
|
||||
timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
|
||||
h := Header{
|
||||
Version: tmversion.Consensus{Block: version.BlockProtocol, App: math.MaxInt64},
|
||||
Version: version.Consensus{Block: version.BlockProtocol, App: math.MaxInt64},
|
||||
ChainID: chainID,
|
||||
Height: commit.Height,
|
||||
Time: timestamp,
|
||||
|
||||
118
types/params.go
118
types/params.go
@@ -21,9 +21,53 @@ const (
|
||||
MaxBlockPartsCount = (MaxBlockSizeBytes / BlockPartSizeBytes) + 1
|
||||
)
|
||||
|
||||
// ConsensusParams contains consensus critical parameters that determine the
|
||||
// validity of blocks.
|
||||
type ConsensusParams struct {
|
||||
Block BlockParams `json:"block"`
|
||||
Evidence EvidenceParams `json:"evidence"`
|
||||
Validator ValidatorParams `json:"validator"`
|
||||
Version VersionParams `json:"version"`
|
||||
}
|
||||
|
||||
// HashedParams is a subset of ConsensusParams.
|
||||
// It is amino encoded and hashed into
|
||||
// the Header.ConsensusHash.
|
||||
type HashedParams struct {
|
||||
BlockMaxBytes int64
|
||||
BlockMaxGas int64
|
||||
}
|
||||
|
||||
// BlockParams define limits on the block size and gas plus minimum time
|
||||
// between blocks.
|
||||
type BlockParams struct {
|
||||
MaxBytes int64 `json:"max_bytes"`
|
||||
MaxGas int64 `json:"max_gas"`
|
||||
// Minimum time increment between consecutive blocks (in milliseconds)
|
||||
// Not exposed to the application.
|
||||
TimeIotaMs int64 `json:"time_iota_ms"`
|
||||
}
|
||||
|
||||
// EvidenceParams determine how we handle evidence of malfeasance.
|
||||
type EvidenceParams struct {
|
||||
MaxAgeNumBlocks int64 `json:"max_age_num_blocks"` // only accept new evidence more recent than this
|
||||
MaxAgeDuration time.Duration `json:"max_age_duration"`
|
||||
MaxBytes int64 `json:"max_bytes"`
|
||||
}
|
||||
|
||||
// ValidatorParams restrict the public key types validators can use.
|
||||
// NOTE: uses ABCI pubkey naming, not Amino names.
|
||||
type ValidatorParams struct {
|
||||
PubKeyTypes []string `json:"pub_key_types"`
|
||||
}
|
||||
|
||||
type VersionParams struct {
|
||||
AppVersion uint64 `json:"app_version"`
|
||||
}
|
||||
|
||||
// DefaultConsensusParams returns a default ConsensusParams.
|
||||
func DefaultConsensusParams() *tmproto.ConsensusParams {
|
||||
return &tmproto.ConsensusParams{
|
||||
func DefaultConsensusParams() *ConsensusParams {
|
||||
return &ConsensusParams{
|
||||
Block: DefaultBlockParams(),
|
||||
Evidence: DefaultEvidenceParams(),
|
||||
Validator: DefaultValidatorParams(),
|
||||
@@ -32,8 +76,8 @@ func DefaultConsensusParams() *tmproto.ConsensusParams {
|
||||
}
|
||||
|
||||
// DefaultBlockParams returns a default BlockParams.
|
||||
func DefaultBlockParams() tmproto.BlockParams {
|
||||
return tmproto.BlockParams{
|
||||
func DefaultBlockParams() BlockParams {
|
||||
return BlockParams{
|
||||
MaxBytes: 22020096, // 21MB
|
||||
MaxGas: -1,
|
||||
TimeIotaMs: 1, // 1s, parameter is now unused
|
||||
@@ -41,8 +85,8 @@ func DefaultBlockParams() tmproto.BlockParams {
|
||||
}
|
||||
|
||||
// DefaultEvidenceParams returns a default EvidenceParams.
|
||||
func DefaultEvidenceParams() tmproto.EvidenceParams {
|
||||
return tmproto.EvidenceParams{
|
||||
func DefaultEvidenceParams() EvidenceParams {
|
||||
return EvidenceParams{
|
||||
MaxAgeNumBlocks: 100000, // 27.8 hrs at 1block/s
|
||||
MaxAgeDuration: 48 * time.Hour,
|
||||
MaxBytes: 1048576, // 1MB
|
||||
@@ -51,21 +95,21 @@ func DefaultEvidenceParams() tmproto.EvidenceParams {
|
||||
|
||||
// DefaultValidatorParams returns a default ValidatorParams, which allows
|
||||
// only ed25519 pubkeys.
|
||||
func DefaultValidatorParams() tmproto.ValidatorParams {
|
||||
return tmproto.ValidatorParams{
|
||||
func DefaultValidatorParams() ValidatorParams {
|
||||
return ValidatorParams{
|
||||
PubKeyTypes: []string{ABCIPubKeyTypeEd25519},
|
||||
}
|
||||
}
|
||||
|
||||
func DefaultVersionParams() tmproto.VersionParams {
|
||||
return tmproto.VersionParams{
|
||||
func DefaultVersionParams() VersionParams {
|
||||
return VersionParams{
|
||||
AppVersion: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func IsValidPubkeyType(params tmproto.ValidatorParams, pubkeyType string) bool {
|
||||
for i := 0; i < len(params.PubKeyTypes); i++ {
|
||||
if params.PubKeyTypes[i] == pubkeyType {
|
||||
func (val *ValidatorParams) IsValidPubkeyType(pubkeyType string) bool {
|
||||
for i := 0; i < len(val.PubKeyTypes); i++ {
|
||||
if val.PubKeyTypes[i] == pubkeyType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -74,7 +118,7 @@ func IsValidPubkeyType(params tmproto.ValidatorParams, pubkeyType string) bool {
|
||||
|
||||
// Validate validates the ConsensusParams to ensure all values are within their
|
||||
// allowed limits, and returns an error if they are not.
|
||||
func ValidateConsensusParams(params tmproto.ConsensusParams) error {
|
||||
func (params ConsensusParams) ValidateConsensusParams() error {
|
||||
if params.Block.MaxBytes <= 0 {
|
||||
return fmt.Errorf("block.MaxBytes must be greater than 0. Got %d",
|
||||
params.Block.MaxBytes)
|
||||
@@ -134,7 +178,7 @@ func ValidateConsensusParams(params tmproto.ConsensusParams) error {
|
||||
// Only the Block.MaxBytes and Block.MaxGas are included in the hash.
|
||||
// This allows the ConsensusParams to evolve more without breaking the block
|
||||
// protocol. No need for a Merkle tree here, just a small struct to hash.
|
||||
func HashConsensusParams(params tmproto.ConsensusParams) []byte {
|
||||
func (params ConsensusParams) HashConsensusParams() []byte {
|
||||
hasher := tmhash.New()
|
||||
|
||||
hp := tmproto.HashedParams{
|
||||
@@ -156,7 +200,7 @@ func HashConsensusParams(params tmproto.ConsensusParams) []byte {
|
||||
|
||||
// Update returns a copy of the params with updates from the non-zero fields of p2.
|
||||
// NOTE: note: must not modify the original
|
||||
func UpdateConsensusParams(params tmproto.ConsensusParams, params2 *abci.ConsensusParams) tmproto.ConsensusParams {
|
||||
func (params ConsensusParams) UpdateConsensusParams(params2 *abci.ConsensusParams) ConsensusParams {
|
||||
res := params // explicit copy
|
||||
|
||||
if params2 == nil {
|
||||
@@ -183,3 +227,45 @@ func UpdateConsensusParams(params tmproto.ConsensusParams, params2 *abci.Consens
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (params ConsensusParams) ToProto() tmproto.ConsensusParams {
|
||||
return tmproto.ConsensusParams{
|
||||
Block: tmproto.BlockParams{
|
||||
MaxBytes: params.Block.MaxBytes,
|
||||
MaxGas: params.Block.MaxGas,
|
||||
TimeIotaMs: params.Block.TimeIotaMs,
|
||||
},
|
||||
Evidence: tmproto.EvidenceParams{
|
||||
MaxAgeNumBlocks: params.Evidence.MaxAgeNumBlocks,
|
||||
MaxAgeDuration: params.Evidence.MaxAgeDuration,
|
||||
MaxBytes: params.Evidence.MaxBytes,
|
||||
},
|
||||
Validator: tmproto.ValidatorParams{
|
||||
PubKeyTypes: params.Validator.PubKeyTypes,
|
||||
},
|
||||
Version: tmproto.VersionParams{
|
||||
AppVersion: params.Version.AppVersion,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func ConsensusParamsFromProto(pbParams tmproto.ConsensusParams) ConsensusParams {
|
||||
return ConsensusParams{
|
||||
Block: BlockParams{
|
||||
MaxBytes: pbParams.Block.MaxBytes,
|
||||
MaxGas: pbParams.Block.MaxGas,
|
||||
TimeIotaMs: pbParams.Block.TimeIotaMs,
|
||||
},
|
||||
Evidence: EvidenceParams{
|
||||
MaxAgeNumBlocks: pbParams.Evidence.MaxAgeNumBlocks,
|
||||
MaxAgeDuration: pbParams.Evidence.MaxAgeDuration,
|
||||
MaxBytes: pbParams.Evidence.MaxBytes,
|
||||
},
|
||||
Validator: ValidatorParams{
|
||||
PubKeyTypes: pbParams.Validator.PubKeyTypes,
|
||||
},
|
||||
Version: VersionParams{
|
||||
AppVersion: pbParams.Version.AppVersion,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ var (
|
||||
|
||||
func TestConsensusParamsValidation(t *testing.T) {
|
||||
testCases := []struct {
|
||||
params tmproto.ConsensusParams
|
||||
params ConsensusParams
|
||||
valid bool
|
||||
}{
|
||||
// test block params
|
||||
@@ -44,9 +44,9 @@ func TestConsensusParamsValidation(t *testing.T) {
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
if tc.valid {
|
||||
assert.NoErrorf(t, ValidateConsensusParams(tc.params), "expected no error for valid params (#%d)", i)
|
||||
assert.NoErrorf(t, tc.params.ValidateConsensusParams(), "expected no error for valid params (#%d)", i)
|
||||
} else {
|
||||
assert.Errorf(t, ValidateConsensusParams(tc.params), "expected error for non valid params (#%d)", i)
|
||||
assert.Errorf(t, tc.params.ValidateConsensusParams(), "expected error for non valid params (#%d)", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,26 +57,26 @@ func makeParams(
|
||||
evidenceAge int64,
|
||||
maxEvidenceBytes int64,
|
||||
pubkeyTypes []string,
|
||||
) tmproto.ConsensusParams {
|
||||
return tmproto.ConsensusParams{
|
||||
Block: tmproto.BlockParams{
|
||||
) ConsensusParams {
|
||||
return ConsensusParams{
|
||||
Block: BlockParams{
|
||||
MaxBytes: blockBytes,
|
||||
MaxGas: blockGas,
|
||||
TimeIotaMs: blockTimeIotaMs,
|
||||
},
|
||||
Evidence: tmproto.EvidenceParams{
|
||||
Evidence: EvidenceParams{
|
||||
MaxAgeNumBlocks: evidenceAge,
|
||||
MaxAgeDuration: time.Duration(evidenceAge),
|
||||
MaxBytes: maxEvidenceBytes,
|
||||
},
|
||||
Validator: tmproto.ValidatorParams{
|
||||
Validator: ValidatorParams{
|
||||
PubKeyTypes: pubkeyTypes,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestConsensusParamsHash(t *testing.T) {
|
||||
params := []tmproto.ConsensusParams{
|
||||
params := []ConsensusParams{
|
||||
makeParams(4, 2, 10, 3, 1, valEd25519),
|
||||
makeParams(1, 4, 10, 3, 1, valEd25519),
|
||||
makeParams(1, 2, 10, 4, 1, valEd25519),
|
||||
@@ -89,7 +89,7 @@ func TestConsensusParamsHash(t *testing.T) {
|
||||
|
||||
hashes := make([][]byte, len(params))
|
||||
for i := range params {
|
||||
hashes[i] = HashConsensusParams(params[i])
|
||||
hashes[i] = params[i].HashConsensusParams()
|
||||
}
|
||||
|
||||
// make sure there are no duplicates...
|
||||
@@ -104,9 +104,9 @@ func TestConsensusParamsHash(t *testing.T) {
|
||||
|
||||
func TestConsensusParamsUpdate(t *testing.T) {
|
||||
testCases := []struct {
|
||||
params tmproto.ConsensusParams
|
||||
params ConsensusParams
|
||||
updates *abci.ConsensusParams
|
||||
updatedParams tmproto.ConsensusParams
|
||||
updatedParams ConsensusParams
|
||||
}{
|
||||
// empty updates
|
||||
{
|
||||
@@ -135,7 +135,7 @@ func TestConsensusParamsUpdate(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
assert.Equal(t, tc.updatedParams, UpdateConsensusParams(tc.params, tc.updates))
|
||||
assert.Equal(t, tc.updatedParams, tc.params.UpdateConsensusParams(tc.updates))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,8 +144,30 @@ func TestConsensusParamsUpdate_AppVersion(t *testing.T) {
|
||||
|
||||
assert.EqualValues(t, 0, params.Version.AppVersion)
|
||||
|
||||
updated := UpdateConsensusParams(params,
|
||||
updated := params.UpdateConsensusParams(
|
||||
&abci.ConsensusParams{Version: &tmproto.VersionParams{AppVersion: 1}})
|
||||
|
||||
assert.EqualValues(t, 1, updated.Version.AppVersion)
|
||||
}
|
||||
|
||||
func TestProto(t *testing.T) {
|
||||
params := []ConsensusParams{
|
||||
makeParams(4, 2, 10, 3, 1, valEd25519),
|
||||
makeParams(1, 4, 10, 3, 1, valEd25519),
|
||||
makeParams(1, 2, 10, 4, 1, valEd25519),
|
||||
makeParams(2, 5, 10, 7, 1, valEd25519),
|
||||
makeParams(1, 7, 10, 6, 1, valEd25519),
|
||||
makeParams(9, 5, 10, 4, 1, valEd25519),
|
||||
makeParams(7, 8, 10, 9, 1, valEd25519),
|
||||
makeParams(4, 6, 10, 5, 1, valEd25519),
|
||||
}
|
||||
|
||||
for i := range params {
|
||||
pbParams := params[i].ToProto()
|
||||
|
||||
oriParams := ConsensusParamsFromProto(pbParams)
|
||||
|
||||
assert.Equal(t, params[i], oriParams)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ type tm2pb struct{}
|
||||
|
||||
func (tm2pb) Header(header *Header) tmproto.Header {
|
||||
return tmproto.Header{
|
||||
Version: header.Version,
|
||||
Version: header.Version.ToProto(),
|
||||
ChainID: header.ChainID,
|
||||
Height: header.Height,
|
||||
Time: header.Time,
|
||||
@@ -97,14 +97,23 @@ func (tm2pb) ValidatorUpdates(vals *ValidatorSet) []abci.ValidatorUpdate {
|
||||
return validators
|
||||
}
|
||||
|
||||
func (tm2pb) ConsensusParams(params *tmproto.ConsensusParams) *abci.ConsensusParams {
|
||||
func (tm2pb) ConsensusParams(params *ConsensusParams) *abci.ConsensusParams {
|
||||
return &abci.ConsensusParams{
|
||||
Block: &abci.BlockParams{
|
||||
MaxBytes: params.Block.MaxBytes,
|
||||
MaxGas: params.Block.MaxGas,
|
||||
},
|
||||
Evidence: ¶ms.Evidence,
|
||||
Validator: ¶ms.Validator,
|
||||
Evidence: &tmproto.EvidenceParams{
|
||||
MaxAgeNumBlocks: params.Evidence.MaxAgeNumBlocks,
|
||||
MaxAgeDuration: params.Evidence.MaxAgeDuration,
|
||||
MaxBytes: params.Evidence.MaxBytes,
|
||||
},
|
||||
Validator: &tmproto.ValidatorParams{
|
||||
PubKeyTypes: params.Validator.PubKeyTypes,
|
||||
},
|
||||
Version: &tmproto.VersionParams{
|
||||
AppVersion: params.Version.AppVersion,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ func TestABCIValidators(t *testing.T) {
|
||||
func TestABCIConsensusParams(t *testing.T) {
|
||||
cp := DefaultConsensusParams()
|
||||
abciCP := TM2PB.ConsensusParams(cp)
|
||||
cp2 := UpdateConsensusParams(*cp, abciCP)
|
||||
cp2 := cp.UpdateConsensusParams(abciCP)
|
||||
|
||||
assert.Equal(t, *cp, cp2)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package version
|
||||
|
||||
import tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
|
||||
var (
|
||||
// TMCoreSemVer is the current version of Tendermint Core.
|
||||
// It's the Semantic Version of the software.
|
||||
@@ -22,3 +24,15 @@ var (
|
||||
// This includes validity of blocks and state updates.
|
||||
BlockProtocol uint64 = 11
|
||||
)
|
||||
|
||||
type Consensus struct {
|
||||
Block uint64 `json:"block"`
|
||||
App uint64 `json:"app"`
|
||||
}
|
||||
|
||||
func (c Consensus) ToProto() tmversion.Consensus {
|
||||
return tmversion.Consensus{
|
||||
Block: c.Block,
|
||||
App: c.App,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user