From 13d70e4112571d26742fe0ce606dd208f4b1bb1d Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sat, 25 Oct 2014 01:30:35 -0700 Subject: [PATCH] stack trace in p2p/connection panics, bitArray fix --- common/bit_array.go | 161 +++++++++++------------- common/bit_array_test.go | 135 ++++++++++++++++++++ common/errors.go | 13 ++ common/ibbs_tree.go | 266 --------------------------------------- common/ibbs_tree_test.go | 203 ------------------------------ consensus/reactor.go | 10 +- p2p/connection.go | 15 ++- 7 files changed, 237 insertions(+), 566 deletions(-) create mode 100644 common/bit_array_test.go delete mode 100644 common/ibbs_tree.go delete mode 100644 common/ibbs_tree_test.go diff --git a/common/bit_array.go b/common/bit_array.go index 1070018fa..a3967a92a 100644 --- a/common/bit_array.go +++ b/common/bit_array.go @@ -1,8 +1,8 @@ package common import ( + "fmt" "io" - "math" "math/rand" "strings" @@ -10,40 +10,43 @@ import ( ) // Not goroutine safe -type BitArray []uint64 +type BitArray struct { + bits uint + elems []uint64 +} -func NewBitArray(length uint) BitArray { - return BitArray(make([]uint64, (length+63)/64)) +func NewBitArray(bits uint) BitArray { + return BitArray{bits, make([]uint64, (bits+63)/64)} } func ReadBitArray(r io.Reader, n *int64, err *error) BitArray { - lengthTotal := ReadUInt32(r, n, err) - lengthWritten := ReadUInt32(r, n, err) + bits := ReadUVarInt(r, n, err) + elemsWritten := ReadUVarInt(r, n, err) if *err != nil { - return nil + return BitArray{} } - buf := make([]uint64, int(lengthTotal)) - for i := uint32(0); i < lengthWritten; i++ { - buf[i] = ReadUInt64(r, n, err) - if err != nil { - return nil + bA := NewBitArray(bits) + for i := uint(0); i < elemsWritten; i++ { + bA.elems[i] = ReadUInt64(r, n, err) + if *err != nil { + return BitArray{} } } - return BitArray(buf) + return bA } func (bA BitArray) WriteTo(w io.Writer) (n int64, err error) { // Count the last element > 0. - lastNonzeroIndex := -1 - for i, elem := range bA { + elemsToWrite := 0 + for i, elem := range bA.elems { if elem > 0 { - lastNonzeroIndex = i + elemsToWrite = i + 1 } } - WriteUInt32(w, uint32(len(bA)), &n, &err) - WriteUInt32(w, uint32(lastNonzeroIndex+1), &n, &err) - for i, elem := range bA { - if i > lastNonzeroIndex { + WriteUVarInt(w, bA.bits, &n, &err) + WriteUVarInt(w, uint(elemsToWrite), &n, &err) + for i, elem := range bA.elems { + if i >= elemsToWrite { break } WriteUInt64(w, elem, &n, &err) @@ -51,44 +54,54 @@ func (bA BitArray) WriteTo(w io.Writer) (n int64, err error) { return } +// NOTE: behavior is undefined if i >= bA.bits func (bA BitArray) GetIndex(i uint) bool { - return bA[i/64]&uint64(1<<(i%64)) > 0 + return bA.elems[i/64]&uint64(1<<(i%64)) > 0 } +// NOTE: behavior is undefined if i >= bA.bits func (bA BitArray) SetIndex(i uint, v bool) { if v { - bA[i/64] |= uint64(1 << (i % 64)) + bA.elems[i/64] |= uint64(1 << (i % 64)) } else { - bA[i/64] &= ^uint64(1 << (i % 64)) + bA.elems[i/64] &= ^uint64(1 << (i % 64)) } } func (bA BitArray) Copy() BitArray { - c := make([]uint64, len(bA)) - copy(c, bA) - return BitArray(c) + c := make([]uint64, len(bA.elems)) + copy(c, bA.elems) + return BitArray{bA.bits, c} +} + +func (bA BitArray) copyBits(bits uint) BitArray { + c := make([]uint64, (bits+63)/64) + copy(c, bA.elems) + return BitArray{bits, c} } +// Returns a BitArray of larger bits size. func (bA BitArray) Or(o BitArray) BitArray { - c := bA.Copy() - for i, _ := range c { - c[i] = o[i] | c[i] + c := bA.copyBits(MaxUint(bA.bits, o.bits)) + for i := 0; i < len(c.elems); i++ { + c.elems[i] |= o.elems[i] } return c } +// Returns a BitArray of smaller bit size. func (bA BitArray) And(o BitArray) BitArray { - c := bA.Copy() - for i, _ := range c { - c[i] = o[i] & c[i] + c := bA.copyBits(MinUint(bA.bits, o.bits)) + for i := 0; i < len(c.elems); i++ { + c.elems[i] &= o.elems[i] } return c } func (bA BitArray) Not() BitArray { c := bA.Copy() - for i, _ := range c { - c[i] = ^c[i] + for i := 0; i < len(c.elems); i++ { + c.elems[i] = ^c.elems[i] } return c } @@ -97,62 +110,38 @@ func (bA BitArray) Sub(o BitArray) BitArray { return bA.And(o.Not()) } -// NOTE: returns counts or a longer int slice as necessary. -func (bA BitArray) AddToCounts(counts []int) []int { - for bytei := 0; bytei < len(bA); bytei++ { - for biti := 0; biti < 64; biti++ { - if (bA[bytei] & (1 << uint(biti))) == 0 { - continue - } - index := 64*bytei + biti - if len(counts) <= index { - counts = append(counts, make([]int, (index-len(counts)+1))...) - } - counts[index]++ - } - } - return counts -} - func (bA BitArray) PickRandom() (int, bool) { - randStart := rand.Intn(len(bA)) - for i := 0; i < len(bA); i++ { - bytei := ((i + randStart) % len(bA)) - if bA[bytei] > 0 { - randBitStart := rand.Intn(64) - for j := 0; j < 64; j++ { - biti := ((j + randBitStart) % 64) - //fmt.Printf("%X %v %v %v\n", iHas, j, biti, randBitStart) - if (bA[bytei] & (1 << uint(biti))) > 0 { - return 64*int(bytei) + int(biti), true + length := len(bA.elems) + randElemStart := rand.Intn(length) + for i := 0; i < length; i++ { + elemIdx := ((i + randElemStart) % length) + if elemIdx < length-1 { + if bA.elems[elemIdx] > 0 { + randBitStart := rand.Intn(64) + for j := 0; j < 64; j++ { + bitIdx := ((j + randBitStart) % 64) + if (bA.elems[elemIdx] & (1 << uint(bitIdx))) > 0 { + return 64*int(elemIdx) + int(bitIdx), true + } } + panic("should not happen") } - panic("should not happen") - } - } - return 0, false -} - -// Pick an index from this BitArray that is 1 && whose count is lowest. -func (bA BitArray) PickRarest(counts []int) (rarest int, ok bool) { - smallestCount := math.MaxInt32 - for bytei := 0; bytei < len(bA); bytei++ { - if bA[bytei] > 0 { - for biti := 0; biti < 64; biti++ { - if (bA[bytei] & (1 << uint(biti))) == 0 { - continue - } - index := 64*bytei + biti - if counts[index] < smallestCount { - smallestCount = counts[index] - rarest = index - ok = true + } else { + // Special case for last elem, to ignore straggler bits + elemBits := int(bA.bits) % 64 + if elemBits == 0 { + elemBits = 64 + } + randBitStart := rand.Intn(elemBits) + for j := 0; j < elemBits; j++ { + bitIdx := ((j + randBitStart) % elemBits) + if (bA.elems[elemIdx] & (1 << uint(bitIdx))) > 0 { + return 64*int(elemIdx) + int(bitIdx), true } } - panic("should not happen") } } - return + return 0, false } func (bA BitArray) String() string { @@ -162,8 +151,8 @@ func (bA BitArray) String() string { func (bA BitArray) StringWithIndent(indent string) string { lines := []string{} bits := "" - for i := 0; i < len(bA)*64; i++ { - if bA.GetIndex(uint(i)) { + for i := uint(0); i < bA.bits; i++ { + if bA.GetIndex(i) { bits += "X" } else { bits += "_" @@ -182,5 +171,5 @@ func (bA BitArray) StringWithIndent(indent string) string { if len(bits) > 0 { lines = append(lines, bits) } - return strings.Join(lines, indent) + return fmt.Sprintf("BA{%v:%v}", bA.bits, strings.Join(lines, indent)) } diff --git a/common/bit_array_test.go b/common/bit_array_test.go new file mode 100644 index 000000000..aa49cc378 --- /dev/null +++ b/common/bit_array_test.go @@ -0,0 +1,135 @@ +package common + +import ( + "bytes" + "testing" +) + +func randBitArray(bits uint) (BitArray, []byte) { + src := RandBytes(int((bits + 7) / 8)) + bA := NewBitArray(bits) + for i := uint(0); i < uint(len(src)); i++ { + for j := uint(0); j < 8; j++ { + if i*8+j >= bits { + return bA, src + } + setBit := src[i]&(1< 0 + bA.SetIndex(i*8+j, setBit) + } + } + return bA, src +} + +func TestReadWriteEmptyBitarray(t *testing.T) { + bA1 := BitArray{} + buf := new(bytes.Buffer) + _, err := bA1.WriteTo(buf) + if err != nil { + t.Error("Failed to write empty bitarray") + } + + var n int64 + bA2 := ReadBitArray(buf, &n, &err) + if err != nil { + t.Error("Failed to read empty bitarray") + } + if bA2.bits != 0 { + t.Error("Expected to get bA2.bits 0") + } +} + +func TestReadWriteBitarray(t *testing.T) { + + // Make random bA1 + bA1, testData := randBitArray(64*10 + 8) // not divisible by 64 + + // Write it + buf := new(bytes.Buffer) + _, err := bA1.WriteTo(buf) + if err != nil { + t.Error("Failed to write bitarray") + } + + // Read it + var n int64 + bA2 := ReadBitArray(buf, &n, &err) + if err != nil { + t.Error("Failed to read bitarray") + } + testData2 := make([]byte, len(testData)) + for i := uint(0); i < uint(len(testData)); i++ { + for j := uint(0); j < 8; j++ { + if bA2.GetIndex(i*8 + j) { + testData2[i] |= 1 << j + } + } + } + + // Compare testData + if !bytes.Equal(testData, testData2) { + t.Errorf("Not the same:\n%X\n%X", testData, testData2) + } +} + +func TestAnd(t *testing.T) { + + bA1, _ := randBitArray(51) + bA2, _ := randBitArray(31) + bA3 := bA1.And(bA2) + + if bA3.bits != 31 { + t.Error("Expected min bits", bA3.bits) + } + if len(bA3.elems) != len(bA2.elems) { + t.Error("Expected min elems length") + } + for i := uint(0); i < bA3.bits; i++ { + expected := bA1.GetIndex(i) && bA2.GetIndex(i) + if bA3.GetIndex(i) != expected { + t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i)) + } + } +} + +func TestOr(t *testing.T) { + + bA1, _ := randBitArray(51) + bA2, _ := randBitArray(31) + bA3 := bA1.Or(bA2) + + if bA3.bits != 51 { + t.Error("Expected max bits") + } + if len(bA3.elems) != len(bA1.elems) { + t.Error("Expected max elems length") + } + for i := uint(0); i < bA3.bits; i++ { + expected := bA1.GetIndex(i) || bA2.GetIndex(i) + if bA3.GetIndex(i) != expected { + t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i)) + } + } +} + +func TestSub(t *testing.T) { + + bA1, _ := randBitArray(31) + bA2, _ := randBitArray(51) + bA3 := bA1.Sub(bA2) + + if bA3.bits != 31 { + t.Error("Expected min bits") + } + if len(bA3.elems) != len(bA1.elems) { + t.Error("Expected min elems length") + } + for i := uint(0); i < bA3.bits; i++ { + expected := bA1.GetIndex(i) + if bA2.GetIndex(i) { + expected = false + } + if bA3.GetIndex(i) != expected { + t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i)) + } + } +} diff --git a/common/errors.go b/common/errors.go index 82b41575c..6cfecf4f3 100644 --- a/common/errors.go +++ b/common/errors.go @@ -8,3 +8,16 @@ import ( func Errorf(s string, args ...interface{}) error { return errors.New(fmt.Sprintf(s, args...)) } + +type StackError struct { + Err interface{} + Stack []byte +} + +func (se StackError) String() string { + return fmt.Sprintf("Error: %v\nStack: %s", se.Err, se.Stack) +} + +func (se StackError) Error() string { + return se.String() +} diff --git a/common/ibbs_tree.go b/common/ibbs_tree.go deleted file mode 100644 index 6ef2fd831..000000000 --- a/common/ibbs_tree.go +++ /dev/null @@ -1,266 +0,0 @@ -package common - -import () - -// This immutable balanced binary tree happens to be an -// immutable AVL+ tree, adapted from tendermint/merkle. -// Unlike that one, this is in-memory, non-merkleized, -// and nodes can be nil to signify an empty tree. -type IBBSTree struct { - key uint64 - value interface{} - size uint64 - height uint8 - left *IBBSTree - right *IBBSTree -} - -// Creates an empty tree. -func NewIBBSTree() *IBBSTree { - return nil -} - -// Creates a single tree node from key and value. -func NewIBBSTreeNode(key uint64, value interface{}) *IBBSTree { - return &IBBSTree{ - key: key, - value: value, - size: 1, - } -} - -func (self *IBBSTree) Copy() *IBBSTree { - if self == nil { - return nil - } - return &IBBSTree{ - key: self.key, - value: self.value, - size: self.size, - height: self.height, - left: self.left, - right: self.right, - } -} - -func (self *IBBSTree) Size() uint64 { - if self == nil { - return 0 - } - return self.size -} - -func (self *IBBSTree) Height() uint8 { - if self == nil { - return 0 - } - return self.height -} - -func (self *IBBSTree) Has(key uint64) (has bool) { - if self == nil { - return false - } - if self.key == key { - return true - } - if self.height == 0 { - return false - } else { - if key < self.key { - return self.left.Has(key) - } else { - return self.right.Has(key) - } - } -} - -func (self *IBBSTree) Get(key uint64) (value interface{}) { - if self == nil { - return nil - } - if self.height == 0 { - if self.key == key { - return self.value - } else { - return nil - } - } else { - if key < self.key { - return self.left.Get(key) - } else { - return self.right.Get(key) - } - } -} - -func (self *IBBSTree) Set(key uint64, value interface{}) (_ *IBBSTree, updated bool) { - if self == nil { - return NewIBBSTreeNode(key, value), false - } - if self.height == 0 { - if key < self.key { - return &IBBSTree{ - key: self.key, - height: 1, - size: 2, - left: NewIBBSTreeNode(key, value), - right: self, - }, false - } else if self.key == key { - return NewIBBSTreeNode(key, value), true - } else { - return &IBBSTree{ - key: key, - height: 1, - size: 2, - left: self, - right: NewIBBSTreeNode(key, value), - }, false - } - } else { - self = self.Copy() - if key < self.key { - self.left, updated = self.left.Set(key, value) - } else { - self.right, updated = self.right.Set(key, value) - } - if updated { - return self, updated - } else { - self.calcHeightAndSize() - return self.balance(), updated - } - } -} - -func (self *IBBSTree) Remove(key uint64) (newSelf *IBBSTree, value interface{}, removed bool) { - newSelf, _, _, value, removed = self.remove(key) - return -} - -// newKey: new leftmost leaf key for tree after successfully removing 'key' if changed. -func (self *IBBSTree) remove(key uint64) (newSelf *IBBSTree, hasNewKey bool, newKey uint64, value interface{}, removed bool) { - if self == nil { - return nil, false, 0, nil, false - } - if self.height == 0 { - if self.key == key { - return nil, false, 0, self.value, true - } else { - return self, false, 0, nil, false - } - } else { - if key < self.key { - var newLeft *IBBSTree - newLeft, hasNewKey, newKey, value, removed = self.left.remove(key) - if !removed { - return self, false, 0, value, false - } else if newLeft == nil { // left node held value, was removed - return self.right, true, self.key, value, true - } - self = self.Copy() - self.left = newLeft - } else { - var newRight *IBBSTree - newRight, hasNewKey, newKey, value, removed = self.right.remove(key) - if !removed { - return self, false, 0, value, false - } else if newRight == nil { // right node held value, was removed - return self.left, false, 0, value, true - } - self = self.Copy() - self.right = newRight - if hasNewKey { - self.key = newKey - hasNewKey = false - newKey = 0 - } - } - self.calcHeightAndSize() - return self.balance(), hasNewKey, newKey, value, true - } -} - -func (self *IBBSTree) rotateRight() *IBBSTree { - self = self.Copy() - sl := self.left.Copy() - slr := sl.right - - sl.right = self - self.left = slr - - self.calcHeightAndSize() - sl.calcHeightAndSize() - - return sl -} - -func (self *IBBSTree) rotateLeft() *IBBSTree { - self = self.Copy() - sr := self.right.Copy() - srl := sr.left - - sr.left = self - self.right = srl - - self.calcHeightAndSize() - sr.calcHeightAndSize() - - return sr -} - -func (self *IBBSTree) calcHeightAndSize() { - self.height = MaxUint8(self.left.Height(), self.right.Height()) + 1 - self.size = self.left.Size() + self.right.Size() -} - -func (self *IBBSTree) calcBalance() int { - return int(self.left.Height()) - int(self.right.Height()) -} - -func (self *IBBSTree) balance() (newSelf *IBBSTree) { - balance := self.calcBalance() - if balance > 1 { - if self.left.calcBalance() >= 0 { - // Left Left Case - return self.rotateRight() - } else { - // Left Right Case - self = self.Copy() - self.left = self.left.rotateLeft() - //self.calcHeightAndSize() - return self.rotateRight() - } - } - if balance < -1 { - if self.right.calcBalance() <= 0 { - // Right Right Case - return self.rotateLeft() - } else { - // Right Left Case - self = self.Copy() - self.right = self.right.rotateRight() - //self.calcHeightAndSize() - return self.rotateLeft() - } - } - // Nothing changed - return self -} - -// Iteration stops when stop is returned. -func (self *IBBSTree) Iterate(cb func(uint64, interface{}) bool) bool { - if self == nil { - return false - } - if self.height == 0 { - return cb(self.key, self.value) - } else { - stop := self.left.Iterate(cb) - if stop { - return stop - } - return self.right.Iterate(cb) - } -} diff --git a/common/ibbs_tree_test.go b/common/ibbs_tree_test.go deleted file mode 100644 index 74748bf77..000000000 --- a/common/ibbs_tree_test.go +++ /dev/null @@ -1,203 +0,0 @@ -package common - -import ( - "fmt" - "runtime" - "testing" -) - -func init() { - // TODO: seed rand? -} - -func (self *IBBSTree) lmd() *IBBSTree { - if self.height == 0 { - return self - } - return self.left.lmd() -} - -func TestUnit(t *testing.T) { - - // Convenience for a new node - N := func(l, r interface{}) *IBBSTree { - var left, right *IBBSTree - if _, ok := l.(*IBBSTree); ok { - left = l.(*IBBSTree) - } else { - left = NewIBBSTreeNode(uint64(l.(int)), nil) - } - if _, ok := r.(*IBBSTree); ok { - right = r.(*IBBSTree) - } else { - right = NewIBBSTreeNode(uint64(r.(int)), nil) - } - - n := &IBBSTree{ - key: right.lmd().key, - left: left, - right: right, - } - n.calcHeightAndSize() - return n - } - - // Convenience for simple printing of keys & tree structure - var P func(*IBBSTree) string - P = func(n *IBBSTree) string { - if n.height == 0 { - return fmt.Sprintf("%v", n.key) - } else { - return fmt.Sprintf("(%v %v)", P(n.left), P(n.right)) - } - } - - expectSet := func(n *IBBSTree, i uint64, repr string) { - n2, updated := n.Set(i, nil) - // ensure node was added & structure is as expected. - if updated == true || P(n2) != repr { - t.Fatalf("Adding %v to %v:\nExpected %v\nUnexpectedly got %v updated:%v", - i, P(n), repr, P(n2), updated) - } - } - - expectRemove := func(n *IBBSTree, i uint64, repr string) { - n2, value, removed := n.Remove(i) - // ensure node was removed & structure is as expected. - if value != nil || P(n2) != repr || !removed { - t.Fatalf("Removing %v from %v:\nExpected %v\nUnexpectedly got %v value:%v err:%v", - i, P(n), repr, P(n2), value, removed) - } - } - - //////// Test Set cases: - - // Case 1: - n1 := N(4, 20) - - expectSet(n1, 8, "((4 8) 20)") - expectSet(n1, 25, "(4 (20 25))") - - n2 := N(4, N(20, 25)) - - expectSet(n2, 8, "((4 8) (20 25))") - expectSet(n2, 30, "((4 20) (25 30))") - - n3 := N(N(1, 2), 6) - - expectSet(n3, 4, "((1 2) (4 6))") - expectSet(n3, 8, "((1 2) (6 8))") - - n4 := N(N(1, 2), N(N(5, 6), N(7, 9))) - - expectSet(n4, 8, "(((1 2) (5 6)) ((7 8) 9))") - expectSet(n4, 10, "(((1 2) (5 6)) (7 (9 10)))") - - //////// Test Remove cases: - - n10 := N(N(1, 2), 3) - - expectRemove(n10, 2, "(1 3)") - expectRemove(n10, 3, "(1 2)") - - n11 := N(N(N(1, 2), 3), N(4, 5)) - - expectRemove(n11, 4, "((1 2) (3 5))") - expectRemove(n11, 3, "((1 2) (4 5))") - -} - -func TestIntegration(t *testing.T) { - - type record struct { - key uint64 - value string - } - - records := make([]*record, 400) - var tree *IBBSTree = NewIBBSTree() - var val interface{} - var removed bool - var updated bool - - randomRecord := func() *record { - return &record{RandUInt64(), RandStr(20)} - } - - for i := range records { - r := randomRecord() - records[i] = r - //t.Log("New record", r) - //PrintIBBSTree(tree.root) - tree, updated = tree.Set(r.key, "") - if updated { - t.Error("should have not been updated") - } - tree, updated = tree.Set(r.key, r.value) - if !updated { - t.Error("should have been updated") - } - if tree.Size() != uint64(i+1) { - t.Error("size was wrong", tree.Size(), i+1) - } - } - - for _, r := range records { - if has := tree.Has(r.key); !has { - t.Error("Missing key", r.key) - } - if val := tree.Get(r.key); val.(string) != r.value { - t.Error("wrong value") - } - } - - for i, x := range records { - if tree, val, removed = tree.Remove(x.key); !removed { - t.Error("not removed") - } else if val.(string) != x.value { - t.Error("wrong value") - } - for _, r := range records[i+1:] { - if has := tree.Has(r.key); !has { - t.Error("Missing key", r.key) - } - val := tree.Get(r.key) - if val.(string) != r.value { - t.Error("wrong value") - } - } - if tree.Size() != uint64(len(records)-(i+1)) { - t.Error("size was wrong", tree.Size(), (len(records) - (i + 1))) - } - } -} - -func BenchmarkIBBSTree(b *testing.B) { - b.StopTimer() - - type record struct { - key uint64 - value interface{} - } - - randomRecord := func() *record { - return &record{RandUInt64(), RandUInt64()} - } - - t := NewIBBSTree() - for i := 0; i < 1000000; i++ { - r := randomRecord() - t, _ = t.Set(r.key, r.value) - } - - fmt.Println("ok, starting") - - runtime.GC() - - b.StartTimer() - for i := 0; i < b.N; i++ { - r := randomRecord() - t, _ = t.Set(r.key, r.value) - t, _, _ = t.Remove(r.key) - } -} diff --git a/consensus/reactor.go b/consensus/reactor.go index 6e9bf6ccd..cca42a09b 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -710,13 +710,13 @@ func (ps *PeerState) ApplyNewRoundStepMessage(msg *NewRoundStepMessage) error { // Reset the rest ps.Proposal = false ps.ProposalBlockHash = nil - ps.ProposalBlockBitArray = nil + ps.ProposalBlockBitArray = BitArray{} ps.ProposalPOLHash = nil - ps.ProposalPOLBitArray = nil - ps.Prevotes = nil - ps.Precommits = nil + ps.ProposalPOLBitArray = BitArray{} + ps.Prevotes = BitArray{} + ps.Precommits = BitArray{} if ps.Height != msg.Height { - ps.Commits = nil + ps.Commits = BitArray{} } return nil } diff --git a/p2p/connection.go b/p2p/connection.go index f9aabf554..352d2e42b 100644 --- a/p2p/connection.go +++ b/p2p/connection.go @@ -6,6 +6,7 @@ import ( "io" "math" "net" + "runtime/debug" "sync/atomic" "time" @@ -141,7 +142,9 @@ func (c *MConnection) flush() { // Catch panics, usually caused by remote disconnects. func (c *MConnection) _recover() { if r := recover(); r != nil { - c.stopForError(r) + stack := debug.Stack() + err := StackError{r, stack} + c.stopForError(err) } } @@ -374,16 +377,16 @@ FOR_LOOP: } break FOR_LOOP } - channel := c.channels[pkt.ChannelId] - if channel == nil { - Panicf("Unknown channel %v", pkt.ChannelId) + channel, ok := c.channelsIdx[pkt.ChannelId] + if !ok || channel == nil { + Panicf("Unknown channel %X", pkt.ChannelId) } msgBytes := channel.recvPacket(pkt) if msgBytes != nil { c.onReceive(pkt.ChannelId, msgBytes) } default: - Panicf("Unknown message type %v", pktType) + Panicf("Unknown message type %X", pktType) } // TODO: shouldn't this go in the sendRoutine? @@ -550,7 +553,7 @@ func (p packet) WriteTo(w io.Writer) (n int64, err error) { } func (p packet) String() string { - return fmt.Sprintf("%v:%X", p.ChannelId, p.Bytes) + return fmt.Sprintf("%X:%X", p.ChannelId, p.Bytes) } func readPacketSafe(r io.Reader) (pkt packet, n int64, err error) {