Browse Source

BitArray sub fix

pull/9/head
Jae Kwon 10 years ago
parent
commit
c3fc1a39ea
9 changed files with 112 additions and 42 deletions
  1. +3
    -3
      blocks/tx.go
  2. +26
    -2
      common/bit_array.go
  3. +27
    -4
      common/bit_array_test.go
  4. +9
    -1
      consensus/proposal.go
  5. +34
    -24
      consensus/reactor.go
  6. +8
    -4
      p2p/connection.go
  7. +2
    -2
      p2p/peer.go
  8. +1
    -1
      p2p/switch.go
  9. +2
    -1
      tendermintd.go

+ 3
- 3
blocks/tx.go View File

@ -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 {


+ 26
- 2
common/bit_array.go View File

@ -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)


+ 27
- 4
common/bit_array_test.go View File

@ -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")
}
}
}

+ 9
- 1
consensus/proposal.go View File

@ -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)
}

+ 34
- 24
consensus/reactor.go View File

@ -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
}


+ 8
- 4
p2p/connection.go View File

@ -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 {


+ 2
- 2
p2p/peer.go View File

@ -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)
}
}


+ 1
- 1
p2p/switch.go View File

@ -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 {


+ 2
- 1
tendermintd.go View File

@ -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)


Loading…
Cancel
Save