diff --git a/blscosi/protocol/protocol.go b/blscosi/protocol/protocol.go index 3d505ee00..8b7e740e0 100644 --- a/blscosi/protocol/protocol.go +++ b/blscosi/protocol/protocol.go @@ -104,9 +104,7 @@ func DefaultSubLeaders(nodes int) int { if nodes == 1 { return 1 } - // As `math.Pow` calculates `9 ** (1/2) < 3`, - // we add 0.0001 for the rounding error. - return int(math.Pow(float64(nodes-1), 1.0/2.0) + 0.0001) + return int(math.Pow(float64(nodes-1), 1.0/2.0)) } // NewBlsCosi method is used to define the blscosi protocol. diff --git a/blscosi/protocol/sub_protocol.go b/blscosi/protocol/sub_protocol.go index 8a3eea761..a0ed1642d 100644 --- a/blscosi/protocol/sub_protocol.go +++ b/blscosi/protocol/sub_protocol.go @@ -4,6 +4,7 @@ import ( "crypto/rand" "errors" "fmt" + "golang.org/x/xerrors" "sync" "time" @@ -207,8 +208,7 @@ func (p *SubBlsCosi) dispatchRoot() error { case err := <-subLeaderActive: if err != nil { p.subleaderNotResponding <- true - log.Warnf("Couldn't contact subleader: %v", err) - return nil + return xerrors.Errorf("Couldn't contact subleader: %v", err) } case <-p.closeChan: return nil @@ -245,7 +245,17 @@ func (p *SubBlsCosi) dispatchSubLeader() error { return err } - p.sendToChildren(a) + if len(p.Children()) > 0 { + for _, node := range p.Children() { + go func(node *onet.TreeNode) { + err := p.SendTo(node, a) + if err != nil { + log.Warnf("Error while sending to leaf %s: %v", + node.Name(), err) + } + }(node) + } + } responses := make(ResponseMap) for _, c := range p.Children() { @@ -447,16 +457,3 @@ func (p *SubBlsCosi) checkIntegrity() error { return nil } - -// sendToChildren does not collect error messages, -// but doesn't block on nodes with a non-rejecting firewall in front of them. -func (p *SubBlsCosi) sendToChildren(msg interface{}) { - for _, c := range p.Children() { - go func(tn *onet.TreeNode) { - err := p.SendTo(tn, msg) - if err != nil { - log.Warnf("Error while sending to children: %v", err) - } - }(c) - } -} diff --git a/byzcoinx/byzcoinx_test.go b/byzcoinx/byzcoinx_test.go index 5263e9007..8a45e0df0 100644 --- a/byzcoinx/byzcoinx_test.go +++ b/byzcoinx/byzcoinx_test.go @@ -200,7 +200,7 @@ func runProtocol(t *testing.T, nbrHosts int, nbrFault int, refuseIndex int, prot log.Lvl3("Added counter", counters.size()-1, refuseIndex) require.True(t, int(math.Pow(float64(bftCosiProto.nSubtrees), - 3.0)) <= nbrHosts) + 2.0)) <= nbrHosts) // kill the leafs first nbrFault = min(nbrFault, len(servers)) diff --git a/messaging/propagate.go b/messaging/propagate.go index d53afc6ab..1f9b65da8 100644 --- a/messaging/propagate.go +++ b/messaging/propagate.go @@ -172,6 +172,7 @@ func (p *Propagate) Dispatch() error { var gotSendData bool var errs []error subtreeCount := p.TreeNode().SubtreeCount() + errsChan := make(chan error, subtreeCount) for process { p.Lock() @@ -207,7 +208,19 @@ func (p *Propagate) Dispatch() error { process = false } log.Lvl3(p.ServerIdentity(), "Sending to children", p.Children()) - p.sendToChildren(&msg.PropagateSendData) + + // Just blindly send to the children - we don't care if they receive it or + // not. If they don't receive it, they will complain later. + for _, c := range p.Children() { + go func(tn *onet.TreeNode) { + err := p.SendTo(tn, &msg.PropagateSendData) + if err != nil { + log.Warnf("Error while sending to child %s: %v", + tn.Name(), err) + errsChan <- err + } + }(c) + } case <-p.ChannelReply: if !gotSendData { log.Error("got response before send") @@ -220,6 +233,11 @@ func (p *Propagate) Dispatch() error { return err } } + errsChan <- nil + case err := <-errsChan: + if err != nil { + errs = append(errs, err) + } // Only wait for the number of children that successfully received our message. if received == subtreeCount-len(errs) && received >= subtreeCount-p.allowedFailures { process = false @@ -265,16 +283,3 @@ func (p *Propagate) Shutdown() error { close(p.closing) return nil } - -// sendToChildren does not collect error messages, -// but doesn't block on nodes with a non-rejecting firewall in front of them. -func (p *Propagate) sendToChildren(msg interface{}) { - for _, c := range p.Children() { - go func(tn *onet.TreeNode) { - err := p.SendTo(tn, msg) - if err != nil { - log.Warnf("Error while sending to children: %v", err) - } - }(c) - } -}