Merge from panic branch

This commit is contained in:
Ethan Buchman
2015-06-17 00:16:58 -04:00
committed by Jae Kwon
parent 7196e5ad8e
commit a7ecdd10de
15 changed files with 117 additions and 32 deletions

View File

@@ -63,8 +63,8 @@ func (cache *BlockCache) GetAccount(addr []byte) *ac.Account {
func (cache *BlockCache) UpdateAccount(acc *ac.Account) {
addr := acc.Address
// SANITY CHECK
_, storage, removed, _ := cache.accounts[string(addr)].unpack()
// SANITY CHECK
if removed {
panic("UpdateAccount on a removed account")
}
@@ -95,9 +95,11 @@ func (cache *BlockCache) GetStorage(addr Word256, key Word256) (value Word256) {
// Get or load storage
acc, storage, removed, dirty := cache.accounts[string(addr.Postfix(20))].unpack()
// SANITY CHECK
if removed {
panic("GetStorage() on removed account")
}
// SANITY CHECK END
if acc != nil && storage == nil {
storage = makeStorage(cache.db, acc.StorageRoot)
cache.accounts[string(addr.Postfix(20))] = accountInfo{acc, storage, false, dirty}
@@ -117,10 +119,12 @@ func (cache *BlockCache) GetStorage(addr Word256, key Word256) (value Word256) {
// NOTE: Set value to zero to removed from the trie.
func (cache *BlockCache) SetStorage(addr Word256, key Word256, value Word256) {
// SANITY CHECK
_, _, removed, _ := cache.accounts[string(addr.Postfix(20))].unpack()
if removed {
panic("SetStorage() on a removed account")
}
// SANITY CHECK END
cache.storages[Tuple256{addr, key}] = storageInfo{value, true}
}
@@ -143,12 +147,6 @@ func (cache *BlockCache) GetNameRegEntry(name string) *types.NameRegEntry {
func (cache *BlockCache) UpdateNameRegEntry(entry *types.NameRegEntry) {
name := entry.Name
// SANITY CHECK
_, removed, _ := cache.names[name].unpack()
if removed {
panic("UpdateNameRegEntry on a removed name")
}
// SANITY CHECK END
cache.names[name] = nameInfo{entry, false, true}
}
@@ -224,6 +222,7 @@ func (cache *BlockCache) Sync() {
if removed {
removed := cache.backend.RemoveAccount(acc.Address)
if !removed {
// SOMETHING HORRIBLE HAS GONE WRONG
panic(Fmt("Could not remove account to be removed: %X", acc.Address))
}
} else {
@@ -257,6 +256,7 @@ func (cache *BlockCache) Sync() {
if removed {
removed := cache.backend.RemoveNameRegEntry(nameStr)
if !removed {
// SOMETHING HORRIBLE HAS GONE WRONG
panic(Fmt("Could not remove namereg entry to be removed: %s", nameStr))
}
} else {

View File

@@ -3,7 +3,6 @@ package state
import (
"bytes"
"errors"
"fmt"
"github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/common"
@@ -22,8 +21,8 @@ func ExecBlock(s *State, block *types.Block, blockPartsHeader types.PartSetHeade
// State.Hash should match block.StateHash
stateHash := s.Hash()
if !bytes.Equal(stateHash, block.StateHash) {
return fmt.Errorf("Invalid state hash. Expected %X, got %X",
stateHash, block.StateHash)
return errors.New(Fmt("Invalid state hash. Expected %X, got %X",
stateHash, block.StateHash))
}
return nil
}
@@ -56,6 +55,7 @@ func execBlock(s *State, block *types.Block, blockPartsHeader types.PartSetHeade
}
// Update Validator.LastCommitHeight as necessary.
// If we panic in here, something has gone horribly wrong
for i, precommit := range block.LastValidation.Precommits {
if precommit == nil {
continue
@@ -194,9 +194,11 @@ func checkInputPubKey(acc *account.Account, in *types.TxInput) error {
func validateInputs(accounts map[string]*account.Account, signBytes []byte, ins []*types.TxInput) (total int64, err error) {
for _, in := range ins {
acc := accounts[string(in.Address)]
// SANITY CHECK
if acc == nil {
panic("validateInputs() expects account in accounts")
}
// SANITY CHECK END
err = validateInput(acc, signBytes, in)
if err != nil {
return
@@ -245,12 +247,14 @@ func validateOutputs(outs []*types.TxOutput) (total int64, err error) {
func adjustByInputs(accounts map[string]*account.Account, ins []*types.TxInput) {
for _, in := range ins {
acc := accounts[string(in.Address)]
// SANITY CHECK
if acc == nil {
panic("adjustByInputs() expects account in accounts")
}
if acc.Balance < in.Amount {
panic("adjustByInputs() expects sufficient funds")
}
// SANITY CHECK END
acc.Balance -= in.Amount
acc.Sequence += 1
}
@@ -259,9 +263,11 @@ func adjustByInputs(accounts map[string]*account.Account, ins []*types.TxInput)
func adjustByOutputs(accounts map[string]*account.Account, outs []*types.TxOutput) {
for _, out := range outs {
acc := accounts[string(out.Address)]
// SANITY CHECK
if acc == nil {
panic("adjustByOutputs() expects account in accounts")
}
// SANITY CHECK END
acc.Balance += out.Amount
}
}
@@ -270,6 +276,14 @@ func adjustByOutputs(accounts map[string]*account.Account, outs []*types.TxOutpu
// Unlike ExecBlock(), state will not be altered.
func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Fireable) error {
defer func() {
if r := recover(); r != nil {
err := errors.New(Fmt("Recovered from panic in ExecTx", "err", r, "tx", tx_))
log.Error(err.Error())
// TODO return error
}
}()
// TODO: do something with fees
fees := int64(0)
_s := blockCache.State() // hack to access validators and block height
@@ -522,7 +536,7 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
// and changing the data
if expired {
if expiresIn < types.MinNameRegistrationPeriod {
return fmt.Errorf("Names must be registered for at least %d blocks", types.MinNameRegistrationPeriod)
return errors.New(Fmt("Names must be registered for at least %d blocks", types.MinNameRegistrationPeriod))
}
entry.Expires = lastBlockHeight + expiresIn
entry.Owner = tx.Input.Address
@@ -534,7 +548,7 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
credit := oldCredit + value
expiresIn = int(credit / costPerBlock)
if expiresIn < types.MinNameRegistrationPeriod {
return fmt.Errorf("Names must be registered for at least %d blocks", types.MinNameRegistrationPeriod)
return errors.New(Fmt("Names must be registered for at least %d blocks", types.MinNameRegistrationPeriod))
}
entry.Expires = lastBlockHeight + expiresIn
log.Debug("Updated namereg entry", "name", entry.Name, "expiresIn", expiresIn, "oldCredit", oldCredit, "value", value, "credit", credit)
@@ -544,7 +558,7 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
}
} else {
if expiresIn < types.MinNameRegistrationPeriod {
return fmt.Errorf("Names must be registered for at least %d blocks", types.MinNameRegistrationPeriod)
return errors.New(Fmt("Names must be registered for at least %d blocks", types.MinNameRegistrationPeriod))
}
// entry does not exist, so create it
entry = &types.NameRegEntry{
@@ -623,6 +637,7 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
Accum: 0,
})
if !added {
// SOMETHING HAS GONE HORRIBLY WRONG
panic("Failed to add validator")
}
if evc != nil {
@@ -720,6 +735,8 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
return nil
default:
// SANITY CHECK (binary decoding should catch bad tx types
// before they get here
panic("Unknown Tx type")
}
}

View File

@@ -2,6 +2,7 @@ package state
import (
"io/ioutil"
"os"
"time"
"github.com/tendermint/tendermint/account"
@@ -34,7 +35,8 @@ func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
var err error
binary.ReadJSON(&genState, jsonBlob, &err)
if err != nil {
panic(Fmt("Couldn't read GenesisDoc: %v", err))
log.Error(Fmt("Couldn't read GenesisDoc: %v", err))
os.Exit(1)
}
return
}
@@ -42,7 +44,8 @@ func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) *State {
jsonBlob, err := ioutil.ReadFile(genDocFile)
if err != nil {
panic(Fmt("Couldn't read GenesisDoc file: %v", err))
log.Error(Fmt("Couldn't read GenesisDoc file: %v", err))
os.Exit(1)
}
genDoc := GenesisDocFromJSON(jsonBlob)
return MakeGenesisState(db, genDoc)

View File

@@ -30,6 +30,8 @@ func voteToStep(vote *types.Vote) int8 {
case types.VoteTypePrecommit:
return stepPrecommit
default:
// SANITY CHECK (binary decoding should catch bad vote types
// before they get here (right?!)
panic("Unknown vote type")
}
}
@@ -69,7 +71,7 @@ func GenPrivValidator() *PrivValidator {
func LoadPrivValidator(filePath string) *PrivValidator {
privValJSONBytes, err := ioutil.ReadFile(filePath)
if err != nil {
panic(err)
Exit(err.Error())
}
privVal := binary.ReadJSON(&PrivValidator{}, privValJSONBytes, &err).(*PrivValidator)
if err != nil {
@@ -93,6 +95,7 @@ func (privVal *PrivValidator) Save() {
func (privVal *PrivValidator) save() {
if privVal.filePath == "" {
// SANITY CHECK
panic("Cannot save PrivValidator: filePath not set")
}
jsonBytes := binary.JSONBytes(privVal)

View File

@@ -2,12 +2,12 @@ package state
import (
"bytes"
"fmt"
"io"
"time"
"github.com/tendermint/tendermint/account"
"github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/common"
dbm "github.com/tendermint/tendermint/db"
"github.com/tendermint/tendermint/events"
"github.com/tendermint/tendermint/merkle"
@@ -67,7 +67,8 @@ func LoadState(db dbm.DB) *State {
s.nameReg = merkle.NewIAVLTree(binary.BasicCodec, NameRegCodec, 0, db)
s.nameReg.Load(nameRegHash)
if *err != nil {
panic(*err)
// DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
Exit(Fmt("Data has been corrupted or its spec has changed: %v\n", *err))
}
// TODO: ensure that buf is completely read.
}
@@ -91,6 +92,7 @@ func (s *State) Save() {
binary.WriteByteSlice(s.validatorInfos.Hash(), buf, n, err)
binary.WriteByteSlice(s.nameReg.Hash(), buf, n, err)
if *err != nil {
// SOMETHING HAS GONE HORRIBLY WRONG
panic(*err)
}
s.DB.Set(stateKey, buf.Bytes())
@@ -145,6 +147,7 @@ func (s *State) ComputeBlockStateHash(block *types.Block) error {
//-------------------------------------
// State.accounts
// Returns nil if account does not exist with given address.
// The returned Account is a copy, so mutating it
// has no side effects.
// Implements Statelike
@@ -200,11 +203,13 @@ func (s *State) unbondValidator(val *Validator) {
// Move validator to UnbondingValidators
val, removed := s.BondedValidators.Remove(val.Address)
if !removed {
// SOMETHING HAS GONE HORRIBLY WRONG
panic("Couldn't remove validator for unbonding")
}
val.UnbondHeight = s.LastBlockHeight + 1
added := s.UnbondingValidators.Add(val)
if !added {
// SOMETHING HAS GONE HORRIBLY WRONG
panic("Couldn't add validator for unbonding")
}
}
@@ -213,11 +218,13 @@ func (s *State) rebondValidator(val *Validator) {
// Move validator to BondingValidators
val, removed := s.UnbondingValidators.Remove(val.Address)
if !removed {
// SOMETHING HAS GONE HORRIBLY WRONG
panic("Couldn't remove validator for rebonding")
}
val.BondHeight = s.LastBlockHeight + 1
added := s.BondedValidators.Add(val)
if !added {
// SOMETHING HAS GONE HORRIBLY WRONG
panic("Couldn't add validator for rebonding")
}
}
@@ -225,17 +232,21 @@ func (s *State) rebondValidator(val *Validator) {
func (s *State) releaseValidator(val *Validator) {
// Update validatorInfo
valInfo := s.GetValidatorInfo(val.Address)
// SANITY CHECK
if valInfo == nil {
panic("Couldn't find validatorInfo for release")
}
// SANITY CHECK END
valInfo.ReleasedHeight = s.LastBlockHeight + 1
s.SetValidatorInfo(valInfo)
// Send coins back to UnbondTo outputs
accounts, err := getOrMakeAccounts(s, nil, valInfo.UnbondTo)
// SANITY CHECK
if err != nil {
panic("Couldn't get or make unbondTo accounts")
}
// SANITY CHECK END
adjustByOutputs(accounts, valInfo.UnbondTo)
for _, acc := range accounts {
s.UpdateAccount(acc)
@@ -244,6 +255,7 @@ func (s *State) releaseValidator(val *Validator) {
// Remove validator from UnbondingValidators
_, removed := s.UnbondingValidators.Remove(val.Address)
if !removed {
// SOMETHING HAS GONE HORRIBLY WRONG
panic("Couldn't remove validator for release")
}
}
@@ -251,9 +263,11 @@ func (s *State) releaseValidator(val *Validator) {
func (s *State) destroyValidator(val *Validator) {
// Update validatorInfo
valInfo := s.GetValidatorInfo(val.Address)
// SANITY CHECK
if valInfo == nil {
panic("Couldn't find validatorInfo for release")
}
// SANITY CHECK END
valInfo.DestroyedHeight = s.LastBlockHeight + 1
valInfo.DestroyedAmount = val.VotingPower
s.SetValidatorInfo(valInfo)
@@ -263,6 +277,7 @@ func (s *State) destroyValidator(val *Validator) {
if !removed {
_, removed := s.UnbondingValidators.Remove(val.Address)
if !removed {
// SOMETHING HAS GONE HORRIBLY WRONG
panic("Couldn't remove validator for destruction")
}
}
@@ -334,5 +349,5 @@ type InvalidTxError struct {
}
func (txErr InvalidTxError) Error() string {
return fmt.Sprintf("Invalid tx: [%v] reason: [%v]", txErr.Tx, txErr.Reason)
return Fmt("Invalid tx: [%v] reason: [%v]", txErr.Tx, txErr.Reason)
}

View File

@@ -83,6 +83,7 @@ func (cache *TxCache) CreateAccount(creator *vm.Account) *vm.Account {
cache.accounts[addr] = vmAccountInfo{account, false}
return account
} else {
// NONCE HANDLING SANITY CHECK OR SHA3 IS BROKEN
panic(Fmt("Could not create account, address already exists: %X", addr))
}
}
@@ -104,10 +105,12 @@ func (cache *TxCache) GetStorage(addr Word256, key Word256) Word256 {
// NOTE: Set value to zero to removed from the trie.
func (cache *TxCache) SetStorage(addr Word256, key Word256, value Word256) {
// SANITY CHECK
_, removed := vmUnpack(cache.accounts[addr])
if removed {
panic("SetStorage() on a removed account")
}
// SANITY CHECK END
cache.storages[Tuple256{addr, key}] = value
}

View File

@@ -76,6 +76,7 @@ func (v *Validator) CompareAccum(other *Validator) *Validator {
} else if bytes.Compare(v.Address, other.Address) > 0 {
return other
} else {
// SANITY CHECK
panic("Cannot compare identical validators")
}
}