diff --git a/blocks/tx.go b/blocks/tx.go index 421a599e7..96063e8e4 100644 --- a/blocks/tx.go +++ b/blocks/tx.go @@ -75,9 +75,9 @@ func ReadTx(r io.Reader, n *int64, err *error) Tx { //----------------------------------------------------------------------------- type BaseTx struct { - Sequence uint - Fee uint64 - Signature + Sequence uint + Fee uint64 + Signature Signature } func ReadBaseTx(r io.Reader, n *int64, err *error) BaseTx { diff --git a/common/bit_array.go b/common/bit_array.go index a3967a92a..913687beb 100644 --- a/common/bit_array.go +++ b/common/bit_array.go @@ -56,16 +56,23 @@ func (bA BitArray) WriteTo(w io.Writer) (n int64, err error) { // NOTE: behavior is undefined if i >= bA.bits func (bA BitArray) GetIndex(i uint) bool { + if i >= bA.bits { + return false + } 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) { +func (bA BitArray) SetIndex(i uint, v bool) bool { + if i >= bA.bits { + return false + } if v { bA.elems[i/64] |= uint64(1 << (i % 64)) } else { bA.elems[i/64] &= ^uint64(1 << (i % 64)) } + return true } func (bA BitArray) Copy() BitArray { @@ -107,11 +114,28 @@ func (bA BitArray) Not() BitArray { } func (bA BitArray) Sub(o BitArray) BitArray { - return bA.And(o.Not()) + if bA.bits > o.bits { + c := bA.Copy() + for i := 0; i < len(o.elems)-1; i++ { + c.elems[i] &= ^c.elems[i] + } + i := uint(len(o.elems) - 1) + if i >= 0 { + for idx := i * 64; idx < o.bits; idx++ { + c.SetIndex(idx, c.GetIndex(idx) && !o.GetIndex(idx)) + } + } + return c + } else { + return bA.And(o.Not()) + } } func (bA BitArray) PickRandom() (int, bool) { length := len(bA.elems) + if length == 0 { + return 0, false + } randElemStart := rand.Intn(length) for i := 0; i < length; i++ { elemIdx := ((i + randElemStart) % length) diff --git a/common/bit_array_test.go b/common/bit_array_test.go index aa49cc378..542522d06 100644 --- a/common/bit_array_test.go +++ b/common/bit_array_test.go @@ -111,17 +111,17 @@ func TestOr(t *testing.T) { } } -func TestSub(t *testing.T) { +func TestSub1(t *testing.T) { bA1, _ := randBitArray(31) bA2, _ := randBitArray(51) bA3 := bA1.Sub(bA2) - if bA3.bits != 31 { - t.Error("Expected min bits") + if bA3.bits != bA1.bits { + t.Error("Expected bA1 bits") } if len(bA3.elems) != len(bA1.elems) { - t.Error("Expected min elems length") + t.Error("Expected bA1 elems length") } for i := uint(0); i < bA3.bits; i++ { expected := bA1.GetIndex(i) @@ -133,3 +133,26 @@ func TestSub(t *testing.T) { } } } + +func TestSub2(t *testing.T) { + + bA1, _ := randBitArray(51) + bA2, _ := randBitArray(31) + bA3 := bA1.Sub(bA2) + + if bA3.bits != bA1.bits { + t.Error("Expected bA1 bits") + } + if len(bA3.elems) != len(bA1.elems) { + t.Error("Expected bA1 elems length") + } + for i := uint(0); i < bA3.bits; i++ { + expected := bA1.GetIndex(i) + if i < bA2.bits && bA2.GetIndex(i) { + expected = false + } + if bA3.GetIndex(i) != expected { + t.Error("Wrong bit from bA3") + } + } +} diff --git a/consensus/proposal.go b/consensus/proposal.go index 53b7a73e7..e2d3cdad8 100644 --- a/consensus/proposal.go +++ b/consensus/proposal.go @@ -2,6 +2,7 @@ package consensus import ( "errors" + "fmt" "io" . "github.com/tendermint/tendermint/binary" @@ -20,7 +21,7 @@ type Proposal struct { BlockPartsHash []byte POLPartsTotal uint16 POLPartsHash []byte - Signature + Signature Signature } func NewProposal(height uint32, round uint16, @@ -67,3 +68,10 @@ func (p *Proposal) GetSignature() Signature { func (p *Proposal) SetSignature(sig Signature) { p.Signature = sig } + +func (p *Proposal) String() string { + return fmt.Sprintf("Proposal{%v/%v %X/%v %X/%v %v}", p.Height, p.Round, + p.BlockPartsHash, p.BlockPartsTotal, + p.POLPartsHash, p.POLPartsTotal, + p.Signature) +} diff --git a/consensus/reactor.go b/consensus/reactor.go index cca42a09b..a015eb7de 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -183,6 +183,8 @@ func (conR *ConsensusReactor) Receive(chId byte, peer *p2p.Peer, msgBytes []byte voteAddCounter := 0 var err error = nil + log.Debug("[%X][%v] Receive: %v", chId, peer, msg_) + switch chId { case StateCh: switch msg_.(type) { @@ -351,9 +353,10 @@ ACTION_LOOP: broadcastNewRoundStep := func(step RoundStep) { // Broadcast NewRoundStepMessage msg := &NewRoundStepMessage{ - Height: height, - Round: round, - Step: step, + Height: height, + Round: round, + Step: step, + NumValidators: uint32(rs.Validators.Size()), SecondsSinceStartTime: uint32(rs.RoundElapsed().Seconds()), } conR.sw.Broadcast(StateCh, msg) @@ -512,17 +515,19 @@ OUTER_LOOP: } // Send proposal POL part? - if index, ok := rs.ProposalPOLPartSet.BitArray().Sub( - prs.ProposalPOLBitArray).PickRandom(); ok { - msg := &PartMessage{ - Height: rs.Height, - Round: rs.Round, - Type: partTypeProposalPOL, - Part: rs.ProposalPOLPartSet.GetPart(uint16(index)), + if rs.ProposalPOLPartSet != nil { + if index, ok := rs.ProposalPOLPartSet.BitArray().Sub( + prs.ProposalPOLBitArray).PickRandom(); ok { + msg := &PartMessage{ + Height: rs.Height, + Round: rs.Round, + Type: partTypeProposalPOL, + Part: rs.ProposalPOLPartSet.GetPart(uint16(index)), + } + peer.Send(DataCh, msg) + ps.SetHasProposalPOLPart(rs.Height, rs.Round, uint16(index)) + continue OUTER_LOOP } - peer.Send(DataCh, msg) - ps.SetHasProposalPOLPart(rs.Height, rs.Round, uint16(index)) - continue OUTER_LOOP } // Nothing to do. Sleep. @@ -708,15 +713,17 @@ func (ps *PeerState) ApplyNewRoundStepMessage(msg *NewRoundStepMessage) error { ps.StartTime = startTime // Reset the rest - ps.Proposal = false - ps.ProposalBlockHash = nil - ps.ProposalBlockBitArray = BitArray{} - ps.ProposalPOLHash = nil - ps.ProposalPOLBitArray = BitArray{} - ps.Prevotes = BitArray{} - ps.Precommits = BitArray{} + if ps.Round != msg.Round { + ps.Proposal = false + ps.ProposalBlockHash = nil + ps.ProposalBlockBitArray = BitArray{} + ps.ProposalPOLHash = nil + ps.ProposalPOLBitArray = BitArray{} + ps.Prevotes = NewBitArray(uint(msg.NumValidators)) + ps.Precommits = NewBitArray(uint(msg.NumValidators)) + } if ps.Height != msg.Height { - ps.Commits = BitArray{} + ps.Commits = NewBitArray(uint(msg.NumValidators)) } return nil } @@ -782,14 +789,16 @@ type NewRoundStepMessage struct { Height uint32 Round uint16 Step RoundStep + NumValidators uint32 SecondsSinceStartTime uint32 } func readNewRoundStepMessage(r io.Reader, n *int64, err *error) *NewRoundStepMessage { return &NewRoundStepMessage{ - Height: ReadUInt32(r, n, err), - Round: ReadUInt16(r, n, err), - Step: RoundStep(ReadUInt8(r, n, err)), + Height: ReadUInt32(r, n, err), + Round: ReadUInt16(r, n, err), + Step: RoundStep(ReadUInt8(r, n, err)), + NumValidators: ReadUInt32(r, n, err), SecondsSinceStartTime: ReadUInt32(r, n, err), } } @@ -799,6 +808,7 @@ func (m *NewRoundStepMessage) WriteTo(w io.Writer) (n int64, err error) { WriteUInt32(w, m.Height, &n, &err) WriteUInt16(w, m.Round, &n, &err) WriteUInt8(w, uint8(m.Step), &n, &err) + WriteUInt32(w, m.NumValidators, &n, &err) WriteUInt32(w, m.SecondsSinceStartTime, &n, &err) return } diff --git a/p2p/connection.go b/p2p/connection.go index 352d2e42b..dfaf0e724 100644 --- a/p2p/connection.go +++ b/p2p/connection.go @@ -127,7 +127,7 @@ func (c *MConnection) Stop() { } func (c *MConnection) String() string { - return fmt.Sprintf("/%v/", c.conn.RemoteAddr()) + return fmt.Sprintf("MConn{%v}", c.conn.RemoteAddr()) } func (c *MConnection) flush() { @@ -163,6 +163,8 @@ func (c *MConnection) Send(chId byte, msg Binary) bool { return false } + log.Debug("[%X][%v] Send: %v", chId, c, msg) + // Send message to channel. channel, ok := c.channelsIdx[chId] if !ok { @@ -188,6 +190,8 @@ func (c *MConnection) TrySend(chId byte, msg Binary) bool { return false } + log.Debug("[%X][%v] TrySend: %v", chId, c, msg) + // Send message to channel. channel, ok := c.channelsIdx[chId] if !ok { @@ -312,7 +316,7 @@ func (c *MConnection) sendPacket() bool { if leastChannel == nil { return true } else { - log.Debug("Found a packet to send") + // log.Debug("Found a packet to send") } // Make & send a packet from this channel @@ -553,7 +557,7 @@ func (p packet) WriteTo(w io.Writer) (n int64, err error) { } func (p packet) String() string { - return fmt.Sprintf("%X:%X", p.ChannelId, p.Bytes) + return fmt.Sprintf("Packet{%X:%X}", p.ChannelId, p.Bytes) } func readPacketSafe(r io.Reader) (pkt packet, n int64, err error) { @@ -580,7 +584,7 @@ func (tm TypedMessage) WriteTo(w io.Writer) (n int64, err error) { } func (tm TypedMessage) String() string { - return fmt.Sprintf("<%X:%v>", tm.Type, tm.Msg) + return fmt.Sprintf("TMsg{%X:%v}", tm.Type, tm.Msg) } func (tm TypedMessage) Bytes() []byte { diff --git a/p2p/peer.go b/p2p/peer.go index 1f39cd7b5..be0608cf3 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -100,9 +100,9 @@ func (p *Peer) WriteTo(w io.Writer) (n int64, err error) { func (p *Peer) String() string { if p.outbound { - return fmt.Sprintf("P(->%v)", p.mconn) + return fmt.Sprintf("Peer{->%v}", p.mconn) } else { - return fmt.Sprintf("P(%v->)", p.mconn) + return fmt.Sprintf("Peer{%v->}", p.mconn) } } diff --git a/p2p/switch.go b/p2p/switch.go index e6ae384c1..6242a89e8 100644 --- a/p2p/switch.go +++ b/p2p/switch.go @@ -173,7 +173,7 @@ func (sw *Switch) Broadcast(chId byte, msg Binary) (numSuccess, numFailure int) log.Debug("[%X] Broadcast: %v", chId, msg) for _, peer := range sw.peers.List() { success := peer.TrySend(chId, msg) - log.Debug("Broadcast for peer %v success: %v", peer, success) + // log.Debug("Broadcast for peer %v success: %v", peer, success) if success { numSuccess += 1 } else { diff --git a/tendermintd.go b/tendermintd.go index 58528a724..408cf093c 100644 --- a/tendermintd.go +++ b/tendermintd.go @@ -35,11 +35,12 @@ func NewNode() *Node { state := state_.LoadState(stateDB) if state == nil { state = state_.GenesisStateFromFile(stateDB, config.RootDir+"/genesis.json") + state.Save() } // Get PrivAccount var privValidator *consensus.PrivValidator - if _, err := os.Stat(config.RootDir + "/private.json"); os.IsExist(err) { + if _, err := os.Stat(config.RootDir + "/private.json"); err == nil { privAccount := state_.PrivAccountFromFile(config.RootDir + "/private.json") privValidatorDB := db_.NewMemDB() // TODO configurable db. privValidator = consensus.NewPrivValidator(privValidatorDB, privAccount)