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 { type BaseTx struct {
Sequence uint
Fee uint64
Signature
Sequence uint
Fee uint64
Signature Signature
} }
func ReadBaseTx(r io.Reader, n *int64, err *error) BaseTx { 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 // NOTE: behavior is undefined if i >= bA.bits
func (bA BitArray) GetIndex(i uint) bool { func (bA BitArray) GetIndex(i uint) bool {
if i >= bA.bits {
return false
}
return bA.elems[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 // 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 { if v {
bA.elems[i/64] |= uint64(1 << (i % 64)) bA.elems[i/64] |= uint64(1 << (i % 64))
} else { } else {
bA.elems[i/64] &= ^uint64(1 << (i % 64)) bA.elems[i/64] &= ^uint64(1 << (i % 64))
} }
return true
} }
func (bA BitArray) Copy() BitArray { func (bA BitArray) Copy() BitArray {
@ -107,11 +114,28 @@ func (bA BitArray) Not() BitArray {
} }
func (bA BitArray) Sub(o BitArray) 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) { func (bA BitArray) PickRandom() (int, bool) {
length := len(bA.elems) length := len(bA.elems)
if length == 0 {
return 0, false
}
randElemStart := rand.Intn(length) randElemStart := rand.Intn(length)
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
elemIdx := ((i + randElemStart) % length) 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) bA1, _ := randBitArray(31)
bA2, _ := randBitArray(51) bA2, _ := randBitArray(51)
bA3 := bA1.Sub(bA2) 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) { 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++ { for i := uint(0); i < bA3.bits; i++ {
expected := bA1.GetIndex(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 ( import (
"errors" "errors"
"fmt"
"io" "io"
. "github.com/tendermint/tendermint/binary" . "github.com/tendermint/tendermint/binary"
@ -20,7 +21,7 @@ type Proposal struct {
BlockPartsHash []byte BlockPartsHash []byte
POLPartsTotal uint16 POLPartsTotal uint16
POLPartsHash []byte POLPartsHash []byte
Signature
Signature Signature
} }
func NewProposal(height uint32, round uint16, func NewProposal(height uint32, round uint16,
@ -67,3 +68,10 @@ func (p *Proposal) GetSignature() Signature {
func (p *Proposal) SetSignature(sig Signature) { func (p *Proposal) SetSignature(sig Signature) {
p.Signature = sig 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 voteAddCounter := 0
var err error = nil var err error = nil
log.Debug("[%X][%v] Receive: %v", chId, peer, msg_)
switch chId { switch chId {
case StateCh: case StateCh:
switch msg_.(type) { switch msg_.(type) {
@ -351,9 +353,10 @@ ACTION_LOOP:
broadcastNewRoundStep := func(step RoundStep) { broadcastNewRoundStep := func(step RoundStep) {
// Broadcast NewRoundStepMessage // Broadcast NewRoundStepMessage
msg := &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()), SecondsSinceStartTime: uint32(rs.RoundElapsed().Seconds()),
} }
conR.sw.Broadcast(StateCh, msg) conR.sw.Broadcast(StateCh, msg)
@ -512,17 +515,19 @@ OUTER_LOOP:
} }
// Send proposal POL part? // 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. // Nothing to do. Sleep.
@ -708,15 +713,17 @@ func (ps *PeerState) ApplyNewRoundStepMessage(msg *NewRoundStepMessage) error {
ps.StartTime = startTime ps.StartTime = startTime
// Reset the rest // 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 { if ps.Height != msg.Height {
ps.Commits = BitArray{}
ps.Commits = NewBitArray(uint(msg.NumValidators))
} }
return nil return nil
} }
@ -782,14 +789,16 @@ type NewRoundStepMessage struct {
Height uint32 Height uint32
Round uint16 Round uint16
Step RoundStep Step RoundStep
NumValidators uint32
SecondsSinceStartTime uint32 SecondsSinceStartTime uint32
} }
func readNewRoundStepMessage(r io.Reader, n *int64, err *error) *NewRoundStepMessage { func readNewRoundStepMessage(r io.Reader, n *int64, err *error) *NewRoundStepMessage {
return &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), 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) WriteUInt32(w, m.Height, &n, &err)
WriteUInt16(w, m.Round, &n, &err) WriteUInt16(w, m.Round, &n, &err)
WriteUInt8(w, uint8(m.Step), &n, &err) WriteUInt8(w, uint8(m.Step), &n, &err)
WriteUInt32(w, m.NumValidators, &n, &err)
WriteUInt32(w, m.SecondsSinceStartTime, &n, &err) WriteUInt32(w, m.SecondsSinceStartTime, &n, &err)
return return
} }


+ 8
- 4
p2p/connection.go View File

@ -127,7 +127,7 @@ func (c *MConnection) Stop() {
} }
func (c *MConnection) String() string { func (c *MConnection) String() string {
return fmt.Sprintf("/%v/", c.conn.RemoteAddr())
return fmt.Sprintf("MConn{%v}", c.conn.RemoteAddr())
} }
func (c *MConnection) flush() { func (c *MConnection) flush() {
@ -163,6 +163,8 @@ func (c *MConnection) Send(chId byte, msg Binary) bool {
return false return false
} }
log.Debug("[%X][%v] Send: %v", chId, c, msg)
// Send message to channel. // Send message to channel.
channel, ok := c.channelsIdx[chId] channel, ok := c.channelsIdx[chId]
if !ok { if !ok {
@ -188,6 +190,8 @@ func (c *MConnection) TrySend(chId byte, msg Binary) bool {
return false return false
} }
log.Debug("[%X][%v] TrySend: %v", chId, c, msg)
// Send message to channel. // Send message to channel.
channel, ok := c.channelsIdx[chId] channel, ok := c.channelsIdx[chId]
if !ok { if !ok {
@ -312,7 +316,7 @@ func (c *MConnection) sendPacket() bool {
if leastChannel == nil { if leastChannel == nil {
return true return true
} else { } else {
log.Debug("Found a packet to send")
// log.Debug("Found a packet to send")
} }
// Make & send a packet from this channel // 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 { 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) { 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 { 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 { 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 { func (p *Peer) String() string {
if p.outbound { if p.outbound {
return fmt.Sprintf("P(->%v)", p.mconn)
return fmt.Sprintf("Peer{->%v}", p.mconn)
} else { } 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) log.Debug("[%X] Broadcast: %v", chId, msg)
for _, peer := range sw.peers.List() { for _, peer := range sw.peers.List() {
success := peer.TrySend(chId, msg) 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 { if success {
numSuccess += 1 numSuccess += 1
} else { } else {


+ 2
- 1
tendermintd.go View File

@ -35,11 +35,12 @@ func NewNode() *Node {
state := state_.LoadState(stateDB) state := state_.LoadState(stateDB)
if state == nil { if state == nil {
state = state_.GenesisStateFromFile(stateDB, config.RootDir+"/genesis.json") state = state_.GenesisStateFromFile(stateDB, config.RootDir+"/genesis.json")
state.Save()
} }
// Get PrivAccount // Get PrivAccount
var privValidator *consensus.PrivValidator 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") privAccount := state_.PrivAccountFromFile(config.RootDir + "/private.json")
privValidatorDB := db_.NewMemDB() // TODO configurable db. privValidatorDB := db_.NewMemDB() // TODO configurable db.
privValidator = consensus.NewPrivValidator(privValidatorDB, privAccount) privValidator = consensus.NewPrivValidator(privValidatorDB, privAccount)


Loading…
Cancel
Save