state: comments; use wire.BinaryBytes

This commit is contained in:
Ethan Buchman
2017-08-21 16:12:07 -04:00
parent 30d351b0c1
commit 34beff117a
2 changed files with 33 additions and 28 deletions

View File

@@ -170,6 +170,7 @@ func commitBitArrayFromBlock(block *types.Block) *cmn.BitArray {
//----------------------------------------------------- //-----------------------------------------------------
// Validate block // Validate block
// ValidateBlock validates the block against the state.
func (s *State) ValidateBlock(block *types.Block) error { func (s *State) ValidateBlock(block *types.Block) error {
return s.validateBlock(block) 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. // then commits and updates the mempool atomically, then saves state.
// Transaction results are optionally indexed. // 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, func (s *State) ApplyBlock(eventCache types.Fireable, proxyAppConn proxy.AppConnConsensus,
block *types.Block, partsHeader types.PartSetHeader, mempool types.Mempool) error { 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 return nil
} }
// mempool must be locked during commit and update // CommitStateUpdateMempool locks the mempool, runs the ABCI Commit message, and updates the mempool.
// because state is typically reset on Commit and old txs must be replayed // 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 // 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 { func (s *State) CommitStateUpdateMempool(proxyAppConn proxy.AppConnConsensus, block *types.Block, mempool types.Mempool) error {
mempool.Lock() mempool.Lock()
defer mempool.Unlock() defer mempool.Unlock()
@@ -286,8 +289,8 @@ func (s *State) indexTxs(abciResponses *ABCIResponses) {
s.TxIndexer.AddBatch(batch) s.TxIndexer.AddBatch(batch)
} }
// Exec and commit a block on the proxyApp without validating or mutating the state // ExecCommitBlock executes and commits a block on the proxyApp without validating or mutating the state.
// Returns the application root hash (result of abci.Commit) // It returns the application root hash (result of abci.Commit).
func ExecCommitBlock(appConnConsensus proxy.AppConnConsensus, block *types.Block, logger log.Logger) ([]byte, error) { func ExecCommitBlock(appConnConsensus proxy.AppConnConsensus, block *types.Block, logger log.Logger) ([]byte, error) {
var eventCache types.Fireable // nil var eventCache types.Fireable // nil
_, err := execBlockOnProxyApp(eventCache, appConnConsensus, block, logger) _, err := execBlockOnProxyApp(eventCache, appConnConsensus, block, logger)

View File

@@ -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. // NOTE: not goroutine-safe.
type State struct { type State struct {
// mtx for writing to db // mtx for writing to db
@@ -49,6 +52,7 @@ type State struct {
logger log.Logger logger log.Logger
} }
// LoadState loads the State from the database.
func LoadState(db dbm.DB) *State { func LoadState(db dbm.DB) *State {
return loadState(db, stateKey) return loadState(db, stateKey)
} }
@@ -70,10 +74,12 @@ func loadState(db dbm.DB, key []byte) *State {
return s return s
} }
// SetLogger sets the logger on the State.
func (s *State) SetLogger(l log.Logger) { func (s *State) SetLogger(l log.Logger) {
s.logger = l s.logger = l
} }
// Copy makes a copy of the State for mutating.
func (s *State) Copy() *State { func (s *State) Copy() *State {
return &State{ return &State{
db: s.db, db: s.db,
@@ -90,19 +96,20 @@ func (s *State) Copy() *State {
} }
} }
// Save persists the State to the database.
func (s *State) Save() { func (s *State) Save() {
s.mtx.Lock() s.mtx.Lock()
defer s.mtx.Unlock() defer s.mtx.Unlock()
s.db.SetSync(stateKey, s.Bytes()) s.db.SetSync(stateKey, s.Bytes())
} }
// Sets the ABCIResponses in the state and writes them to disk // SaveABCIResponses persists the ABCIResponses to the database.
// in case we crash after app.Commit and before s.Save() // This is useful in case we crash after app.Commit and before s.Save().
func (s *State) SaveABCIResponses(abciResponses *ABCIResponses) { func (s *State) SaveABCIResponses(abciResponses *ABCIResponses) {
// save the validators to the db
s.db.SetSync(abciResponsesKey, abciResponses.Bytes()) s.db.SetSync(abciResponsesKey, abciResponses.Bytes())
} }
// LoadABCIResponses loads the ABCIResponses from the database.
func (s *State) LoadABCIResponses() *ABCIResponses { func (s *State) LoadABCIResponses() *ABCIResponses {
abciResponses := new(ABCIResponses) abciResponses := new(ABCIResponses)
@@ -119,21 +126,17 @@ func (s *State) LoadABCIResponses() *ABCIResponses {
return abciResponses return abciResponses
} }
// Equals returns true if the States are identical.
func (s *State) Equals(s2 *State) bool { func (s *State) Equals(s2 *State) bool {
return bytes.Equal(s.Bytes(), s2.Bytes()) return bytes.Equal(s.Bytes(), s2.Bytes())
} }
// Bytes serializes the State using go-wire.
func (s *State) Bytes() []byte { func (s *State) Bytes() []byte {
buf, n, err := new(bytes.Buffer), new(int), new(error) return wire.BinaryBytes(s)
wire.WriteBinary(s, buf, n, err)
if *err != nil {
cmn.PanicCrisis(*err)
}
return buf.Bytes()
} }
// Mutate state variables to match block and validators // SetBlockAndValidators mutates State variables to update block and validators after running EndBlock.
// after running EndBlock
func (s *State) SetBlockAndValidators(header *types.Header, blockPartsHeader types.PartSetHeader, abciResponses *ABCIResponses) { func (s *State) SetBlockAndValidators(header *types.Header, blockPartsHeader types.PartSetHeader, abciResponses *ABCIResponses) {
// copy the valset so we can apply changes from EndBlock // 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() prevValSet := s.Validators.Copy()
nextValSet := prevValSet.Copy() nextValSet := prevValSet.Copy()
// update the validator set with the latest abciResponses
err := updateValidators(nextValSet, abciResponses.EndBlock.Diffs) err := updateValidators(nextValSet, abciResponses.EndBlock.Diffs)
if err != nil { if err != nil {
s.logger.Error("Error changing validator set", "err", err) 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, s.setBlockAndValidators(header.Height,
types.BlockID{header.Hash(), blockPartsHeader}, header.Time, types.BlockID{header.Hash(), blockPartsHeader}, header.Time,
prevValSet, nextValSet) prevValSet, nextValSet)
} }
func (s *State) setBlockAndValidators( func (s *State) setBlockAndValidators(
@@ -167,12 +170,14 @@ func (s *State) setBlockAndValidators(
s.LastValidators = prevValSet s.LastValidators = prevValSet
} }
// GetValidators returns the last and current validator sets.
func (s *State) GetValidators() (*types.ValidatorSet, *types.ValidatorSet) { func (s *State) GetValidators() (*types.ValidatorSet, *types.ValidatorSet) {
return s.LastValidators, s.Validators return s.LastValidators, s.Validators
} }
// Load the most recent state from "state" db, // GetState loads the most recent state from the database,
// or create a new one (and save) from genesis. // or creates a new one from the given genesisFile and persists the result
// to the database.
func GetState(stateDB dbm.DB, genesisFile string) *State { func GetState(stateDB dbm.DB, genesisFile string) *State {
state := LoadState(stateDB) state := LoadState(stateDB)
if state == nil { 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 { type ABCIResponses struct {
Height int Height int
@@ -195,6 +201,7 @@ type ABCIResponses struct {
txs types.Txs // reference for indexing results by hash txs types.Txs // reference for indexing results by hash
} }
// NewABCIResponses returns a new ABCIResponses
func NewABCIResponses(block *types.Block) *ABCIResponses { func NewABCIResponses(block *types.Block) *ABCIResponses {
return &ABCIResponses{ return &ABCIResponses{
Height: block.Height, 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 { func (a *ABCIResponses) Bytes() []byte {
buf, n, err := new(bytes.Buffer), new(int), new(error) return wire.BinaryBytes(*a)
wire.WriteBinary(*a, buf, n, err)
if *err != nil {
cmn.PanicCrisis(*err)
}
return buf.Bytes()
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------