diff --git a/state/execution.go b/state/execution.go index db2091804..9e4a5fb29 100644 --- a/state/execution.go +++ b/state/execution.go @@ -170,6 +170,7 @@ func commitBitArrayFromBlock(block *types.Block) *cmn.BitArray { //----------------------------------------------------- // Validate block +// ValidateBlock validates the block against the state. func (s *State) ValidateBlock(block *types.Block) error { return s.validateBlock(block) } @@ -206,7 +207,9 @@ func (s *State) validateBlock(block *types.Block) error { // then commits and updates the mempool atomically, then saves state. // Transaction results are optionally indexed. -// Validate, execute, and commit block against app, save block and state +// ApplyBlock validates the block against the state, executes it against the app, +// commits it, and saves the block and state. It's the only function that needs to be called +// from outside this package to process and commit an entire block. func (s *State) ApplyBlock(eventCache types.Fireable, proxyAppConn proxy.AppConnConsensus, block *types.Block, partsHeader types.PartSetHeader, mempool types.Mempool) error { @@ -242,9 +245,9 @@ func (s *State) ApplyBlock(eventCache types.Fireable, proxyAppConn proxy.AppConn return nil } -// mempool must be locked during commit and update -// because state is typically reset on Commit and old txs must be replayed -// against committed state before new txs are run in the mempool, lest they be invalid +// CommitStateUpdateMempool locks the mempool, runs the ABCI Commit message, and updates the mempool. +// The Mempool must be locked during commit and update because state is typically reset on Commit and old txs must be replayed +// against committed state before new txs are run in the mempool, lest they be invalid. func (s *State) CommitStateUpdateMempool(proxyAppConn proxy.AppConnConsensus, block *types.Block, mempool types.Mempool) error { mempool.Lock() defer mempool.Unlock() @@ -286,8 +289,8 @@ func (s *State) indexTxs(abciResponses *ABCIResponses) { s.TxIndexer.AddBatch(batch) } -// Exec and commit a block on the proxyApp without validating or mutating the state -// Returns the application root hash (result of abci.Commit) +// ExecCommitBlock executes and commits a block on the proxyApp without validating or mutating the state. +// It returns the application root hash (result of abci.Commit). func ExecCommitBlock(appConnConsensus proxy.AppConnConsensus, block *types.Block, logger log.Logger) ([]byte, error) { var eventCache types.Fireable // nil _, err := execBlockOnProxyApp(eventCache, appConnConsensus, block, logger) diff --git a/state/state.go b/state/state.go index e1ccca9b1..21ad92776 100644 --- a/state/state.go +++ b/state/state.go @@ -24,6 +24,9 @@ var ( //----------------------------------------------------------------------------- +// State represents the latest committed state of the Tendermint consensus, +// including the last committed block and validator set. +// Newly committed blocks are validated and executed against the State. // NOTE: not goroutine-safe. type State struct { // mtx for writing to db @@ -49,6 +52,7 @@ type State struct { logger log.Logger } +// LoadState loads the State from the database. func LoadState(db dbm.DB) *State { return loadState(db, stateKey) } @@ -70,10 +74,12 @@ func loadState(db dbm.DB, key []byte) *State { return s } +// SetLogger sets the logger on the State. func (s *State) SetLogger(l log.Logger) { s.logger = l } +// Copy makes a copy of the State for mutating. func (s *State) Copy() *State { return &State{ db: s.db, @@ -90,19 +96,20 @@ func (s *State) Copy() *State { } } +// Save persists the State to the database. func (s *State) Save() { s.mtx.Lock() defer s.mtx.Unlock() s.db.SetSync(stateKey, s.Bytes()) } -// Sets the ABCIResponses in the state and writes them to disk -// in case we crash after app.Commit and before s.Save() +// SaveABCIResponses persists the ABCIResponses to the database. +// This is useful in case we crash after app.Commit and before s.Save(). func (s *State) SaveABCIResponses(abciResponses *ABCIResponses) { - // save the validators to the db s.db.SetSync(abciResponsesKey, abciResponses.Bytes()) } +// LoadABCIResponses loads the ABCIResponses from the database. func (s *State) LoadABCIResponses() *ABCIResponses { abciResponses := new(ABCIResponses) @@ -119,21 +126,17 @@ func (s *State) LoadABCIResponses() *ABCIResponses { return abciResponses } +// Equals returns true if the States are identical. func (s *State) Equals(s2 *State) bool { return bytes.Equal(s.Bytes(), s2.Bytes()) } +// Bytes serializes the State using go-wire. func (s *State) Bytes() []byte { - buf, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(s, buf, n, err) - if *err != nil { - cmn.PanicCrisis(*err) - } - return buf.Bytes() + return wire.BinaryBytes(s) } -// Mutate state variables to match block and validators -// after running EndBlock +// SetBlockAndValidators mutates State variables to update block and validators after running EndBlock. func (s *State) SetBlockAndValidators(header *types.Header, blockPartsHeader types.PartSetHeader, abciResponses *ABCIResponses) { // copy the valset so we can apply changes from EndBlock @@ -141,7 +144,6 @@ func (s *State) SetBlockAndValidators(header *types.Header, blockPartsHeader typ prevValSet := s.Validators.Copy() nextValSet := prevValSet.Copy() - // update the validator set with the latest abciResponses err := updateValidators(nextValSet, abciResponses.EndBlock.Diffs) if err != nil { s.logger.Error("Error changing validator set", "err", err) @@ -154,6 +156,7 @@ func (s *State) SetBlockAndValidators(header *types.Header, blockPartsHeader typ s.setBlockAndValidators(header.Height, types.BlockID{header.Hash(), blockPartsHeader}, header.Time, prevValSet, nextValSet) + } func (s *State) setBlockAndValidators( @@ -167,12 +170,14 @@ func (s *State) setBlockAndValidators( s.LastValidators = prevValSet } +// GetValidators returns the last and current validator sets. func (s *State) GetValidators() (*types.ValidatorSet, *types.ValidatorSet) { return s.LastValidators, s.Validators } -// Load the most recent state from "state" db, -// or create a new one (and save) from genesis. +// 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 { @@ -184,8 +189,9 @@ func GetState(stateDB dbm.DB, genesisFile string) *State { } //-------------------------------------------------- -// ABCIResponses holds intermediate state during block processing +// ABCIResponses retains the responses of the various ABCI calls during block processing. +// It is persisted to disk before calling Commit. type ABCIResponses struct { Height int @@ -195,6 +201,7 @@ type ABCIResponses struct { txs types.Txs // reference for indexing results by hash } +// NewABCIResponses returns a new ABCIResponses func NewABCIResponses(block *types.Block) *ABCIResponses { return &ABCIResponses{ Height: block.Height, @@ -203,14 +210,9 @@ func NewABCIResponses(block *types.Block) *ABCIResponses { } } -// Serialize the ABCIResponse +// Bytes serializes the ABCIResponse using go-wire func (a *ABCIResponses) Bytes() []byte { - buf, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(*a, buf, n, err) - if *err != nil { - cmn.PanicCrisis(*err) - } - return buf.Bytes() + return wire.BinaryBytes(*a) } //-----------------------------------------------------------------------------