Browse Source

Merge pull request #676 from tendermint/state-unexpose-genesisDoc-chainID

all, state: unexpose GenesisDoc, ChainID fields make them accessor methods
pull/737/merge
Ethan Buchman 7 years ago
committed by GitHub
parent
commit
fa56e8c0ce
9 changed files with 84 additions and 53 deletions
  1. +5
    -3
      blockchain/reactor.go
  2. +2
    -2
      blockchain/reactor_test.go
  3. +2
    -2
      blockchain/store.go
  4. +2
    -2
      consensus/replay_test.go
  5. +6
    -7
      consensus/state.go
  6. +7
    -7
      consensus/state_test.go
  7. +43
    -7
      node/node.go
  8. +14
    -22
      state/state.go
  9. +3
    -1
      state/state_test.go

+ 5
- 3
blockchain/reactor.go View File

@ -175,7 +175,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.Params().BlockSizeParams.MaxBytes + 2
return bcR.state.Params.BlockSizeParams.MaxBytes + 2
}
// Handle messages from the poolReactor telling the reactor what to do.
@ -187,6 +187,8 @@ func (bcR *BlockchainReactor) poolRoutine() {
statusUpdateTicker := time.NewTicker(statusUpdateIntervalSeconds * time.Second)
switchToConsensusTicker := time.NewTicker(switchToConsensusIntervalSeconds * time.Second)
chainID := bcR.state.ChainID
FOR_LOOP:
for {
select {
@ -236,14 +238,14 @@ FOR_LOOP:
// We need both to sync the first block.
break SYNC_LOOP
}
firstParts := first.MakePartSet(bcR.state.Params().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
// first.Hash() doesn't verify the tx contents, so MakePartSet() is
// currently necessary.
err := bcR.state.Validators.VerifyCommit(
bcR.state.ChainID, types.BlockID{first.Hash(), firstPartsHeader}, first.Height, second.LastCommit)
chainID, types.BlockID{first.Hash(), firstPartsHeader}, first.Height, second.LastCommit)
if err != nil {
bcR.Logger.Error("Error in validation", "err", err)
bcR.pool.RedoRequest(first.Height)


+ 2
- 2
blockchain/reactor_test.go View File

@ -42,7 +42,7 @@ func newBlockchainReactor(logger log.Logger, maxBlockHeight int) *BlockchainReac
for blockHeight := 1; blockHeight <= maxBlockHeight; blockHeight++ {
firstBlock := makeBlock(blockHeight, state)
secondBlock := makeBlock(blockHeight+1, state)
firstParts := firstBlock.MakePartSet(state.Params().BlockGossipParams.BlockPartSizeBytes)
firstParts := firstBlock.MakePartSet(state.Params.BlockGossipParams.BlockPartSizeBytes)
blockStore.SaveBlock(firstBlock, firstParts, secondBlock.LastCommit)
}
@ -113,7 +113,7 @@ func makeBlock(blockNumber int, state *sm.State) *types.Block {
valHash := state.Validators.Hash()
prevBlockID := types.BlockID{prevHash, prevParts}
block, _ := types.MakeBlock(blockNumber, "test_chain", makeTxs(blockNumber),
new(types.Commit), prevBlockID, valHash, state.AppHash, state.Params().BlockGossipParams.BlockPartSizeBytes)
new(types.Commit), prevBlockID, valHash, state.AppHash, state.Params.BlockGossipParams.BlockPartSizeBytes)
return block
}


+ 2
- 2
blockchain/store.go View File

@ -7,10 +7,10 @@ import (
"io"
"sync"
wire "github.com/tendermint/go-wire"
"github.com/tendermint/tendermint/types"
. "github.com/tendermint/tmlibs/common"
dbm "github.com/tendermint/tmlibs/db"
"github.com/tendermint/go-wire"
"github.com/tendermint/tendermint/types"
)
/*


+ 2
- 2
consensus/replay_test.go View File

@ -382,7 +382,7 @@ func testHandshakeReplay(t *testing.T, nBlocks int, mode uint) {
}
func applyBlock(st *sm.State, blk *types.Block, proxyApp proxy.AppConns) {
testPartSize := st.Params().BlockPartSizeBytes
testPartSize := st.Params.BlockPartSizeBytes
err := st.ApplyBlock(nil, proxyApp.Consensus(), blk, blk.MakePartSet(testPartSize).Header(), mempool)
if err != nil {
panic(err)
@ -562,7 +562,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.Params())
store := NewMockBlockStore(config, state.Params)
return state, store
}


+ 6
- 7
consensus/state.go View File

@ -390,7 +390,7 @@ func (cs *ConsensusState) reconstructLastCommit(state *sm.State) {
return
}
seenCommit := cs.blockStore.LoadSeenCommit(state.LastBlockHeight)
lastPrecommits := types.NewVoteSet(cs.state.ChainID, state.LastBlockHeight, seenCommit.Round(), types.VoteTypePrecommit, state.LastValidators)
lastPrecommits := types.NewVoteSet(state.ChainID, state.LastBlockHeight, seenCommit.Round(), types.VoteTypePrecommit, state.LastValidators)
for _, precommit := range seenCommit.Precommits {
if precommit == nil {
continue
@ -707,6 +707,7 @@ func (cs *ConsensusState) proposalHeartbeat(height, round int) {
// not a validator
valIndex = -1
}
chainID := cs.state.ChainID
for {
rs := cs.GetRoundState()
// if we've already moved on, no need to send more heartbeats
@ -720,7 +721,7 @@ func (cs *ConsensusState) proposalHeartbeat(height, round int) {
ValidatorAddress: addr,
ValidatorIndex: valIndex,
}
cs.privValidator.SignHeartbeat(cs.state.ChainID, heartbeat)
cs.privValidator.SignHeartbeat(chainID, heartbeat)
heartbeatEvent := types.EventDataProposalHeartbeat{heartbeat}
types.FireEventProposalHeartbeat(cs.evsw, heartbeatEvent)
counter += 1
@ -797,8 +798,7 @@ func (cs *ConsensusState) defaultDecideProposal(height, round int) {
// Make proposal
polRound, polBlockID := cs.Votes.POLInfo()
proposal := types.NewProposal(height, round, blockParts.Header(), polRound, polBlockID)
err := cs.privValidator.SignProposal(cs.state.ChainID, proposal)
if err == nil {
if err := cs.privValidator.SignProposal(cs.state.ChainID, proposal); err == nil {
// Set fields
/* fields set by setProposal and addBlockPart
cs.Proposal = proposal
@ -857,10 +857,9 @@ func (cs *ConsensusState) createProposalBlock() (block *types.Block, blockParts
// Mempool validated transactions
txs := cs.mempool.Reap(cs.config.MaxBlockSizeTxs)
return types.MakeBlock(cs.Height, cs.state.ChainID, txs, commit,
cs.state.LastBlockID, cs.state.Validators.Hash(),
cs.state.AppHash, cs.state.Params().BlockPartSizeBytes)
cs.state.AppHash, cs.state.Params.BlockPartSizeBytes)
}
// Enter: `timeoutPropose` after entering Propose.
@ -1295,7 +1294,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.Params().BlockSizeParams.MaxBytes, &n, &err).(*types.Block)
cs.state.Params.BlockSizeParams.MaxBytes, &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 == cstypes.RoundStepPropose && cs.isProposalComplete() {


+ 7
- 7
consensus/state_test.go View File

@ -181,7 +181,7 @@ func TestBadProposal(t *testing.T) {
height, round := cs1.Height, cs1.Round
vs2 := vss[1]
partSize := cs1.state.Params().BlockPartSizeBytes
partSize := cs1.state.Params.BlockPartSizeBytes
proposalCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringCompleteProposal(), 1)
voteCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringVote(), 1)
@ -328,7 +328,7 @@ func TestLockNoPOL(t *testing.T) {
vs2 := vss[1]
height := cs1.Height
partSize := cs1.state.Params().BlockPartSizeBytes
partSize := cs1.state.Params.BlockPartSizeBytes
timeoutProposeCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutPropose(), 1)
timeoutWaitCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutWait(), 1)
@ -494,7 +494,7 @@ func TestLockPOLRelock(t *testing.T) {
cs1, vss := randConsensusState(4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
partSize := cs1.state.Params().BlockPartSizeBytes
partSize := cs1.state.Params.BlockPartSizeBytes
timeoutProposeCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutPropose(), 1)
timeoutWaitCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutWait(), 1)
@ -607,7 +607,7 @@ func TestLockPOLUnlock(t *testing.T) {
cs1, vss := randConsensusState(4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
partSize := cs1.state.Params().BlockPartSizeBytes
partSize := cs1.state.Params.BlockPartSizeBytes
proposalCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringCompleteProposal(), 1)
timeoutProposeCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutPropose(), 1)
@ -702,7 +702,7 @@ func TestLockPOLSafety1(t *testing.T) {
cs1, vss := randConsensusState(4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
partSize := cs1.state.Params().BlockPartSizeBytes
partSize := cs1.state.Params.BlockPartSizeBytes
proposalCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringCompleteProposal(), 1)
timeoutProposeCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutPropose(), 1)
@ -823,7 +823,7 @@ func TestLockPOLSafety2(t *testing.T) {
cs1, vss := randConsensusState(4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
partSize := cs1.state.Params().BlockPartSizeBytes
partSize := cs1.state.Params.BlockPartSizeBytes
proposalCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringCompleteProposal(), 1)
timeoutProposeCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutPropose(), 1)
@ -998,7 +998,7 @@ func TestHalt1(t *testing.T) {
cs1, vss := randConsensusState(4)
vs2, vs3, vs4 := vss[1], vss[2], vss[3]
partSize := cs1.state.Params().BlockPartSizeBytes
partSize := cs1.state.Params.BlockPartSizeBytes
proposalCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringCompleteProposal(), 1)
timeoutWaitCh := subscribeToEvent(cs1.evsw, "tester", types.EventStringTimeoutWait(), 1)


+ 43
- 7
node/node.go View File

@ -2,6 +2,7 @@ package node
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net"
@ -132,19 +133,27 @@ func NewNode(config *cfg.Config,
if err != nil {
return nil, err
}
state := sm.LoadState(stateDB)
if state == nil {
genDoc, err := genesisDocProvider()
// Get genesis doc
genDoc, err := loadGenesisDoc(stateDB)
if err != nil {
genDoc, err = genesisDocProvider()
if err != nil {
return nil, err
}
// save genesis doc to prevent a certain class of user errors (e.g. when it
// was changed, accidentally or not). Also good for audit trail.
saveGenesisDoc(stateDB, genDoc)
}
state := sm.LoadState(stateDB)
if state == nil {
state, err = sm.MakeGenesisState(stateDB, genDoc)
if err != nil {
return nil, err
}
state.Save()
}
state.SetLogger(stateLogger)
// Create the proxyApp, which manages connections (consensus, mempool, query)
@ -286,7 +295,7 @@ func NewNode(config *cfg.Config,
node := &Node{
config: config,
genesisDoc: state.GenesisDoc,
genesisDoc: genDoc,
privValidator: privValidator,
privKey: privKey,
@ -485,11 +494,10 @@ func (n *Node) makeNodeInfo() *p2p.NodeInfo {
if _, ok := n.txIndexer.(*null.TxIndex); ok {
txIndexerStatus = "off"
}
nodeInfo := &p2p.NodeInfo{
PubKey: n.privKey.PubKey().Unwrap().(crypto.PubKeyEd25519),
Moniker: n.config.Moniker,
Network: n.consensusState.GetState().ChainID,
Network: n.genesisDoc.ChainID,
Version: version.Version,
Other: []string{
cmn.Fmt("wire_version=%v", wire.Version),
@ -536,3 +544,31 @@ func (n *Node) DialSeeds(seeds []string) error {
}
//------------------------------------------------------------------------------
var (
genesisDocKey = []byte("genesisDoc")
)
// panics if failed to unmarshal bytes
func loadGenesisDoc(db dbm.DB) (*types.GenesisDoc, error) {
bytes := db.Get(genesisDocKey)
if len(bytes) == 0 {
return nil, errors.New("Genesis doc not found")
} else {
var genDoc *types.GenesisDoc
err := json.Unmarshal(bytes, &genDoc)
if err != nil {
cmn.PanicCrisis(fmt.Sprintf("Failed to load genesis doc due to unmarshaling error: %v (bytes: %X)", err, bytes))
}
return genDoc, nil
}
}
// panics if failed to marshal the given genesis document
func saveGenesisDoc(db dbm.DB, genDoc *types.GenesisDoc) {
bytes, err := json.Marshal(genDoc)
if err != nil {
cmn.PanicCrisis(fmt.Sprintf("Failed to save genesis doc due to marshaling error: %v", err))
}
db.SetSync(genesisDocKey, bytes)
}

+ 14
- 22
state/state.go View File

@ -38,9 +38,9 @@ type State struct {
mtx sync.Mutex
db dbm.DB
// should not change
GenesisDoc *types.GenesisDoc
ChainID string
ChainID string
// Consensus parameters used for validating blocks
Params types.ConsensusParams
// These fields are updated by SetBlockAndValidators.
// LastBlockHeight=0 at genesis (ie. block(H=0) does not exist)
@ -69,15 +69,16 @@ type State struct {
// or creates a new one from the given genesisFile and persists the result
// to the database.
func GetState(stateDB dbm.DB, genesisFile string) (*State, error) {
var err error
state := LoadState(stateDB)
if state == nil {
var err error
state, err = MakeGenesisStateFromFile(stateDB, genesisFile)
if err != nil {
return nil, err
}
state.Save()
}
return state, nil
}
@ -100,7 +101,6 @@ func loadState(db dbm.DB, key []byte) *State {
}
// TODO: ensure that buf is completely read.
}
return s
}
@ -113,8 +113,6 @@ func (s *State) SetLogger(l log.Logger) {
func (s *State) Copy() *State {
return &State{
db: s.db,
GenesisDoc: s.GenesisDoc,
ChainID: s.ChainID,
LastBlockHeight: s.LastBlockHeight,
LastBlockID: s.LastBlockID,
LastBlockTime: s.LastBlockTime,
@ -123,7 +121,9 @@ func (s *State) Copy() *State {
AppHash: s.AppHash,
TxIndexer: s.TxIndexer, // pointer here, not value
LastHeightValidatorsChanged: s.LastHeightValidatorsChanged,
logger: s.logger,
logger: s.logger,
ChainID: s.ChainID,
Params: s.Params,
}
}
@ -168,7 +168,7 @@ func (s *State) LoadValidators(height int) (*types.ValidatorSet, error) {
if v.ValidatorSet == nil {
v = s.loadValidators(v.LastHeightChanged)
if v == nil {
cmn.PanicSanity(fmt.Sprintf(`Couldn't find validators at
cmn.PanicSanity(fmt.Sprintf(`Couldn't find validators at
height %d as last changed from height %d`, v.LastHeightChanged, height))
}
}
@ -264,14 +264,6 @@ func (s *State) GetValidators() (*types.ValidatorSet, *types.ValidatorSet) {
return s.LastValidators, s.Validators
}
// Params returns the consensus parameters used for
// validating blocks
func (s *State) Params() types.ConsensusParams {
// TODO: this should move into the State proper
// when we allow the app to change it
return *s.GenesisDoc.ConsensusParams
}
//------------------------------------------------------------------------
// ABCIResponses retains the responses of the various ABCI calls during block processing.
@ -341,8 +333,6 @@ func MakeGenesisDocFromFile(genDocFile string) (*types.GenesisDoc, error) {
}
// MakeGenesisState creates state from types.GenesisDoc.
//
// Used in tests.
func MakeGenesisState(db dbm.DB, genDoc *types.GenesisDoc) (*State, error) {
err := genDoc.ValidateAndComplete()
if err != nil {
@ -364,9 +354,11 @@ func MakeGenesisState(db dbm.DB, genDoc *types.GenesisDoc) (*State, error) {
}
return &State{
db: db,
GenesisDoc: genDoc,
ChainID: genDoc.ChainID,
db: db,
ChainID: genDoc.ChainID,
Params: *genDoc.ConsensusParams,
LastBlockHeight: 0,
LastBlockID: types.BlockID{},
LastBlockTime: genDoc.GenesisTime,


+ 3
- 1
state/state_test.go View File

@ -12,6 +12,7 @@ import (
abci "github.com/tendermint/abci/types"
crypto "github.com/tendermint/go-crypto"
cmn "github.com/tendermint/tmlibs/common"
dbm "github.com/tendermint/tmlibs/db"
"github.com/tendermint/tmlibs/log"
@ -127,7 +128,8 @@ func TestValidatorChangesSaveLoad(t *testing.T) {
// each valset is just one validator.
// create list of them
pubkeys := make([]crypto.PubKey, N+1)
pubkeys[0] = state.GenesisDoc.Validators[0].PubKey
_, val := state.Validators.GetByIndex(0)
pubkeys[0] = val.PubKey
for i := 1; i < N+1; i++ {
pubkeys[i] = crypto.GenPrivKeyEd25519().PubKey()
}


Loading…
Cancel
Save