Browse Source

genesis json tests and mv ConsensusParams to types

pull/650/head
Ethan Buchman 7 years ago
parent
commit
2b6db268cf
9 changed files with 149 additions and 61 deletions
  1. +2
    -2
      blockchain/reactor.go
  2. +0
    -27
      config/consensus.go
  3. +4
    -4
      consensus/replay_test.go
  4. +2
    -2
      consensus/state.go
  5. +7
    -7
      consensus/state_test.go
  6. +17
    -11
      state/state.go
  7. +6
    -8
      types/genesis.go
  8. +79
    -0
      types/genesis_test.go
  9. +32
    -0
      types/params.go

+ 2
- 2
blockchain/reactor.go View File

@ -165,7 +165,7 @@ func (bcR *BlockchainReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte)
// maxMsgSize returns the maximum allowable size of a
// message on the blockchain reactor.
func (bcR *BlockchainReactor) maxMsgSize() int {
return bcR.state.GenesisDoc.ConsensusParams.MaxBlockSizeBytes + 2
return bcR.state.Params().MaxBlockSizeBytes + 2
}
// Handle messages from the poolReactor telling the reactor what to do.
@ -226,7 +226,7 @@ FOR_LOOP:
// We need both to sync the first block.
break SYNC_LOOP
}
firstParts := first.MakePartSet(bcR.state.GenesisDoc.ConsensusParams.BlockPartSizeBytes)
firstParts := first.MakePartSet(bcR.state.Params().BlockPartSizeBytes)
firstPartsHeader := firstParts.Header()
// Finally, verify the first block using the second's commit
// NOTE: we can probably make this more efficient, but note that calling


+ 0
- 27
config/consensus.go View File

@ -1,27 +0,0 @@
package config
import (
"fmt"
)
type ConsensusParams struct {
MaxBlockSizeBytes int `json:"max_block_size_bytes"`
BlockPartSizeBytes int `json:"block_part_size_bytes"`
}
func DefaultConsensusParams() *ConsensusParams {
return &ConsensusParams{
MaxBlockSizeBytes: 22020096, // 21MB
BlockPartSizeBytes: 65536, // 64kB,
}
}
func (params *ConsensusParams) Validate() error {
if params.MaxBlockSizeBytes <= 0 {
return fmt.Errorf("MaxBlockSizeBytes must be greater than 0. Got %d", params.MaxBlockSizeBytes)
}
if params.BlockPartSizeBytes <= 0 {
return fmt.Errorf("BlockPartSizeBytes must be greater than 0. Got %d", params.BlockPartSizeBytes)
}
return nil
}

+ 4
- 4
consensus/replay_test.go View File

@ -381,7 +381,7 @@ func testHandshakeReplay(t *testing.T, nBlocks int, mode uint) {
}
func applyBlock(st *sm.State, blk *types.Block, proxyApp proxy.AppConns) {
testPartSize := st.GenesisDoc.ConsensusParams.BlockPartSizeBytes
testPartSize := st.Params().BlockPartSizeBytes
err := st.ApplyBlock(nil, proxyApp.Consensus(), blk, blk.MakePartSet(testPartSize).Header(), mempool)
if err != nil {
panic(err)
@ -561,7 +561,7 @@ func stateAndStore(config *cfg.Config, pubKey crypto.PubKey) (*sm.State, *mockBl
state := sm.MakeGenesisStateFromFile(stateDB, config.GenesisFile())
state.SetLogger(log.TestingLogger().With("module", "state"))
store := NewMockBlockStore(config, state.GenesisDoc.ConsensusParams)
store := NewMockBlockStore(config, state.Params())
return state, store
}
@ -570,13 +570,13 @@ func stateAndStore(config *cfg.Config, pubKey crypto.PubKey) (*sm.State, *mockBl
type mockBlockStore struct {
config *cfg.Config
params *cfg.ConsensusParams
params *types.ConsensusParams
chain []*types.Block
commits []*types.Commit
}
// TODO: NewBlockStore(db.NewMemDB) ...
func NewMockBlockStore(config *cfg.Config, params *cfg.ConsensusParams) *mockBlockStore {
func NewMockBlockStore(config *cfg.Config, params *types.ConsensusParams) *mockBlockStore {
return &mockBlockStore{config, params, nil, nil}
}


+ 2
- 2
consensus/state.go View File

@ -984,7 +984,7 @@ func (cs *ConsensusState) createProposalBlock() (block *types.Block, blockParts
return types.MakeBlock(cs.Height, cs.state.ChainID, txs, commit,
cs.state.LastBlockID, cs.state.Validators.Hash(),
cs.state.AppHash, cs.state.GenesisDoc.ConsensusParams.BlockPartSizeBytes)
cs.state.AppHash, cs.state.Params().BlockPartSizeBytes)
}
// Enter: `timeoutPropose` after entering Propose.
@ -1419,7 +1419,7 @@ func (cs *ConsensusState) addProposalBlockPart(height int, part *types.Part, ver
var n int
var err error
cs.ProposalBlock = wire.ReadBinary(&types.Block{}, cs.ProposalBlockParts.GetReader(),
cs.state.GenesisDoc.ConsensusParams.MaxBlockSizeBytes, &n, &err).(*types.Block)
cs.state.Params().MaxBlockSizeBytes, &n, &err).(*types.Block)
// NOTE: it's possible to receive complete proposal blocks for future rounds without having the proposal
cs.Logger.Info("Received complete proposal block", "height", cs.ProposalBlock.Height, "hash", cs.ProposalBlock.Hash())
if cs.Step == RoundStepPropose && cs.isProposalComplete() {


+ 7
- 7
consensus/state_test.go View File

@ -180,7 +180,7 @@ func TestBadProposal(t *testing.T) {
height, round := cs1.Height, cs1.Round
vs2 := vss[1]
partSize := cs1.state.GenesisDoc.ConsensusParams.BlockPartSizeBytes
partSize := cs1.state.Params().BlockPartSizeBytes
proposalCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringCompleteProposal(), 1)
voteCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringVote(), 1)
@ -327,7 +327,7 @@ func TestLockNoPOL(t *testing.T) {
vs2 := vss[1]
height := cs1.Height
partSize := cs1.state.GenesisDoc.ConsensusParams.BlockPartSizeBytes
partSize := cs1.state.Params().BlockPartSizeBytes
timeoutProposeCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutPropose(), 1)
timeoutWaitCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutWait(), 1)
@ -493,7 +493,7 @@ func TestLockPOLRelock(t *testing.T) {
cs1, vss := randConsensusState(4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
partSize := cs1.state.GenesisDoc.ConsensusParams.BlockPartSizeBytes
partSize := cs1.state.Params().BlockPartSizeBytes
timeoutProposeCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutPropose(), 1)
timeoutWaitCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutWait(), 1)
@ -608,7 +608,7 @@ func TestLockPOLUnlock(t *testing.T) {
cs1, vss := randConsensusState(4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
partSize := cs1.state.GenesisDoc.ConsensusParams.BlockPartSizeBytes
partSize := cs1.state.Params().BlockPartSizeBytes
proposalCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringCompleteProposal(), 1)
timeoutProposeCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutPropose(), 1)
@ -703,7 +703,7 @@ func TestLockPOLSafety1(t *testing.T) {
cs1, vss := randConsensusState(4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
partSize := cs1.state.GenesisDoc.ConsensusParams.BlockPartSizeBytes
partSize := cs1.state.Params().BlockPartSizeBytes
proposalCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringCompleteProposal(), 1)
timeoutProposeCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutPropose(), 1)
@ -824,7 +824,7 @@ func TestLockPOLSafety2(t *testing.T) {
cs1, vss := randConsensusState(4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
partSize := cs1.state.GenesisDoc.ConsensusParams.BlockPartSizeBytes
partSize := cs1.state.Params().BlockPartSizeBytes
proposalCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringCompleteProposal(), 1)
timeoutProposeCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutPropose(), 1)
@ -999,7 +999,7 @@ func TestHalt1(t *testing.T) {
cs1, vss := randConsensusState(4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
partSize := cs1.state.GenesisDoc.ConsensusParams.BlockPartSizeBytes
partSize := cs1.state.Params().BlockPartSizeBytes
proposalCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringCompleteProposal(), 1)
timeoutWaitCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutWait(), 1)


+ 17
- 11
state/state.go View File

@ -65,6 +65,19 @@ type State struct {
logger log.Logger
}
// GetState loads the most recent state from the database,
// or creates a new one from the given genesisFile and persists the result
// to the database.
func GetState(stateDB dbm.DB, genesisFile string) *State {
state := LoadState(stateDB)
if state == nil {
state = MakeGenesisStateFromFile(stateDB, genesisFile)
state.Save()
}
return state
}
// LoadState loads the State from the database.
func LoadState(db dbm.DB) *State {
return loadState(db, stateKey)
@ -248,17 +261,10 @@ func (s *State) GetValidators() (*types.ValidatorSet, *types.ValidatorSet) {
return s.LastValidators, s.Validators
}
// GetState loads the most recent state from the database,
// or creates a new one from the given genesisFile and persists the result
// to the database.
func GetState(stateDB dbm.DB, genesisFile string) *State {
state := LoadState(stateDB)
if state == nil {
state = MakeGenesisStateFromFile(stateDB, genesisFile)
state.Save()
}
return state
// Params returns the consensus parameters used for
// validating blocks
func (s *State) Params() *types.ConsensusParams {
return s.GenesisDoc.ConsensusParams
}
//------------------------------------------------------------------------


+ 6
- 8
types/genesis.go View File

@ -10,8 +10,6 @@ import (
"github.com/tendermint/go-crypto"
"github.com/tendermint/go-wire/data"
cmn "github.com/tendermint/tmlibs/common"
cfg "github.com/tendermint/tendermint/config"
)
//------------------------------------------------------------
@ -26,11 +24,11 @@ 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"`
ConsensusParams *cfg.ConsensusParams `json:"consensus_params"`
Validators []GenesisValidator `json:"validators"`
AppHash data.Bytes `json:"app_hash"`
GenesisTime time.Time `json:"genesis_time"`
ChainID string `json:"chain_id"`
ConsensusParams *ConsensusParams `json:"consensus_params"`
Validators []GenesisValidator `json:"validators"`
AppHash data.Bytes `json:"app_hash"`
}
// SaveAs is a utility method for saving GenensisDoc as a JSON file.
@ -61,7 +59,7 @@ func (genDoc *GenesisDoc) ValidateAndComplete() error {
}
if genDoc.ConsensusParams == nil {
genDoc.ConsensusParams = cfg.DefaultConsensusParams()
genDoc.ConsensusParams = DefaultConsensusParams()
} else {
if err := genDoc.ConsensusParams.Validate(); err != nil {
return err


+ 79
- 0
types/genesis_test.go View File

@ -0,0 +1,79 @@
package types
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
crypto "github.com/tendermint/go-crypto"
)
func TestGenesis(t *testing.T) {
// test some bad ones from raw json
testCases := [][]byte{
[]byte{}, // empty
[]byte{1, 1, 1, 1, 1}, // junk
[]byte(`{}`), // empty
[]byte(`{"chain_id": "mychain"}`), // missing validators
[]byte(`{"validators": [{"data":abcd}`), // missing validators
[]byte(`{"validators":[{"pub_key":
{"type":"ed25519","data":"961EAB8752E51A03618502F55C2B6E09C38C65635C64CCF3173ED452CF86C957"},
"amount":10,"name":""}]}`), // missing chain_id
}
for _, testCase := range testCases {
_, err := GenesisDocFromJSON(testCase)
assert.NotNil(t, err, "expected error for empty genDoc json")
}
// test a good one by raw json
genDocBytes := []byte(`{"genesis_time":"0001-01-01T00:00:00Z","chain_id":"test-chain-QDKdJr","consensus_params":null,"validators":[{"pub_key":{"type":"ed25519","data":"961EAB8752E51A03618502F55C2B6E09C38C65635C64CCF3173ED452CF86C957"},"amount":10,"name":""}],"app_hash":""}`)
_, err := GenesisDocFromJSON(genDocBytes)
assert.Nil(t, err, "expected no error for good genDoc json")
// create a base gendoc from struct
baseGenDoc := &GenesisDoc{
ChainID: "abc",
Validators: []GenesisValidator{{crypto.GenPrivKeyEd25519().PubKey(), 10, "myval"}},
}
genDocBytes, err = json.Marshal(baseGenDoc)
assert.Nil(t, err, "error marshalling genDoc")
// test base gendoc and check consensus params were filled
genDoc, err := GenesisDocFromJSON(genDocBytes)
assert.Nil(t, err, "expected no error for valid genDoc json")
assert.NotNil(t, genDoc.ConsensusParams, "expected consensus params to be filled in")
// create json with consensus params filled
genDocBytes, err = json.Marshal(genDoc)
assert.Nil(t, err, "error marshalling genDoc")
genDoc, err = GenesisDocFromJSON(genDocBytes)
assert.Nil(t, err, "expected no error for valid genDoc json")
// test with invalid consensus params
genDoc.ConsensusParams.MaxBlockSizeBytes = 0
genDocBytes, err = json.Marshal(genDoc)
assert.Nil(t, err, "error marshalling genDoc")
genDoc, err = GenesisDocFromJSON(genDocBytes)
assert.NotNil(t, err, "expected error for genDoc json with block size of 0")
}
func TestConsensusParams(t *testing.T) {
testCases := []struct {
params *ConsensusParams
valid bool
}{
{&ConsensusParams{1, 1}, true},
{&ConsensusParams{1, 0}, false},
{&ConsensusParams{0, 1}, false},
{&ConsensusParams{0, 0}, false},
}
for _, testCase := range testCases {
if testCase.valid {
assert.Nil(t, testCase.params.Validate(), "expected no error for valid params")
} else {
assert.NotNil(t, testCase.params.Validate(), "expected error for non valid params")
}
}
}

+ 32
- 0
types/params.go View File

@ -0,0 +1,32 @@
package types
import (
"github.com/pkg/errors"
)
// ConsensusParams contains consensus critical parameters
// that determine the validity of blocks.
type ConsensusParams struct {
MaxBlockSizeBytes int `json:"max_block_size_bytes"`
BlockPartSizeBytes int `json:"block_part_size_bytes"`
}
// DefaultConsensusParams returns a default ConsensusParams.
func DefaultConsensusParams() *ConsensusParams {
return &ConsensusParams{
MaxBlockSizeBytes: 22020096, // 21MB
BlockPartSizeBytes: 65536, // 64kB,
}
}
// Validate validates the ConsensusParams to ensure all values
// are within their allowed limits, and returns an error if they are not.
func (params *ConsensusParams) Validate() error {
if params.MaxBlockSizeBytes <= 0 {
return errors.Errorf("MaxBlockSizeBytes must be greater than 0. Got %d", params.MaxBlockSizeBytes)
}
if params.BlockPartSizeBytes <= 0 {
return errors.Errorf("BlockPartSizeBytes must be greater than 0. Got %d", params.BlockPartSizeBytes)
}
return nil
}

Loading…
Cancel
Save