diff --git a/account/account.go b/account/account.go index 8e8cd72b5..175a7bb94 100644 --- a/account/account.go +++ b/account/account.go @@ -6,6 +6,7 @@ import ( "io" "github.com/tendermint/tendermint/binary" + . "github.com/tendermint/tendermint/common" "github.com/tendermint/tendermint/merkle" ptypes "github.com/tendermint/tendermint/permission/types" ) @@ -21,8 +22,7 @@ func SignBytes(chainID string, o Signable) []byte { buf, n, err := new(bytes.Buffer), new(int64), new(error) o.WriteSignBytes(chainID, buf, n, err) if *err != nil { - // SOMETHING HAS GONE HORRIBLY WRONG - panic(err) + PanicCrisis(err) } return buf.Bytes() } diff --git a/account/priv_account.go b/account/priv_account.go index 4e170c8f7..c97d03940 100644 --- a/account/priv_account.go +++ b/account/priv_account.go @@ -64,7 +64,7 @@ func GenPrivAccountFromSecret(secret []byte) *PrivAccount { func GenPrivAccountFromPrivKeyBytes(privKeyBytes *[64]byte) *PrivAccount { if len(privKeyBytes) != 64 { - panic(Fmt("Expected 64 bytes but got %v", len(privKeyBytes))) + PanicSanity(Fmt("Expected 64 bytes but got %v", len(privKeyBytes))) } pubKeyBytes := ed25519.MakePublicKey(privKeyBytes) pubKey := PubKeyEd25519(*pubKeyBytes) diff --git a/account/pub_key.go b/account/pub_key.go index 64f2a30c8..1a307989b 100644 --- a/account/pub_key.go +++ b/account/pub_key.go @@ -40,7 +40,7 @@ func (pubKey PubKeyEd25519) Address() []byte { w, n, err := new(bytes.Buffer), new(int64), new(error) binary.WriteBinary(pubKey[:], w, n, err) if *err != nil { - panic(*err) + PanicCrisis(*err) } // append type byte encodedPubkey := append([]byte{1}, w.Bytes()...) diff --git a/binary/binary.go b/binary/binary.go index 8a4abd6a0..d003a0435 100644 --- a/binary/binary.go +++ b/binary/binary.go @@ -5,6 +5,8 @@ import ( "errors" "io" "reflect" + + . "github.com/tendermint/tendermint/common" ) // TODO document and maybe make it configurable. @@ -37,10 +39,10 @@ func ReadBinaryPtr(o interface{}, r io.Reader, n *int64, err *error) interface{} rv, rt := reflect.ValueOf(o), reflect.TypeOf(o) if rv.Kind() == reflect.Ptr { readReflectBinary(rv.Elem(), rt.Elem(), Options{}, r, n, err) - return o } else { - panic("ReadBinaryPtr expects o to be a pointer") + PanicSanity("ReadBinaryPtr expects o to be a pointer") } + return o } func WriteBinary(o interface{}, w io.Writer, n *int64, err *error) { @@ -93,10 +95,10 @@ func ReadJSONObjectPtr(o interface{}, object interface{}, err *error) interface{ rv, rt := reflect.ValueOf(o), reflect.TypeOf(o) if rv.Kind() == reflect.Ptr { readReflectJSON(rv.Elem(), rt.Elem(), object, err) - return o } else { - panic("ReadJSON(Object)Ptr expects o to be a pointer") + PanicSanity("ReadJSON(Object)Ptr expects o to be a pointer") } + return o } func WriteJSON(o interface{}, w io.Writer, n *int64, err *error) { diff --git a/binary/codec.go b/binary/codec.go index 6397c51f8..e66fad276 100644 --- a/binary/codec.go +++ b/binary/codec.go @@ -40,8 +40,7 @@ const ( func BasicCodecEncoder(o interface{}, w io.Writer, n *int64, err *error) { switch o := o.(type) { case nil: - // SANITY CHECK - panic("nil type unsupported") + PanicSanity("nil type unsupported") case byte: WriteByte(typeByte, w, n, err) WriteByte(o, w, n, err) @@ -85,8 +84,7 @@ func BasicCodecEncoder(o interface{}, w io.Writer, n *int64, err *error) { WriteByte(typeTime, w, n, err) WriteTime(o, w, n, err) default: - // SANITY CHECK - panic(fmt.Sprintf("Unsupported type: %v", reflect.TypeOf(o))) + PanicSanity(fmt.Sprintf("Unsupported type: %v", reflect.TypeOf(o))) } } @@ -161,8 +159,7 @@ func BasicCodecComparator(o1 interface{}, o2 interface{}) int { case time.Time: return int(o1.(time.Time).UnixNano() - o2.(time.Time).UnixNano()) default: - // SANITY CHECK - panic(Fmt("Unsupported type: %v", reflect.TypeOf(o1))) + PanicSanity(Fmt("Unsupported type: %v", reflect.TypeOf(o1))) } return 0 } diff --git a/binary/reflect.go b/binary/reflect.go index a97025467..a8c160cd8 100644 --- a/binary/reflect.go +++ b/binary/reflect.go @@ -70,8 +70,7 @@ func (info StructFieldInfo) unpack() (int, reflect.Type, Options) { func GetTypeFromStructDeclaration(o interface{}) reflect.Type { rt := reflect.TypeOf(o) if rt.NumField() != 1 { - // SANITY CHECK - panic("Unexpected number of fields in struct-wrapped declaration of type") + PanicSanity("Unexpected number of fields in struct-wrapped declaration of type") } return rt.Field(0).Type } @@ -79,8 +78,7 @@ func GetTypeFromStructDeclaration(o interface{}) reflect.Type { func SetByteForType(typeByte byte, rt reflect.Type) { typeInfo := GetTypeInfo(rt) if typeInfo.Byte != 0x00 && typeInfo.Byte != typeByte { - // SANITY CHECK - panic(Fmt("Type %v already registered with type byte %X", rt, typeByte)) + PanicSanity(Fmt("Type %v already registered with type byte %X", rt, typeByte)) } typeInfo.Byte = typeByte // If pointer, we need to set it for the concrete type as well. @@ -124,8 +122,7 @@ type ConcreteType struct { func RegisterInterface(o interface{}, ctypes ...ConcreteType) *TypeInfo { it := GetTypeFromStructDeclaration(o) if it.Kind() != reflect.Interface { - // SANITY CHECK - panic("RegisterInterface expects an interface") + PanicSanity("RegisterInterface expects an interface") } toType := make(map[byte]reflect.Type, 0) toByte := make(map[reflect.Type]byte, 0) @@ -134,12 +131,10 @@ func RegisterInterface(o interface{}, ctypes ...ConcreteType) *TypeInfo { typeByte := ctype.Byte SetByteForType(typeByte, crt) if typeByte == 0x00 { - // SANITY CHECK - panic(Fmt("Byte of 0x00 is reserved for nil (%v)", ctype)) + PanicSanity(Fmt("Byte of 0x00 is reserved for nil (%v)", ctype)) } if toType[typeByte] != nil { - // SANITY CHECK - panic(Fmt("Duplicate Byte for type %v and %v", ctype, toType[typeByte])) + PanicSanity(Fmt("Duplicate Byte for type %v and %v", ctype, toType[typeByte])) } toType[typeByte] = crt toByte[crt] = typeByte @@ -398,8 +393,7 @@ func readReflectBinary(rv reflect.Value, rt reflect.Type, opts Options, r io.Rea rv.SetBool(num > 0) default: - // SANITY CHECK - panic(Fmt("Unknown field type %v", rt.Kind())) + PanicSanity(Fmt("Unknown field type %v", rt.Kind())) } } @@ -567,8 +561,7 @@ func writeReflectBinary(rv reflect.Value, rt reflect.Type, opts Options, w io.Wr } default: - // SANITY CHECK - panic(Fmt("Unknown field type %v", rt.Kind())) + PanicSanity(Fmt("Unknown field type %v", rt.Kind())) } } @@ -800,8 +793,7 @@ func readReflectJSON(rv reflect.Value, rt reflect.Type, o interface{}, err *erro rv.SetBool(bl) default: - // SANITY CHECK - panic(Fmt("Unknown field type %v", rt.Kind())) + PanicSanity(Fmt("Unknown field type %v", rt.Kind())) } } @@ -949,8 +941,7 @@ func writeReflectJSON(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, WriteTo(jsonBytes, w, n, err) default: - // SANITY CHECK - panic(Fmt("Unknown field type %v", rt.Kind())) + PanicSanity(Fmt("Unknown field type %v", rt.Kind())) } } diff --git a/binary/util.go b/binary/util.go index d03464bf1..1a4a2f417 100644 --- a/binary/util.go +++ b/binary/util.go @@ -4,15 +4,15 @@ import ( "bytes" "crypto/sha256" "github.com/tendermint/tendermint/Godeps/_workspace/src/code.google.com/p/go.crypto/ripemd160" -) -// THESE PANICS ARE SANITY CHECKS + . "github.com/tendermint/tendermint/common" +) func BinaryBytes(o interface{}) []byte { w, n, err := new(bytes.Buffer), new(int64), new(error) WriteBinary(o, w, n, err) if *err != nil { - panic(*err) + PanicSanity(*err) } return w.Bytes() } @@ -21,7 +21,7 @@ func JSONBytes(o interface{}) []byte { w, n, err := new(bytes.Buffer), new(int64), new(error) WriteJSON(o, w, n, err) if *err != nil { - panic(*err) + PanicSanity(*err) } return w.Bytes() } @@ -45,7 +45,7 @@ func BinarySha256(o interface{}) []byte { hasher, n, err := sha256.New(), new(int64), new(error) WriteBinary(o, hasher, n, err) if *err != nil { - panic(*err) + PanicSanity(*err) } return hasher.Sum(nil) } @@ -55,7 +55,7 @@ func BinaryRipemd160(o interface{}) []byte { hasher, n, err := ripemd160.New(), new(int64), new(error) WriteBinary(o, hasher, n, err) if *err != nil { - panic(*err) + PanicSanity(*err) } return hasher.Sum(nil) } diff --git a/blockchain/pool.go b/blockchain/pool.go index ab931d8f6..e15fd162a 100644 --- a/blockchain/pool.go +++ b/blockchain/pool.go @@ -126,11 +126,9 @@ func (pool *BlockPool) PopRequest() { pool.requestsMtx.Lock() // Lock defer pool.requestsMtx.Unlock() - // SANITY CHECK if r := pool.requests[pool.height]; r == nil || r.block == nil { - panic("PopRequest() requires a valid block") + PanicSanity("PopRequest() requires a valid block") } - // SANITY CHECK END delete(pool.requests, pool.height) pool.height++ @@ -143,11 +141,9 @@ func (pool *BlockPool) RedoRequest(height int) { defer pool.requestsMtx.Unlock() request := pool.requests[height] - // SANITY CHECK if request.block == nil { - panic("Expected block to be non-nil") + PanicSanity("Expected block to be non-nil") } - // SANITY CHECK END // TODO: record this malfeasance // maybe punish peer on switch (an invalid block!) pool.RemovePeer(request.peerId) // Lock on peersMtx. diff --git a/blockchain/reactor.go b/blockchain/reactor.go index ccd04773e..7c3e42264 100644 --- a/blockchain/reactor.go +++ b/blockchain/reactor.go @@ -53,12 +53,10 @@ type BlockchainReactor struct { } func NewBlockchainReactor(state *sm.State, store *BlockStore, sync bool) *BlockchainReactor { - // SANITY CHECK if state.LastBlockHeight != store.Height() && state.LastBlockHeight != store.Height()-1 { // XXX double check this logic. - panic(Fmt("state (%v) and store (%v) height mismatch", state.LastBlockHeight, store.Height())) + PanicSanity(Fmt("state (%v) and store (%v) height mismatch", state.LastBlockHeight, store.Height())) } - // SANITY CHECK END requestsCh := make(chan BlockRequest, defaultChannelCapacity) timeoutsCh := make(chan string, defaultChannelCapacity) pool := NewBlockPool( @@ -231,7 +229,7 @@ FOR_LOOP: err := sm.ExecBlock(bcR.state, first, firstPartsHeader) if err != nil { // TODO This is bad, are we zombie? - panic(Fmt("Failed to process committed block: %v", err)) + PanicQ(Fmt("Failed to process committed block: %v", err)) } bcR.store.SaveBlock(first, firstParts, second.LastValidation) bcR.state.Save() diff --git a/blockchain/store.go b/blockchain/store.go index 74afc3295..54e5f475d 100644 --- a/blockchain/store.go +++ b/blockchain/store.go @@ -61,8 +61,7 @@ func (bs *BlockStore) LoadBlock(height int) *types.Block { } meta := binary.ReadBinary(&types.BlockMeta{}, r, &n, &err).(*types.BlockMeta) if err != nil { - // SOMETHING HAS GONE HORRIBLY WRONG - panic(Fmt("Error reading block meta: %v", err)) + PanicCrisis(Fmt("Error reading block meta: %v", err)) } bytez := []byte{} for i := 0; i < meta.PartsHeader.Total; i++ { @@ -71,8 +70,7 @@ func (bs *BlockStore) LoadBlock(height int) *types.Block { } block := binary.ReadBinary(&types.Block{}, bytes.NewReader(bytez), &n, &err).(*types.Block) if err != nil { - // SOMETHING HAS GONE HORRIBLY WRONG - panic(Fmt("Error reading block: %v", err)) + PanicCrisis(Fmt("Error reading block: %v", err)) } return block } @@ -86,8 +84,7 @@ func (bs *BlockStore) LoadBlockPart(height int, index int) *types.Part { } part := binary.ReadBinary(&types.Part{}, r, &n, &err).(*types.Part) if err != nil { - // SOMETHING HAS GONE HORRIBLY WRONG - panic(Fmt("Error reading block part: %v", err)) + PanicCrisis(Fmt("Error reading block part: %v", err)) } return part } @@ -101,8 +98,7 @@ func (bs *BlockStore) LoadBlockMeta(height int) *types.BlockMeta { } meta := binary.ReadBinary(&types.BlockMeta{}, r, &n, &err).(*types.BlockMeta) if err != nil { - // SOMETHING HAS GONE HORRIBLY WRONG - panic(Fmt("Error reading block meta: %v", err)) + PanicCrisis(Fmt("Error reading block meta: %v", err)) } return meta } @@ -118,8 +114,7 @@ func (bs *BlockStore) LoadBlockValidation(height int) *types.Validation { } validation := binary.ReadBinary(&types.Validation{}, r, &n, &err).(*types.Validation) if err != nil { - // SOMETHING HAS GONE HORRIBLY WRONG - panic(Fmt("Error reading validation: %v", err)) + PanicCrisis(Fmt("Error reading validation: %v", err)) } return validation } @@ -134,8 +129,7 @@ func (bs *BlockStore) LoadSeenValidation(height int) *types.Validation { } validation := binary.ReadBinary(&types.Validation{}, r, &n, &err).(*types.Validation) if err != nil { - // SOMETHING HAS GONE HORRIBLY WRONG - panic(Fmt("Error reading validation: %v", err)) + PanicCrisis(Fmt("Error reading validation: %v", err)) } return validation } @@ -148,12 +142,10 @@ func (bs *BlockStore) LoadSeenValidation(height int) *types.Validation { func (bs *BlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, seenValidation *types.Validation) { height := block.Height if height != bs.height+1 { - // SANITY CHECK - panic(Fmt("BlockStore can only save contiguous blocks. Wanted %v, got %v", bs.height+1, height)) + PanicSanity(Fmt("BlockStore can only save contiguous blocks. Wanted %v, got %v", bs.height+1, height)) } if !blockParts.IsComplete() { - // SANITY CHECK - panic(Fmt("BlockStore can only save complete block part sets")) + PanicSanity(Fmt("BlockStore can only save complete block part sets")) } // Save block meta @@ -182,11 +174,9 @@ func (bs *BlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, s } func (bs *BlockStore) saveBlockPart(height int, index int, part *types.Part) { - // SANITY CHECK if height != bs.height+1 { - panic(Fmt("BlockStore can only save contiguous blocks. Wanted %v, got %v", bs.height+1, height)) + PanicSanity(Fmt("BlockStore can only save contiguous blocks. Wanted %v, got %v", bs.height+1, height)) } - // SANITY CHECK END partBytes := binary.BinaryBytes(part) bs.db.Set(calcBlockPartKey(height, index), partBytes) } @@ -220,8 +210,7 @@ type BlockStoreStateJSON struct { func (bsj BlockStoreStateJSON) Save(db dbm.DB) { bytes, err := json.Marshal(bsj) if err != nil { - // SANITY CHECK - panic(Fmt("Could not marshal state bytes: %v", err)) + PanicSanity(Fmt("Could not marshal state bytes: %v", err)) } db.Set(blockStoreKey, bytes) } @@ -236,8 +225,7 @@ func LoadBlockStoreStateJSON(db dbm.DB) BlockStoreStateJSON { bsj := BlockStoreStateJSON{} err := json.Unmarshal(bytes, &bsj) if err != nil { - // SOMETHING HAS GONE HORRIBLY WRONG - panic(Fmt("Could not unmarshal bytes: %X", bytes)) + PanicCrisis(Fmt("Could not unmarshal bytes: %X", bytes)) } return bsj } diff --git a/common/bit_array.go b/common/bit_array.go index 320b629ef..dc006f0eb 100644 --- a/common/bit_array.go +++ b/common/bit_array.go @@ -209,7 +209,7 @@ func (bA *BitArray) PickRandom() (int, bool) { return 64*elemIdx + bitIdx, true } } - panic("should not happen") + PanicSanity("should not happen") } } else { // Special case for last elem, to ignore straggler bits diff --git a/common/errors.go b/common/errors.go index a3312e97f..e168a75b7 100644 --- a/common/errors.go +++ b/common/errors.go @@ -16,3 +16,30 @@ func (se StackError) String() string { func (se StackError) Error() string { return se.String() } + +//-------------------------------------------------------------------------------------------------- +// panic wrappers + +// A panic resulting from a sanity check means there is a programmer error +// and some gaurantee is not satisfied. +func PanicSanity(v interface{}) { + panic(Fmt("Paniced on a Sanity Check: %v", v)) +} + +// A panic here means something has gone horribly wrong, in the form of data corruption or +// failure of the operating system. In a correct/healthy system, these should never fire. +// If they do, it's indicative of a much more serious problem. +func PanicCrisis(v interface{}) { + panic(Fmt("Paniced on a Crisis: %v", v)) +} + +// Indicates a failure of consensus. Someone was malicious or something has +// gone horribly wrong. These should really boot us into an "emergency-recover" mode +func PanicConsensus(v interface{}) { + panic(Fmt("Paniced on a Consensus Failure: %v", v)) +} + +// For those times when we're not sure if we should panic +func PanicQ(v interface{}) { + panic(Fmt("Paniced questionably: %v", v)) +} diff --git a/common/random.go b/common/random.go index e1d6046d6..645601154 100644 --- a/common/random.go +++ b/common/random.go @@ -134,7 +134,7 @@ func CRandBytes(numBytes int) []byte { b := make([]byte, numBytes) _, err := crand.Read(b) if err != nil { - panic(err) + PanicCrisis(err) } return b } diff --git a/consensus/height_vote_set.go b/consensus/height_vote_set.go index 52c0b8a42..279bf5471 100644 --- a/consensus/height_vote_set.go +++ b/consensus/height_vote_set.go @@ -63,7 +63,7 @@ func (hvs *HeightVoteSet) SetRound(round int) { hvs.mtx.Lock() defer hvs.mtx.Unlock() if hvs.round != 0 && (round < hvs.round+1) { - panic("SetRound() must increment hvs.round") + PanicSanity("SetRound() must increment hvs.round") } for r := hvs.round + 1; r <= round; r++ { if _, ok := hvs.roundVoteSets[r]; ok { @@ -76,7 +76,7 @@ func (hvs *HeightVoteSet) SetRound(round int) { func (hvs *HeightVoteSet) addRound(round int) { if _, ok := hvs.roundVoteSets[round]; ok { - panic("addRound() for an existing round") + PanicSanity("addRound() for an existing round") } log.Info("addRound(round)", "round", round) prevotes := NewVoteSet(hvs.height, round, types.VoteTypePrevote, hvs.valSet) @@ -146,7 +146,8 @@ func (hvs *HeightVoteSet) getVoteSet(round int, type_ byte) *VoteSet { case types.VoteTypePrecommit: return rvs.Precommits default: - panic(Fmt("Unexpected vote type %X", type_)) + PanicSanity(Fmt("Unexpected vote type %X", type_)) + return nil } } diff --git a/consensus/reactor.go b/consensus/reactor.go index b45670d80..d63840fa8 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -669,7 +669,7 @@ func (ps *PeerState) getVoteBitArray(height, round int, type_ byte) *BitArray { case types.VoteTypePrecommit: return ps.Precommits default: - panic(Fmt("Unexpected vote type %X", type_)) + PanicSanity(Fmt("Unexpected vote type %X", type_)) } } if ps.CatchupCommitRound == round { @@ -679,7 +679,7 @@ func (ps *PeerState) getVoteBitArray(height, round int, type_ byte) *BitArray { case types.VoteTypePrecommit: return ps.CatchupCommit default: - panic(Fmt("Unexpected vote type %X", type_)) + PanicSanity(Fmt("Unexpected vote type %X", type_)) } } return nil @@ -692,7 +692,7 @@ func (ps *PeerState) getVoteBitArray(height, round int, type_ byte) *BitArray { case types.VoteTypePrecommit: return ps.LastCommit default: - panic(Fmt("Unexpected vote type %X", type_)) + PanicSanity(Fmt("Unexpected vote type %X", type_)) } } return nil @@ -706,7 +706,7 @@ func (ps *PeerState) ensureCatchupCommitRound(height, round int, numValidators i return } if ps.CatchupCommitRound != -1 && ps.CatchupCommitRound != round { - panic(Fmt("Conflicting CatchupCommitRound. Height: %v, Orig: %v, New: %v", height, ps.CatchupCommitRound, round)) + PanicSanity(Fmt("Conflicting CatchupCommitRound. Height: %v, Orig: %v, New: %v", height, ps.CatchupCommitRound, round)) } if ps.CatchupCommitRound == round { return // Nothing to do! @@ -758,7 +758,7 @@ func (ps *PeerState) SetHasVote(vote *types.Vote, index int) { func (ps *PeerState) setHasVote(height int, round int, type_ byte, index int) { log := log.New("peer", ps.Peer.Key, "peerRound", ps.Round, "height", height, "round", round) if type_ != types.VoteTypePrevote && type_ != types.VoteTypePrecommit { - panic("Invalid vote type") // SANITY + PanicSanity("Invalid vote type") } if ps.Height == height { diff --git a/consensus/state.go b/consensus/state.go index 3fabfebd4..12479a76e 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -330,11 +330,11 @@ func (cs *ConsensusState) reconstructLastCommit(state *sm.State) { } added, _, err := lastPrecommits.AddByIndex(idx, precommit) if !added || err != nil { - panic(Fmt("Failed to reconstruct LastCommit: %v", err)) + PanicCrisis(Fmt("Failed to reconstruct LastCommit: %v", err)) } } if !lastPrecommits.HasTwoThirdsMajority() { - panic("Failed to reconstruct LastCommit: Does not have +2/3 maj") + PanicSanity("Failed to reconstruct LastCommit: Does not have +2/3 maj") } cs.LastCommit = lastPrecommits } @@ -383,18 +383,16 @@ func (cs *ConsensusState) scheduleRound0(height int) { // Updates ConsensusState and increments height to match that of state. // The round becomes 0 and cs.Step becomes RoundStepNewHeight. func (cs *ConsensusState) updateToState(state *sm.State, contiguous bool) { - // SANITY CHECK if contiguous && 0 < cs.Height && cs.Height != state.LastBlockHeight { - panic(Fmt("updateToState() expected state height of %v but found %v", + PanicSanity(Fmt("updateToState() expected state height of %v but found %v", cs.Height, state.LastBlockHeight)) } if cs.state != nil && cs.state.LastBlockHeight+1 != cs.Height { // This might happen when someone else is mutating cs.state. // Someone forgot to pass in state.Copy() somewhere?! - panic(Fmt("Inconsistent cs.state.LastBlockHeight+1 %v vs cs.Height %v", + PanicSanity(Fmt("Inconsistent cs.state.LastBlockHeight+1 %v vs cs.Height %v", cs.state.LastBlockHeight+1, cs.Height)) } - // END SANITY CHECK // If state isn't further out than cs.state, just ignore. // This happens when SwitchToConsensus() is called in the reactor. @@ -410,7 +408,7 @@ func (cs *ConsensusState) updateToState(state *sm.State, contiguous bool) { lastPrecommits := (*VoteSet)(nil) if contiguous && cs.Votes != nil { if !cs.Votes.Precommits(cs.Round).HasTwoThirdsMajority() { - panic("updateToState(state, true) called but last Precommit round didn't have +2/3") + PanicSanity("updateToState(state, true) called but last Precommit round didn't have +2/3") } lastPrecommits = cs.Votes.Precommits(cs.Round) } @@ -717,7 +715,7 @@ func (cs *ConsensusState) EnterPrevoteWait(height int, round int) { return } if !cs.Votes.Prevotes(round).HasTwoThirdsAny() { - panic(Fmt("EnterPrevoteWait(%v/%v), but Prevotes does not have any +2/3 votes", height, round)) + PanicSanity(Fmt("EnterPrevoteWait(%v/%v), but Prevotes does not have any +2/3 votes", height, round)) } log.Info(Fmt("EnterPrevoteWait(%v/%v). Current: %v/%v/%v", height, round, cs.Height, cs.Round, cs.Step)) @@ -801,7 +799,7 @@ func (cs *ConsensusState) EnterPrecommit(height int, round int) { log.Info("EnterPrecommit: +2/3 prevoted proposal block.") // Validate the block. if err := cs.stageBlock(cs.ProposalBlock, cs.ProposalBlockParts); err != nil { - panic(Fmt("EnterPrecommit: +2/3 prevoted for an invalid block: %v", err)) + PanicConsensus(Fmt("EnterPrecommit: +2/3 prevoted for an invalid block: %v", err)) } cs.LockedRound = round cs.LockedBlock = cs.ProposalBlock @@ -814,7 +812,7 @@ func (cs *ConsensusState) EnterPrecommit(height int, round int) { // Unlock and precommit nil. // The +2/3 prevotes for this round is the POL for our unlock. if cs.Votes.POLRound() < round { - panic(Fmt("This POLRound shold be %v but got %", round, cs.Votes.POLRound())) + PanicSanity(Fmt("This POLRound shold be %v but got %", round, cs.Votes.POLRound())) } cs.LockedRound = 0 cs.LockedBlock = nil @@ -836,7 +834,7 @@ func (cs *ConsensusState) EnterPrecommitWait(height int, round int) { return } if !cs.Votes.Precommits(round).HasTwoThirdsAny() { - panic(Fmt("EnterPrecommitWait(%v/%v), but Precommits does not have any +2/3 votes", height, round)) + PanicSanity(Fmt("EnterPrecommitWait(%v/%v), but Precommits does not have any +2/3 votes", height, round)) } log.Info(Fmt("EnterPrecommitWait(%v/%v). Current: %v/%v/%v", height, round, cs.Height, cs.Round, cs.Step)) @@ -876,12 +874,10 @@ func (cs *ConsensusState) EnterCommit(height int) { cs.tryFinalizeCommit(height) }() - // SANITY CHECK hash, partsHeader, ok := cs.Votes.Precommits(cs.Round).TwoThirdsMajority() if !ok { - panic("RunActionCommit() expects +2/3 precommits") + PanicSanity("RunActionCommit() expects +2/3 precommits") } - // END SANITY CHECK // The Locked* fields no longer matter. // Move them over to ProposalBlock if they match the commit hash, @@ -913,11 +909,9 @@ func (cs *ConsensusState) EnterCommit(height int) { // If we have the block AND +2/3 commits for it, finalize. func (cs *ConsensusState) tryFinalizeCommit(height int) { - // SANITY CHECK if cs.Height != height { - panic(Fmt("tryFinalizeCommit() cs.Height: %v vs height: %v", cs.Height, height)) + PanicSanity(Fmt("tryFinalizeCommit() cs.Height: %v vs height: %v", cs.Height, height)) } - // END SANITY CHECK hash, _, ok := cs.Votes.Precommits(cs.Round).TwoThirdsMajority() if !ok || len(hash) == 0 { @@ -941,20 +935,18 @@ func (cs *ConsensusState) FinalizeCommit(height int) { hash, header, ok := cs.Votes.Precommits(cs.Round).TwoThirdsMajority() - // SANITY CHECK if !ok { - panic(Fmt("Cannot FinalizeCommit, commit does not have two thirds majority")) + PanicSanity(Fmt("Cannot FinalizeCommit, commit does not have two thirds majority")) } if !cs.ProposalBlockParts.HasHeader(header) { - panic(Fmt("Expected ProposalBlockParts header to be commit header")) + PanicSanity(Fmt("Expected ProposalBlockParts header to be commit header")) } if !cs.ProposalBlock.HashesTo(hash) { - panic(Fmt("Cannot FinalizeCommit, ProposalBlock does not hash to commit hash")) + PanicSanity(Fmt("Cannot FinalizeCommit, ProposalBlock does not hash to commit hash")) } if err := cs.stageBlock(cs.ProposalBlock, cs.ProposalBlockParts); err != nil { - panic(Fmt("+2/3 committed an invalid block: %v", err)) + PanicConsensus(Fmt("+2/3 committed an invalid block: %v", err)) } - // END SANITY CHECK log.Info(Fmt("Finalizing commit of block: %v", cs.ProposalBlock)) // We have the block, so stage/save/commit-vote. @@ -1132,7 +1124,7 @@ func (cs *ConsensusState) addVote(address []byte, vote *types.Vote, peerKey stri }() } default: - panic(Fmt("Unexpected vote type %X", vote.Type)) // Should not happen. + PanicSanity(Fmt("Unexpected vote type %X", vote.Type)) // Should not happen. } } // Either duplicate, or error upon cs.Votes.AddByAddress() @@ -1146,7 +1138,7 @@ func (cs *ConsensusState) addVote(address []byte, vote *types.Vote, peerKey stri func (cs *ConsensusState) stageBlock(block *types.Block, blockParts *types.PartSet) error { if block == nil { - panic("Cannot stage nil block") + PanicSanity("Cannot stage nil block") } // Already staged? @@ -1200,7 +1192,7 @@ func (cs *ConsensusState) saveBlock(block *types.Block, blockParts *types.PartSe // The proposal must be valid. if err := cs.stageBlock(block, blockParts); err != nil { - panic(Fmt("saveBlock() an invalid block: %v", err)) + PanicSanity(Fmt("saveBlock() an invalid block: %v", err)) } // Save to blockStore. diff --git a/consensus/vote_set.go b/consensus/vote_set.go index a12416fdd..e2fec51b5 100644 --- a/consensus/vote_set.go +++ b/consensus/vote_set.go @@ -37,7 +37,7 @@ type VoteSet struct { // Constructs a new VoteSet struct used to accumulate votes for given height/round. func NewVoteSet(height int, round int, type_ byte, valSet *sm.ValidatorSet) *VoteSet { if height == 0 { - panic("Cannot make VoteSet for height == 0, doesn't make sense.") + PanicSanity("Cannot make VoteSet for height == 0, doesn't make sense.") } return &VoteSet{ height: height, @@ -187,7 +187,7 @@ func (voteSet *VoteSet) GetByAddress(address []byte) *types.Vote { defer voteSet.mtx.Unlock() valIndex, val := voteSet.valSet.GetByAddress(address) if val == nil { - panic("GetByAddress(address) returned nil") + PanicSanity("GetByAddress(address) returned nil") } return voteSet.votes[valIndex] } @@ -273,12 +273,12 @@ func (voteSet *VoteSet) StringShort() string { func (voteSet *VoteSet) MakeValidation() *types.Validation { if voteSet.type_ != types.VoteTypePrecommit { - panic("Cannot MakeValidation() unless VoteSet.Type is types.VoteTypePrecommit") + PanicSanity("Cannot MakeValidation() unless VoteSet.Type is types.VoteTypePrecommit") } voteSet.mtx.Lock() defer voteSet.mtx.Unlock() if len(voteSet.maj23Hash) == 0 { - panic("Cannot MakeValidation() unless a blockhash has +2/3") + PanicSanity("Cannot MakeValidation() unless a blockhash has +2/3") } precommits := make([]*types.Vote, voteSet.valSet.Size()) voteSet.valSet.Iterate(func(valIndex int, val *sm.Validator) bool { diff --git a/db/db.go b/db/db.go index 5f959247a..7c2bdaaeb 100644 --- a/db/db.go +++ b/db/db.go @@ -39,11 +39,12 @@ func GetDB(name string) DB { case DBBackendLevelDB: db, err := NewLevelDB(path.Join(config.GetString("db_dir"), name+".db")) if err != nil { - panic(err) + PanicCrisis(err) } dbs.Set(name, db) return db default: - panic(Fmt("Unknown DB backend: %v", config.GetString("db_backend"))) + PanicSanity(Fmt("Unknown DB backend: %v", config.GetString("db_backend"))) } + return nil } diff --git a/db/level_db.go b/db/level_db.go index 2a7621917..a8a6735c3 100644 --- a/db/level_db.go +++ b/db/level_db.go @@ -6,6 +6,8 @@ import ( "github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" "github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" "path" + + . "github.com/tendermint/tendermint/common" ) type LevelDB struct { @@ -28,7 +30,7 @@ func (db *LevelDB) Get(key []byte) []byte { if err == errors.ErrNotFound { return nil } else { - panic(err) + PanicCrisis(err) } } return res @@ -37,28 +39,28 @@ func (db *LevelDB) Get(key []byte) []byte { func (db *LevelDB) Set(key []byte, value []byte) { err := db.db.Put(key, value, nil) if err != nil { - panic(err) + PanicCrisis(err) } } func (db *LevelDB) SetSync(key []byte, value []byte) { err := db.db.Put(key, value, &opt.WriteOptions{Sync: true}) if err != nil { - panic(err) + PanicCrisis(err) } } func (db *LevelDB) Delete(key []byte) { err := db.db.Delete(key, nil) if err != nil { - panic(err) + PanicCrisis(err) } } func (db *LevelDB) DeleteSync(key []byte) { err := db.db.Delete(key, &opt.WriteOptions{Sync: true}) if err != nil { - panic(err) + PanicCrisis(err) } } diff --git a/merkle/iavl_node.go b/merkle/iavl_node.go index 0055f6717..4fc04ef28 100644 --- a/merkle/iavl_node.go +++ b/merkle/iavl_node.go @@ -6,6 +6,7 @@ import ( "io" "github.com/tendermint/tendermint/binary" + . "github.com/tendermint/tendermint/common" ) // Node @@ -50,15 +51,12 @@ func ReadIAVLNode(t *IAVLTree, r io.Reader, n *int64, err *error) *IAVLNode { node.leftHash = binary.ReadByteSlice(r, n, err) node.rightHash = binary.ReadByteSlice(r, n, err) } - if *err != nil { - panic(*err) - } return node } func (node *IAVLNode) _copy() *IAVLNode { if node.height == 0 { - panic("Why are you copying a value node?") + PanicSanity("Why are you copying a value node?") } return &IAVLNode{ key: node.key, @@ -112,7 +110,8 @@ func (node *IAVLNode) getByIndex(t *IAVLTree, index int) (key interface{}, value if index == 0 { return node.key, node.value } else { - panic("getByIndex asked for invalid index") + PanicSanity("getByIndex asked for invalid index") + return nil, nil } } else { // TODO: could improve this by storing the @@ -136,7 +135,7 @@ func (node *IAVLNode) hashWithCount(t *IAVLTree) ([]byte, int) { buf := new(bytes.Buffer) _, hashCount, err := node.writeHashBytes(t, buf) if err != nil { - panic(err) + PanicCrisis(err) } // fmt.Printf("Wrote IAVL hash bytes: %X\n", buf.Bytes()) hasher.Write(buf.Bytes()) @@ -165,7 +164,7 @@ func (node *IAVLNode) writeHashBytes(t *IAVLTree, w io.Writer) (n int64, hashCou hashCount += leftCount } if node.leftHash == nil { - panic("node.leftHash was nil in writeHashBytes") + PanicSanity("node.leftHash was nil in writeHashBytes") } binary.WriteByteSlice(node.leftHash, w, &n, &err) // right @@ -175,7 +174,7 @@ func (node *IAVLNode) writeHashBytes(t *IAVLTree, w io.Writer) (n int64, hashCou hashCount += rightCount } if node.rightHash == nil { - panic("node.rightHash was nil in writeHashBytes") + PanicSanity("node.rightHash was nil in writeHashBytes") } binary.WriteByteSlice(node.rightHash, w, &n, &err) } @@ -221,12 +220,12 @@ func (node *IAVLNode) writePersistBytes(t *IAVLTree, w io.Writer) (n int64, err } else { // left if node.leftHash == nil { - panic("node.leftHash was nil in writePersistBytes") + PanicSanity("node.leftHash was nil in writePersistBytes") } binary.WriteByteSlice(node.leftHash, w, &n, &err) // right if node.rightHash == nil { - panic("node.rightHash was nil in writePersistBytes") + PanicSanity("node.rightHash was nil in writePersistBytes") } binary.WriteByteSlice(node.rightHash, w, &n, &err) } diff --git a/merkle/iavl_proof.go b/merkle/iavl_proof.go index 4216c6c11..58d8468b3 100644 --- a/merkle/iavl_proof.go +++ b/merkle/iavl_proof.go @@ -56,7 +56,7 @@ func (branch IAVLProofInnerNode) Hash(childHash []byte) []byte { binary.WriteByteSlice(childHash, buf, &n, &err) } if err != nil { - panic(Fmt("Failed to hash IAVLProofInnerNode: %v", err)) + PanicCrisis(Fmt("Failed to hash IAVLProofInnerNode: %v", err)) } // fmt.Printf("InnerNode hash bytes: %X\n", buf.Bytes()) hasher.Write(buf.Bytes()) @@ -77,7 +77,7 @@ func (leaf IAVLProofLeafNode) Hash() []byte { binary.WriteByteSlice(leaf.KeyBytes, buf, &n, &err) binary.WriteByteSlice(leaf.ValueBytes, buf, &n, &err) if err != nil { - panic(Fmt("Failed to hash IAVLProofLeafNode: %v", err)) + PanicCrisis(Fmt("Failed to hash IAVLProofLeafNode: %v", err)) } // fmt.Printf("LeafNode hash bytes: %X\n", buf.Bytes()) hasher.Write(buf.Bytes()) @@ -91,11 +91,11 @@ func (node *IAVLNode) constructProof(t *IAVLTree, key interface{}, proof *IAVLPr n, err := int64(0), error(nil) t.keyCodec.Encode(node.key, keyBuf, &n, &err) if err != nil { - panic(Fmt("Failed to encode node.key: %v", err)) + PanicCrisis(Fmt("Failed to encode node.key: %v", err)) } t.valueCodec.Encode(node.value, valueBuf, &n, &err) if err != nil { - panic(Fmt("Failed to encode node.value: %v", err)) + PanicCrisis(Fmt("Failed to encode node.value: %v", err)) } leaf := IAVLProofLeafNode{ KeyBytes: keyBuf.Bytes(), diff --git a/merkle/iavl_tree.go b/merkle/iavl_tree.go index 144ae9b6a..19f9c6cdf 100644 --- a/merkle/iavl_tree.go +++ b/merkle/iavl_tree.go @@ -54,7 +54,7 @@ func (t *IAVLTree) Copy() Tree { // It sets all the hashes recursively, // clears all the leftNode/rightNode values recursively, // and all the .persisted flags get set. - panic("It is unsafe to Copy() an unpersisted tree.") + PanicSanity("It is unsafe to Copy() an unpersisted tree.") } else if t.ndb == nil && t.root.hash == nil { // An in-memory IAVLTree is finalized when the hashes are // calculated. @@ -211,14 +211,14 @@ func (ndb *nodeDB) GetNode(t *IAVLTree, hash []byte) *IAVLNode { buf := ndb.db.Get(hash) if len(buf) == 0 { ndb.db.(*dbm.LevelDB).Print() - panic(Fmt("Value missing for key %X", hash)) + PanicSanity(Fmt("Value missing for key %X", hash)) } r := bytes.NewReader(buf) var n int64 var err error node := ReadIAVLNode(t, r, &n, &err) if err != nil { - panic(Fmt("Error reading IAVLNode. bytes: %X error: %v", buf, err)) + PanicCrisis(Fmt("Error reading IAVLNode. bytes: %X error: %v", buf, err)) } node.hash = hash node.persisted = true @@ -231,10 +231,10 @@ func (ndb *nodeDB) SaveNode(t *IAVLTree, node *IAVLNode) { ndb.mtx.Lock() defer ndb.mtx.Unlock() if node.hash == nil { - panic("Expected to find node.hash, but none found.") + PanicSanity("Expected to find node.hash, but none found.") } if node.persisted { - panic("Shouldn't be calling save on an already persisted node.") + PanicSanity("Shouldn't be calling save on an already persisted node.") } /*if _, ok := ndb.cache[string(node.hash)]; ok { panic("Shouldn't be calling save on an already cached node.") @@ -243,7 +243,7 @@ func (ndb *nodeDB) SaveNode(t *IAVLTree, node *IAVLNode) { buf := bytes.NewBuffer(nil) _, err := node.writePersistBytes(t, buf) if err != nil { - panic(err) + PanicCrisis(err) } ndb.db.Set(node.hash, buf.Bytes()) node.persisted = true diff --git a/merkle/simple_tree.go b/merkle/simple_tree.go index ad75393c3..42a7de6c2 100644 --- a/merkle/simple_tree.go +++ b/merkle/simple_tree.go @@ -31,6 +31,7 @@ import ( "github.com/tendermint/tendermint/Godeps/_workspace/src/code.google.com/p/go.crypto/ripemd160" "github.com/tendermint/tendermint/binary" + . "github.com/tendermint/tendermint/common" ) func SimpleHashFromTwoHashes(left []byte, right []byte) []byte { @@ -40,7 +41,7 @@ func SimpleHashFromTwoHashes(left []byte, right []byte) []byte { binary.WriteByteSlice(left, hasher, &n, &err) binary.WriteByteSlice(right, hasher, &n, &err) if err != nil { - panic(err) + PanicCrisis(err) } return hasher.Sum(nil) } @@ -73,7 +74,7 @@ func SimpleHashFromBinary(item interface{}) []byte { hasher, n, err := ripemd160.New(), new(int64), new(error) binary.WriteBinary(item, hasher, n, err) if *err != nil { - panic(err) + PanicCrisis(err) } return hasher.Sum(nil) } @@ -162,7 +163,8 @@ func computeHashFromInnerHashes(index int, total int, leafHash []byte, innerHash } switch total { case 0: - panic("Cannot call computeHashFromInnerHashes() with 0 total") + PanicSanity("Cannot call computeHashFromInnerHashes() with 0 total") + return nil case 1: if len(innerHashes) != 0 { return nil diff --git a/node/node.go b/node/node.go index c4a259f76..24da8e84e 100644 --- a/node/node.go +++ b/node/node.go @@ -66,14 +66,16 @@ func NewNode() *Node { binary.WriteJSON(genDoc, buf, n, err) stateDB.Set(sm.GenDocKey, buf.Bytes()) if *err != nil { - panic(Fmt("Unable to write gendoc to db: %v", err)) + log.Error("Unable to write gendoc to db", "error", err) + os.Exit(1) } } else { genDocBytes := stateDB.Get(sm.GenDocKey) err := new(error) binary.ReadJSONPtr(&genDoc, genDocBytes, err) if *err != nil { - panic(Fmt("Unable to read gendoc from db: %v", err)) + log.Error("Unable to read gendoc from db", "error", err) + os.Exit(1) } } // add the chainid to the global config @@ -204,7 +206,7 @@ func (n *Node) dialSeed(addr *p2p.NetAddress) { } } -func (n *Node) StartRPC() net.Listener { +func (n *Node) StartRPC() (net.Listener, error) { core.SetBlockStore(n.blockStore) core.SetConsensusState(n.consensusState) core.SetConsensusReactor(n.consensusReactor) @@ -217,11 +219,7 @@ func (n *Node) StartRPC() net.Listener { mux := http.NewServeMux() rpcserver.RegisterEventsHandler(mux, n.evsw) rpcserver.RegisterRPCFuncs(mux, core.Routes) - listener, err := rpcserver.StartHTTPServer(listenAddr, mux) - if err != nil { - panic(err) - } - return listener + return rpcserver.StartHTTPServer(listenAddr, mux) } func (n *Node) Switch() *p2p.Switch { @@ -269,7 +267,7 @@ func makeNodeInfo(sw *p2p.Switch, privKey acm.PrivKeyEd25519) *types.NodeInfo { _, rpcPortStr, _ := net.SplitHostPort(rpcListenAddr) rpcPort, err := strconv.Atoi(rpcPortStr) if err != nil { - panic(Fmt("Expected numeric RPC.ListenAddr port but got %v", rpcPortStr)) + PanicSanity(Fmt("Expected numeric RPC.ListenAddr port but got %v", rpcPortStr)) } // We assume that the rpcListener has the same ExternalAddress. @@ -299,7 +297,10 @@ func RunNode() { // Run the RPC server. if config.GetString("rpc_laddr") != "" { - n.StartRPC() + _, err := n.StartRPC() + if err != nil { + PanicCrisis(err) + } } // Sleep forever and then... diff --git a/p2p/addrbook.go b/p2p/addrbook.go index 6397e7042..a9e471339 100644 --- a/p2p/addrbook.go +++ b/p2p/addrbook.go @@ -200,7 +200,7 @@ func (a *AddrBook) PickAddress(newBias int) *NetAddress { } randIndex-- } - panic("Should not happen") + PanicSanity("Should not happen") } else { // pick random New bucket. var bucket map[string]*knownAddress = nil @@ -215,7 +215,7 @@ func (a *AddrBook) PickAddress(newBias int) *NetAddress { } randIndex-- } - panic("Should not happen") + PanicSanity("Should not happen") } return nil } @@ -332,14 +332,14 @@ func (a *AddrBook) loadFromFile(filePath string) bool { // Load addrBookJSON{} r, err := os.Open(filePath) if err != nil { - panic(Fmt("Error opening file %s: %v", filePath, err)) + PanicCrisis(Fmt("Error opening file %s: %v", filePath, err)) } defer r.Close() aJSON := &addrBookJSON{} dec := json.NewDecoder(r) err = dec.Decode(aJSON) if err != nil { - panic(Fmt("Error reading file %s: %v", filePath, err)) + PanicCrisis(Fmt("Error reading file %s: %v", filePath, err)) } // Restore all the fields... @@ -388,7 +388,8 @@ func (a *AddrBook) getBucket(bucketType byte, bucketIdx int) map[string]*knownAd case bucketTypeOld: return a.addrOld[bucketIdx] default: - panic("Should not happen") + PanicSanity("Should not happen") + return nil } } diff --git a/p2p/connection.go b/p2p/connection.go index 9fcb9831f..48940b24a 100644 --- a/p2p/connection.go +++ b/p2p/connection.go @@ -420,7 +420,7 @@ FOR_LOOP: } channel, ok := c.channelsIdx[pkt.ChannelId] if !ok || channel == nil { - panic(Fmt("Unknown channel %X", pkt.ChannelId)) + PanicQ(Fmt("Unknown channel %X", pkt.ChannelId)) } msgBytes, err := channel.recvMsgPacket(pkt) if err != nil { @@ -435,7 +435,7 @@ FOR_LOOP: c.onReceive(pkt.ChannelId, msgBytes) } default: - panic(Fmt("Unknown message type %X", pktType)) + PanicSanity(Fmt("Unknown message type %X", pktType)) } // TODO: shouldn't this go in the sendRoutine? @@ -485,7 +485,7 @@ type Channel struct { func newChannel(conn *MConnection, desc *ChannelDescriptor) *Channel { desc.FillDefaults() if desc.Priority <= 0 { - panic("Channel default priority must be a postive integer") + PanicSanity("Channel default priority must be a postive integer") } return &Channel{ conn: conn, diff --git a/p2p/listener.go b/p2p/listener.go index 95dddc80d..67f3dded2 100644 --- a/p2p/listener.go +++ b/p2p/listener.go @@ -35,11 +35,11 @@ const ( func splitHostPort(addr string) (host string, port int) { host, portStr, err := net.SplitHostPort(addr) if err != nil { - panic(err) + PanicSanity(err) } port, err = strconv.Atoi(portStr) if err != nil { - panic(err) + PanicSanity(err) } return host, port } @@ -51,7 +51,7 @@ func NewDefaultListener(protocol string, lAddr string, requireUPNPHairpin bool) // Create listener listener, err := net.Listen(protocol, lAddr) if err != nil { - panic(err) + PanicCrisis(err) } // Actual listener local IP & port listenerIP, listenerPort := splitHostPort(listener.Addr().String()) @@ -83,7 +83,7 @@ SKIP_UPNP: extAddr = getNaiveExternalAddress(listenerPort) } if extAddr == nil { - panic("Could not determine external address!") + PanicCrisis("Could not determine external address!") } dl := &DefaultListener{ @@ -117,7 +117,7 @@ func (l *DefaultListener) listenRoutine() { // listener wasn't stopped, // yet we encountered an error. if err != nil { - panic(err) + PanicCrisis(err) } l.connections <- conn @@ -190,7 +190,7 @@ func getUPNPExternalAddress(externalPort, internalPort int) *NetAddress { func getNaiveExternalAddress(port int) *NetAddress { addrs, err := net.InterfaceAddrs() if err != nil { - panic(Fmt("Could not fetch interface addresses: %v", err)) + PanicCrisis(Fmt("Could not fetch interface addresses: %v", err)) } for _, a := range addrs { diff --git a/p2p/netaddress.go b/p2p/netaddress.go index 39979fdcd..0730ab942 100644 --- a/p2p/netaddress.go +++ b/p2p/netaddress.go @@ -9,6 +9,8 @@ import ( "net" "strconv" "time" + + . "github.com/tendermint/tendermint/common" ) type NetAddress struct { @@ -21,7 +23,7 @@ type NetAddress struct { func NewNetAddress(addr net.Addr) *NetAddress { tcpAddr, ok := addr.(*net.TCPAddr) if !ok { - panic(fmt.Sprintf("Only TCPAddrs are supported. Got: %v", addr)) + PanicSanity(fmt.Sprintf("Only TCPAddrs are supported. Got: %v", addr)) } ip := tcpAddr.IP port := uint16(tcpAddr.Port) @@ -32,21 +34,21 @@ func NewNetAddress(addr net.Addr) *NetAddress { func NewNetAddressString(addr string) *NetAddress { host, portStr, err := net.SplitHostPort(addr) if err != nil { - panic(err) + PanicSanity(err) } ip := net.ParseIP(host) if ip == nil { if len(host) > 0 { ips, err := net.LookupIP(host) if err != nil { - panic(err) + PanicSanity(err) } ip = ips[0] } } port, err := strconv.ParseUint(portStr, 10, 16) if err != nil { - panic(err) + PanicSanity(err) } na := NewNetAddressIPPort(ip, uint16(port)) return na @@ -76,7 +78,8 @@ func (na *NetAddress) Less(other interface{}) bool { if o, ok := other.(*NetAddress); ok { return na.String() < o.String() } else { - panic("Cannot compare unequal types") + PanicSanity("Cannot compare unequal types") + return false } } diff --git a/p2p/peer.go b/p2p/peer.go index 0a0973a9c..0b8b5c94b 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -52,7 +52,7 @@ func newPeer(conn net.Conn, peerNodeInfo *types.NodeInfo, outbound bool, reactor onReceive := func(chId byte, msgBytes []byte) { reactor := reactorsByCh[chId] if reactor == nil { - panic(Fmt("Unknown channel %X", chId)) + PanicSanity(Fmt("Unknown channel %X", chId)) } reactor.Receive(chId, p, msgBytes) } diff --git a/p2p/secret_connection.go b/p2p/secret_connection.go index 97f8a6aa6..1311d42d1 100644 --- a/p2p/secret_connection.go +++ b/p2p/secret_connection.go @@ -190,7 +190,7 @@ func genEphKeys() (ephPub, ephPriv *[32]byte) { var err error ephPub, ephPriv, err = box.GenerateKey(crand.Reader) if err != nil { - panic("Could not generate ephemeral keypairs") + PanicCrisis("Could not generate ephemeral keypairs") } return } diff --git a/p2p/switch.go b/p2p/switch.go index e951e1775..0c04c7ac9 100644 --- a/p2p/switch.go +++ b/p2p/switch.go @@ -98,7 +98,7 @@ func (sw *Switch) AddReactor(name string, reactor Reactor) Reactor { for _, chDesc := range reactorChannels { chId := chDesc.Id if sw.reactorsByCh[chId] != nil { - panic(fmt.Sprintf("Channel %X has multiple reactors %v & %v", chId, sw.reactorsByCh[chId], reactor)) + PanicSanity(fmt.Sprintf("Channel %X has multiple reactors %v & %v", chId, sw.reactorsByCh[chId], reactor)) } sw.chDescs = append(sw.chDescs, chDesc) sw.reactorsByCh[chId] = reactor diff --git a/rpc/server/http_params.go b/rpc/server/http_params.go index 293edd36a..acf5b4c8c 100644 --- a/rpc/server/http_params.go +++ b/rpc/server/http_params.go @@ -6,8 +6,6 @@ import ( "net/http" "regexp" "strconv" - - . "github.com/tendermint/tendermint/rpc/types" ) var ( @@ -24,10 +22,6 @@ var ( //RE_ID12 = regexp.MustCompile(`^[a-zA-Z0-9]{12}$`) ) -func panicRPC(err error) { - panic(NewRPCResponse(nil, err.Error())) -} - func GetParam(r *http.Request, param string) string { s := r.URL.Query().Get(param) if s == "" { diff --git a/state/block_cache.go b/state/block_cache.go index ae5c7573a..74f6c2f82 100644 --- a/state/block_cache.go +++ b/state/block_cache.go @@ -64,21 +64,17 @@ func (cache *BlockCache) GetAccount(addr []byte) *acm.Account { func (cache *BlockCache) UpdateAccount(acc *acm.Account) { addr := acc.Address _, storage, removed, _ := cache.accounts[string(addr)].unpack() - // SANITY CHECK if removed { - panic("UpdateAccount on a removed account") + PanicSanity("UpdateAccount on a removed account") } - // SANITY CHECK END cache.accounts[string(addr)] = accountInfo{acc, storage, false, true} } func (cache *BlockCache) RemoveAccount(addr []byte) { - // SANITY CHECK _, _, removed, _ := cache.accounts[string(addr)].unpack() if removed { - panic("RemoveAccount on a removed account") + PanicSanity("RemoveAccount on a removed account") } - // SANITY CHECK END cache.accounts[string(addr)] = accountInfo{nil, nil, true, false} } @@ -95,11 +91,9 @@ 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") + PanicSanity("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} @@ -119,12 +113,10 @@ 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") + PanicSanity("SetStorage() on a removed account") } - // SANITY CHECK END cache.storages[Tuple256{addr, key}] = storageInfo{value, true} } @@ -151,12 +143,10 @@ func (cache *BlockCache) UpdateNameRegEntry(entry *types.NameRegEntry) { } func (cache *BlockCache) RemoveNameRegEntry(name string) { - // SANITY CHECK _, removed, _ := cache.names[name].unpack() if removed { - panic("RemoveNameRegEntry on a removed entry") + PanicSanity("RemoveNameRegEntry on a removed entry") } - // SANITY CHECK END cache.names[name] = nameInfo{nil, true, false} } @@ -222,8 +212,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)) + PanicCrisis(Fmt("Could not remove account to be removed: %X", acc.Address)) } } else { if acc == nil { @@ -256,8 +245,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)) + PanicCrisis(Fmt("Could not remove namereg entry to be removed: %s", nameStr)) } } else { if entry == nil { diff --git a/state/execution.go b/state/execution.go index 4e41df161..e04f92293 100644 --- a/state/execution.go +++ b/state/execution.go @@ -57,29 +57,28 @@ 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 } _, val := s.LastBondedValidators.GetByIndex(i) if val == nil { - panic(Fmt("Failed to fetch validator at index %v", i)) + PanicCrisis(Fmt("Failed to fetch validator at index %v", i)) } if _, val_ := s.BondedValidators.GetByAddress(val.Address); val_ != nil { val_.LastCommitHeight = block.Height - 1 updated := s.BondedValidators.Update(val_) if !updated { - panic("Failed to update bonded validator LastCommitHeight") + PanicCrisis("Failed to update bonded validator LastCommitHeight") } } else if _, val_ := s.UnbondingValidators.GetByAddress(val.Address); val_ != nil { val_.LastCommitHeight = block.Height - 1 updated := s.UnbondingValidators.Update(val_) if !updated { - panic("Failed to update unbonding validator LastCommitHeight") + PanicCrisis("Failed to update unbonding validator LastCommitHeight") } } else { - panic("Could not find validator") + PanicCrisis("Could not find validator") } } @@ -213,11 +212,9 @@ func checkInputPubKey(acc *acm.Account, in *types.TxInput) error { func validateInputs(accounts map[string]*acm.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") + PanicSanity("validateInputs() expects account in accounts") } - // SANITY CHECK END err = validateInput(acc, signBytes, in) if err != nil { return @@ -266,14 +263,12 @@ func validateOutputs(outs []*types.TxOutput) (total int64, err error) { func adjustByInputs(accounts map[string]*acm.Account, ins []*types.TxInput) { for _, in := range ins { acc := accounts[string(in.Address)] - // SANITY CHECK if acc == nil { - panic("adjustByInputs() expects account in accounts") + PanicSanity("adjustByInputs() expects account in accounts") } if acc.Balance < in.Amount { - panic("adjustByInputs() expects sufficient funds") + PanicSanity("adjustByInputs() expects sufficient funds") } - // SANITY CHECK END acc.Balance -= in.Amount acc.Sequence += 1 } @@ -282,11 +277,9 @@ func adjustByInputs(accounts map[string]*acm.Account, ins []*types.TxInput) { func adjustByOutputs(accounts map[string]*acm.Account, outs []*types.TxOutput) { for _, out := range outs { acc := accounts[string(out.Address)] - // SANITY CHECK if acc == nil { - panic("adjustByOutputs() expects account in accounts") + PanicSanity("adjustByOutputs() expects account in accounts") } - // SANITY CHECK END acc.Balance += out.Amount } } @@ -701,8 +694,7 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab Accum: 0, }) if !added { - // SOMETHING HAS GONE HORRIBLY WRONG - panic("Failed to add validator") + PanicCrisis("Failed to add validator") } if evc != nil { evc.FireEvent(types.EventStringBond(), tx) @@ -802,9 +794,9 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab return nil default: - // SANITY CHECK (binary decoding should catch bad tx types - // before they get here - panic("Unknown Tx type") + // binary decoding should not let this happen + PanicSanity("Unknown Tx type") + return nil } } @@ -813,7 +805,7 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab // Get permission on an account or fall back to global value func HasPermission(state AccountGetter, acc *acm.Account, perm ptypes.PermFlag) bool { if perm > ptypes.AllBasePermFlags { - panic("Checking an unknown permission in state should never happen") + PanicSanity("Checking an unknown permission in state should never happen") } if acc == nil { @@ -826,7 +818,7 @@ func HasPermission(state AccountGetter, acc *acm.Account, perm ptypes.PermFlag) if _, ok := err.(ptypes.ErrValueNotSet); ok { log.Info("Account does not have permission", "account", acc, "accPermissions", acc.Permissions, "perm", perm) if state == nil { - panic("All known global permissions should be set!") + PanicSanity("All known global permissions should be set!") } log.Info("Querying GlobalPermissionsAddress") return HasPermission(nil, state.GetAccount(ptypes.GlobalPermissionsAddress), perm) diff --git a/state/priv_validator.go b/state/priv_validator.go index e17de003e..615104ffd 100644 --- a/state/priv_validator.go +++ b/state/priv_validator.go @@ -30,9 +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") + PanicSanity("Unknown vote type") + return 0 } } @@ -95,14 +94,13 @@ func (privVal *PrivValidator) Save() { func (privVal *PrivValidator) save() { if privVal.filePath == "" { - // SANITY CHECK - panic("Cannot save PrivValidator: filePath not set") + PanicSanity("Cannot save PrivValidator: filePath not set") } jsonBytes := binary.JSONBytes(privVal) err := WriteFileAtomic(privVal.filePath, jsonBytes) if err != nil { // `@; BOOM!!! - panic(err) + PanicCrisis(err) } } diff --git a/state/state.go b/state/state.go index fe4ec5267..da585e8a8 100644 --- a/state/state.go +++ b/state/state.go @@ -92,8 +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) + PanicCrisis(*err) } s.DB.Set(stateKey, buf.Bytes()) } @@ -216,14 +215,12 @@ 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") + PanicCrisis("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") + PanicCrisis("Couldn't add validator for unbonding") } } @@ -231,35 +228,29 @@ 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") + PanicCrisis("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") + PanicCrisis("Couldn't add validator for rebonding") } } 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") + PanicSanity("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 := getOrMakeOutputs(s, nil, valInfo.UnbondTo) - // SANITY CHECK if err != nil { - panic("Couldn't get or make unbondTo accounts") + PanicSanity("Couldn't get or make unbondTo accounts") } - // SANITY CHECK END adjustByOutputs(accounts, valInfo.UnbondTo) for _, acc := range accounts { s.UpdateAccount(acc) @@ -268,19 +259,16 @@ 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") + PanicCrisis("Couldn't remove validator for release") } } 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") + PanicSanity("Couldn't find validatorInfo for release") } - // SANITY CHECK END valInfo.DestroyedHeight = s.LastBlockHeight + 1 valInfo.DestroyedAmount = val.VotingPower s.SetValidatorInfo(valInfo) @@ -290,8 +278,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") + PanicCrisis("Couldn't remove validator for destruction") } } diff --git a/state/test.go b/state/test.go index 4ae0d29fa..65035c829 100644 --- a/state/test.go +++ b/state/test.go @@ -18,7 +18,7 @@ import ( func Tempfile(prefix string) (*os.File, string) { file, err := ioutil.TempFile("", prefix) if err != nil { - panic(err) + PanicCrisis(err) } return file, file.Name() } diff --git a/state/tx_cache.go b/state/tx_cache.go index 26b8ce428..71d72cc93 100644 --- a/state/tx_cache.go +++ b/state/tx_cache.go @@ -42,23 +42,19 @@ func (cache *TxCache) GetAccount(addr Word256) *vm.Account { func (cache *TxCache) UpdateAccount(acc *vm.Account) { addr := acc.Address - // SANITY CHECK _, removed := vmUnpack(cache.accounts[addr]) if removed { - panic("UpdateAccount on a removed account") + PanicSanity("UpdateAccount on a removed account") } - // SANITY CHECK END cache.accounts[addr] = vmAccountInfo{acc, false} } func (cache *TxCache) RemoveAccount(acc *vm.Account) { addr := acc.Address - // SANITY CHECK _, removed := vmUnpack(cache.accounts[addr]) if removed { - panic("RemoveAccount on a removed account") + PanicSanity("RemoveAccount on a removed account") } - // SANITY CHECK END cache.accounts[addr] = vmAccountInfo{acc, true} } @@ -86,8 +82,9 @@ 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)) + // either we've messed up nonce handling, or sha3 is broken + PanicSanity(Fmt("Could not create account, address already exists: %X", addr)) + return nil } } @@ -108,12 +105,10 @@ 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") + PanicSanity("SetStorage() on a removed account") } - // SANITY CHECK END cache.storages[Tuple256{addr, key}] = value } diff --git a/state/validator.go b/state/validator.go index 933cab5a1..44e26adb4 100644 --- a/state/validator.go +++ b/state/validator.go @@ -7,6 +7,7 @@ import ( acm "github.com/tendermint/tendermint/account" "github.com/tendermint/tendermint/binary" + . "github.com/tendermint/tendermint/common" "github.com/tendermint/tendermint/types" ) @@ -77,8 +78,8 @@ 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") + PanicSanity("Cannot compare identical validators") + return nil } } } @@ -116,5 +117,6 @@ func (vc validatorCodec) Decode(r io.Reader, n *int64, err *error) interface{} { } func (vc validatorCodec) Compare(o1 interface{}, o2 interface{}) int { - panic("ValidatorCodec.Compare not implemented") + PanicSanity("ValidatorCodec.Compare not implemented") + return 0 } diff --git a/types/part_set.go b/types/part_set.go index 32803fb22..b38ac8bca 100644 --- a/types/part_set.go +++ b/types/part_set.go @@ -36,10 +36,7 @@ func (part *Part) Hash() []byte { return part.hash } else { hasher := ripemd160.New() - _, err := hasher.Write(part.Bytes) - if err != nil { - panic(err) - } + hasher.Write(part.Bytes) // doesn't err part.hash = hasher.Sum(nil) return part.hash } @@ -226,7 +223,7 @@ func (ps *PartSet) IsComplete() bool { func (ps *PartSet) GetReader() io.Reader { if !ps.IsComplete() { - panic("Cannot GetReader() on incomplete PartSet") + PanicSanity("Cannot GetReader() on incomplete PartSet") } buf := []byte{} for _, part := range ps.parts { diff --git a/types/tx.go b/types/tx.go index efd93c479..990b47468 100644 --- a/types/tx.go +++ b/types/tx.go @@ -305,7 +305,7 @@ type DupeoutTx struct { } func (tx *DupeoutTx) WriteSignBytes(chainID string, w io.Writer, n *int64, err *error) { - panic("DupeoutTx has no sign bytes") + PanicSanity("DupeoutTx has no sign bytes") } func (tx *DupeoutTx) String() string { @@ -326,7 +326,7 @@ func TxID(chainID string, tx Tx) []byte { func jsonEscape(str string) string { escapedBytes, err := json.Marshal(str) if err != nil { - panic(Fmt("Error json-escaping a string", str)) + PanicSanity(Fmt("Error json-escaping a string", str)) } return string(escapedBytes) } diff --git a/types/vote.go b/types/vote.go index 895d2f787..1eed092ce 100644 --- a/types/vote.go +++ b/types/vote.go @@ -64,7 +64,7 @@ func (vote *Vote) String() string { case VoteTypePrecommit: typeString = "Precommit" default: - panic("Unknown vote type") + PanicSanity("Unknown vote type") } return fmt.Sprintf("Vote{%v/%02d/%v(%v) %X#%v %v}", vote.Height, vote.Round, vote.Type, typeString, Fingerprint(vote.BlockHash), vote.BlockParts, vote.Signature) diff --git a/vm/snative.go b/vm/snative.go index 863c0a181..16f45a6d7 100644 --- a/vm/snative.go +++ b/vm/snative.go @@ -116,7 +116,7 @@ func setGlobalPerm(appState AppState, acc *Account, args []byte) (output []byte, permNum, perm := returnTwoArgs(args) vmAcc := appState.GetAccount(ptypes.GlobalPermissionsAddress256) if vmAcc == nil { - panic("cant find the global permissions account") + PanicSanity("cant find the global permissions account") } permN := ptypes.PermFlag(Uint64FromWord256(permNum)) if !ValidPermN(permN) { diff --git a/vm/stack.go b/vm/stack.go index 4e7278f93..9dfff4df6 100644 --- a/vm/stack.go +++ b/vm/stack.go @@ -50,7 +50,7 @@ func (st *Stack) Push(d Word256) { // currently only called after Sha3 func (st *Stack) PushBytes(bz []byte) { if len(bz) != 32 { - panic("Invalid bytes size: expected 32") + PanicSanity("Invalid bytes size: expected 32") } st.Push(LeftPadWord256(bz)) } diff --git a/vm/vm.go b/vm/vm.go index c678fc8e8..bf36356f5 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -141,7 +141,7 @@ func (vm *VM) Call(caller, callee *Account, code, input []byte, value int64, gas err := transfer(callee, caller, value) if err != nil { // data has been corrupted in ram - panic("Could not return value to caller") + PanicCrisis("Could not return value to caller") } } }